From cf411f8d4746f16d3cd09c07992c6075e76b3ed3 Mon Sep 17 00:00:00 2001 From: Lukas Rusak Date: Wed, 3 Feb 2016 11:44:21 +0100 Subject: [PATCH] libnfs: update to 1.10 --- packages/network/libnfs/package.mk | 2 +- .../libnfs/patches/libnfs-master.patch | 1262 ----------------- 2 files changed, 1 insertion(+), 1263 deletions(-) delete mode 100644 packages/network/libnfs/patches/libnfs-master.patch diff --git a/packages/network/libnfs/package.mk b/packages/network/libnfs/package.mk index 89ea969252..7916daf318 100644 --- a/packages/network/libnfs/package.mk +++ b/packages/network/libnfs/package.mk @@ -17,7 +17,7 @@ ################################################################################ PKG_NAME="libnfs" -PKG_VERSION="1.9.8" +PKG_VERSION="1.10.0" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/network/libnfs/patches/libnfs-master.patch b/packages/network/libnfs/patches/libnfs-master.patch deleted file mode 100644 index a11f6cb4a7..0000000000 --- a/packages/network/libnfs/patches/libnfs-master.patch +++ /dev/null @@ -1,1262 +0,0 @@ -From b319b976dc9d02c894daed35a8bd056ca56b1328 Mon Sep 17 00:00:00 2001 -From: Peter Lieven -Date: Tue, 4 Aug 2015 14:55:28 +0200 -Subject: [PATCH 02/22] socket: handle count == 0 in rpc_read_from_socket - -An EOF is signalled through a POLLIN event and subsequen recvs return -always 0. Handle this condition and reconnect. Otherwise we might -deadlock here. - -Signed-off-by: Peter Lieven ---- - lib/socket.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/lib/socket.c b/lib/socket.c -index 3937e2f..9de580e 100644 ---- a/lib/socket.c -+++ b/lib/socket.c -@@ -249,6 +249,12 @@ static int rpc_read_from_socket(struct rpc_context *rpc) - rpc_set_error(rpc, "Read from socket failed, errno:%d. Closing socket.", errno); - return -1; - } -+ -+ if (count == 0) { -+ /* remote side has closed the socket. Reconnect. */ -+ return -1; -+ } -+ - rpc->inpos += count; - - while (rpc->inpos >= 4) { - -From aacee393caf013ead4e76906b881e77b229109bd Mon Sep 17 00:00:00 2001 -From: Peter Lieven -Date: Thu, 6 Aug 2015 09:53:49 +0200 -Subject: [PATCH 03/22] socket: also reconnect on write errors - -This also return -1 for rpc_service if rpc_reconnect_requeue fails. - -Signed-off-by: Peter Lieven ---- - lib/socket.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/lib/socket.c b/lib/socket.c -index 9de580e..f0ba682 100644 ---- a/lib/socket.c -+++ b/lib/socket.c -@@ -345,15 +345,13 @@ int rpc_service(struct rpc_context *rpc, int revents) - - if (revents & POLLIN) { - if (rpc_read_from_socket(rpc) != 0) { -- rpc_reconnect_requeue(rpc); -- return 0; -+ return rpc_reconnect_requeue(rpc); - } - } - - if (revents & POLLOUT && rpc_has_queue(&rpc->outqueue)) { - if (rpc_write_to_socket(rpc) != 0) { -- rpc_set_error(rpc, "write to socket failed"); -- return -1; -+ return rpc_reconnect_requeue(rpc); - } - } - - -From 29ab169d2bf29b8f9487d070571c1c751aa2567e Mon Sep 17 00:00:00 2001 -From: Peter Lieven -Date: Thu, 6 Aug 2015 10:10:45 +0200 -Subject: [PATCH 04/22] init: do not write to stderr in rpc_set_error - -only log error if debug >= 1. - -Signed-off-by: Peter Lieven ---- - lib/init.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/lib/init.c b/lib/init.c -index b898c39..874b027 100644 ---- a/lib/init.c -+++ b/lib/init.c -@@ -168,7 +168,7 @@ void rpc_set_error(struct rpc_context *rpc, const char *error_string, ...) - vsnprintf(rpc->error_string, 1024, error_string, ap); - va_end(ap); - -- fprintf(stderr, "libnfs error: %s\n", rpc->error_string); -+ RPC_LOG(rpc, 1, "error: %s", rpc->error_string); - - if (old_error_string != NULL) { - free(old_error_string); - -From 5c7a0f04e68e9c186ede5ee11e1944e66f85c528 Mon Sep 17 00:00:00 2001 -From: Peter Lieven -Date: Fri, 28 Aug 2015 21:13:37 +0200 -Subject: [PATCH 06/22] socket: fix deadlock in rpc_reconnect_requeue - -the requeueing code is broken because we access pdu->next -after we mangled it in rpc_return_to_queue. - -This leads to losing of waitqueue elements and more severe -a deadlock as soon as more than one waitpdu queue has elements. - -Reason for that is that the first elements of the first -two queues are linked to each other. - -Example: -waitpdu[0]->head = pduA ; pduA->next = pduB; pduB->next = NULL; -waitpdu[1]->head = pduC ; pduC->next = NULL; -outqueue->head = NULL; - -After the for loop for waitpdu[0] queue the outqueue looks like - -outqueue->head = pduA; pduA->next = NULL; - -At this point pduB is lost! - -In the for loop for waitpdu[1] queue the outqueue looks like this -after the first iteration: - -outqueue->head = pduC; pduC->next = pduA; pduA->next = NULL; - -We now fetch pdu->next of pduC which is pduA. - -In the next iteration we put pduA in front of pduC. pduA->next -is then pduC and pduC->next is pduA. => Deadlock. - -Signed-off-by: Peter Lieven ---- - lib/socket.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/lib/socket.c b/lib/socket.c -index 9de580e..a9d675d 100644 ---- a/lib/socket.c -+++ b/lib/socket.c -@@ -585,7 +585,7 @@ static void reconnect_cb(struct rpc_context *rpc, int status, void *data _U_, vo - /* disconnect but do not error all PDUs, just move pdus in-flight back to the outqueue and reconnect */ - static int rpc_reconnect_requeue(struct rpc_context *rpc) - { -- struct rpc_pdu *pdu; -+ struct rpc_pdu *pdu, *next; - unsigned int i; - - assert(rpc->magic == RPC_CONTEXT_MAGIC); -@@ -606,8 +606,8 @@ static int rpc_reconnect_requeue(struct rpc_context *rpc) - */ - for (i = 0; i < HASHES; i++) { - struct rpc_queue *q = &rpc->waitpdu[i]; -- -- for (pdu=q->head; pdu; pdu=pdu->next) { -+ for (pdu = q->head; pdu; pdu = next) { -+ next = pdu->next; - rpc_return_to_queue(&rpc->outqueue, pdu); - /* we have to re-send the whole pdu again */ - pdu->written = 0; - -From c078a42353fbc3f182256b62af80e185034de337 Mon Sep 17 00:00:00 2001 -From: Ronnie Sahlberg -Date: Sun, 6 Sep 2015 06:50:22 -0700 -Subject: [PATCH 07/22] Fix OSX build. - -Signed-off-by: Ronnie Sahlberg ---- - utils/nfs-cp.c | 6 +++--- - utils/nfs-ls.c | 3 ++- - 2 files changed, 5 insertions(+), 4 deletions(-) - -diff --git a/utils/nfs-cp.c b/utils/nfs-cp.c -index d862e46..582fe3c 100644 ---- a/utils/nfs-cp.c -+++ b/utils/nfs-cp.c -@@ -104,9 +104,9 @@ fstat_file(struct file_context *fc, struct stat *st) - st->st_size = nfs_st.nfs_size; - st->st_blksize = nfs_st.nfs_blksize; - st->st_blocks = nfs_st.nfs_blocks; -- st->st_atim.tv_sec = nfs_st.nfs_atime; -- st->st_mtim.tv_sec = nfs_st.nfs_mtime; -- st->st_ctim.tv_sec = nfs_st.nfs_ctime; -+ st->st_atime = nfs_st.nfs_atime; -+ st->st_mtime = nfs_st.nfs_mtime; -+ st->st_ctime = nfs_st.nfs_ctime; - - return res; - } -diff --git a/utils/nfs-ls.c b/utils/nfs-ls.c -index a989891..a854dfc 100644 ---- a/utils/nfs-ls.c -+++ b/utils/nfs-ls.c -@@ -255,7 +255,8 @@ int main(int argc, char *argv[]) - goto finished; - } - printf("\n%12" PRId64 " of %12" PRId64 " bytes free.\n", -- stvfs.f_frsize * stvfs.f_bfree, stvfs.f_frsize * stvfs.f_blocks); -+ (uint64_t)(stvfs.f_frsize * stvfs.f_bfree), -+ (uint64_t)(stvfs.f_frsize * stvfs.f_blocks)); - } - - ret = 0; - -From e81f9e23ab220d7770523d0ec559d74ad5eab4c4 Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Fri, 11 Sep 2015 00:22:07 +0200 -Subject: [PATCH 08/22] fuse_nfs: Consider st_.tim as struct timespec - -At least in my version of glibc the members st_mtim, st_ctim and st_atim -are defined as struct timespec rather than struct timeval, thus -containing a tv_nsec field rather than tv_usec. - -Use the proper struct fields instead, fixing compilation on Linux. - -Signed-off-by: Alexander Graf ---- - examples/fuse_nfs.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -index 635cca1..fd4b8ee 100644 ---- a/examples/fuse_nfs.c -+++ b/examples/fuse_nfs.c -@@ -51,11 +51,11 @@ static int fuse_nfs_getattr(const char *path, struct stat *stbuf) - stbuf->st_blksize = nfs_st.nfs_blksize; - stbuf->st_blocks = nfs_st.nfs_blocks; - stbuf->st_atim.tv_sec = nfs_st.nfs_atime; -- stbuf->st_atim.tv_usec = nfs_st.nfs_atime_nsec / 1000; -+ stbuf->st_atim.tv_nsec = nfs_st.nfs_atime_nsec; - stbuf->st_mtim.tv_sec = nfs_st.nfs_mtime; -- stbuf->st_mtim.tv_usec = nfs_st.nfs_mtime_nsec / 1000; -+ stbuf->st_mtim.tv_nsec = nfs_st.nfs_mtime_nsec; - stbuf->st_ctim.tv_sec = nfs_st.nfs_ctime; -- stbuf->st_ctim.tv_usec = nfs_st.nfs_ctime_nsec / 1000; -+ stbuf->st_ctim.tv_nsec = nfs_st.nfs_ctime_nsec; - - return ret; - } - -From 39d1f3693cdb3d779f2a39286daf3a3f0d327bbd Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Fri, 11 Sep 2015 00:23:46 +0200 -Subject: [PATCH 09/22] fuse_nfs: Add symlink support - -The fuse framework allows us to directly expose symlinks from NFS to the user, -just like a real NFS mount would. All we need to do is call lstat rather -than stat and implement a readlink function. - -With this patch I can successfully chroot into a rootfs mounted using -fuse_nfs. - -Signed-off-by: Alexander Graf ---- - examples/fuse_nfs.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -index fd4b8ee..5d82b69 100644 ---- a/examples/fuse_nfs.c -+++ b/examples/fuse_nfs.c -@@ -38,7 +38,7 @@ static int fuse_nfs_getattr(const char *path, struct stat *stbuf) - int ret = 0; - struct nfs_stat_64 nfs_st; - -- ret = nfs_stat64(nfs, path, &nfs_st); -+ ret = nfs_lstat64(nfs, path, &nfs_st); - - stbuf->st_dev = nfs_st.nfs_dev; - stbuf->st_ino = nfs_st.nfs_ino; -@@ -79,6 +79,11 @@ static int fuse_nfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, - return ret; - } - -+static int fuse_nfs_readlink(const char *path, char *buf, size_t size) -+{ -+ return nfs_readlink(nfs, path, buf, size); -+} -+ - static int fuse_nfs_open(const char *path, struct fuse_file_info *fi) - { - int ret = 0; -@@ -199,6 +204,7 @@ static struct fuse_operations nfs_oper = { - .open = fuse_nfs_open, - .read = fuse_nfs_read, - .readdir = fuse_nfs_readdir, -+ .readlink = fuse_nfs_readlink, - .release = fuse_nfs_release, - .rmdir = fuse_nfs_rmdir, - .unlink = fuse_nfs_unlink, - -From 618b6ea03057da666319ff346382f353ff6641b3 Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Fri, 11 Sep 2015 11:19:50 +0200 -Subject: [PATCH 10/22] fuse_nfs: Add mknod - -Libnfs already has exports for mknod, hook them up to the fuse example. - -Signed-off-by: Alexander Graf ---- - examples/fuse_nfs.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -index 5d82b69..3c0e553 100644 ---- a/examples/fuse_nfs.c -+++ b/examples/fuse_nfs.c -@@ -197,10 +197,16 @@ static int fuse_nfs_mkdir(const char *path, mode_t mode) - return ret; - } - -+static int fuse_nfs_mknod(const char *path, mode_t mode, dev_t rdev) -+{ -+ return nfs_mknod(nfs, path, mode, rdev); -+} -+ - static struct fuse_operations nfs_oper = { - .create = fuse_nfs_create, - .getattr = fuse_nfs_getattr, - .mkdir = fuse_nfs_mkdir, -+ .mknod = fuse_nfs_mknod, - .open = fuse_nfs_open, - .read = fuse_nfs_read, - .readdir = fuse_nfs_readdir, - -From 50aabd0729e9e443bf61dbd550e48f4d23fba26e Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Fri, 11 Sep 2015 11:20:42 +0200 -Subject: [PATCH 11/22] fuse_nfs: Add symlink - -Libnfs already has exports for symlink, hook them up to the fuse example. - -Signed-off-by: Alexander Graf ---- - examples/fuse_nfs.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -index 3c0e553..759f35b 100644 ---- a/examples/fuse_nfs.c -+++ b/examples/fuse_nfs.c -@@ -202,6 +202,11 @@ static int fuse_nfs_mknod(const char *path, mode_t mode, dev_t rdev) - return nfs_mknod(nfs, path, mode, rdev); - } - -+static int fuse_nfs_symlink(const char *from, const char *to) -+{ -+ return nfs_symlink(nfs, from, to); -+} -+ - static struct fuse_operations nfs_oper = { - .create = fuse_nfs_create, - .getattr = fuse_nfs_getattr, -@@ -215,6 +220,7 @@ static struct fuse_operations nfs_oper = { - .rmdir = fuse_nfs_rmdir, - .unlink = fuse_nfs_unlink, - .utime = fuse_nfs_utime, -+ .symlink = fuse_nfs_symlink, - .write = fuse_nfs_write, - }; - - -From 37fd16ee087472dbbdb7bc7c10781a7ff91a3764 Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Fri, 11 Sep 2015 11:21:30 +0200 -Subject: [PATCH 12/22] fuse_nfs: Add rename - -Libnfs already has exports for rename, hook them up to the fuse example. - -Signed-off-by: Alexander Graf ---- - examples/fuse_nfs.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -index 759f35b..647de2e 100644 ---- a/examples/fuse_nfs.c -+++ b/examples/fuse_nfs.c -@@ -207,6 +207,11 @@ static int fuse_nfs_symlink(const char *from, const char *to) - return nfs_symlink(nfs, from, to); - } - -+static int fuse_nfs_rename(const char *from, const char *to) -+{ -+ return nfs_rename(nfs, from, to); -+} -+ - static struct fuse_operations nfs_oper = { - .create = fuse_nfs_create, - .getattr = fuse_nfs_getattr, -@@ -220,6 +225,7 @@ static struct fuse_operations nfs_oper = { - .rmdir = fuse_nfs_rmdir, - .unlink = fuse_nfs_unlink, - .utime = fuse_nfs_utime, -+ .rename = fuse_nfs_rename, - .symlink = fuse_nfs_symlink, - .write = fuse_nfs_write, - }; - -From d1709ab57371080ed699667b7bed13abfca6154c Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Fri, 11 Sep 2015 11:22:27 +0200 -Subject: [PATCH 13/22] fuse_nfs: Add link - -Libnfs already has exports for link, hook them up to the fuse example. - -Signed-off-by: Alexander Graf ---- - examples/fuse_nfs.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -index 647de2e..b40fa73 100644 ---- a/examples/fuse_nfs.c -+++ b/examples/fuse_nfs.c -@@ -212,9 +212,15 @@ static int fuse_nfs_rename(const char *from, const char *to) - return nfs_rename(nfs, from, to); - } - -+static int fuse_nfs_link(const char *from, const char *to) -+{ -+ return nfs_link(nfs, from, to); -+} -+ - static struct fuse_operations nfs_oper = { - .create = fuse_nfs_create, - .getattr = fuse_nfs_getattr, -+ .link = fuse_nfs_link, - .mkdir = fuse_nfs_mkdir, - .mknod = fuse_nfs_mknod, - .open = fuse_nfs_open, - -From 315112b923cd7845ce9703e60e0c30e582e93c39 Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Fri, 11 Sep 2015 11:23:02 +0200 -Subject: [PATCH 14/22] fuse_nfs: Add chmod - -Libnfs already has exports for chmod, hook them up to the fuse example. - -Signed-off-by: Alexander Graf ---- - examples/fuse_nfs.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -index b40fa73..ad15579 100644 ---- a/examples/fuse_nfs.c -+++ b/examples/fuse_nfs.c -@@ -217,7 +217,13 @@ static int fuse_nfs_link(const char *from, const char *to) - return nfs_link(nfs, from, to); - } - -+static int fuse_nfs_chmod(const char *path, mode_t mode) -+{ -+ return nfs_chmod(nfs, path, mode); -+} -+ - static struct fuse_operations nfs_oper = { -+ .chmod = fuse_nfs_chmod, - .create = fuse_nfs_create, - .getattr = fuse_nfs_getattr, - .link = fuse_nfs_link, - -From b66121610d21e8e5187dd16691d15e159e0cfcd8 Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Fri, 11 Sep 2015 11:23:34 +0200 -Subject: [PATCH 15/22] fuse_nfs: Add chown - -Libnfs already has exports for chown, hook them up to the fuse example. - -Signed-off-by: Alexander Graf ---- - examples/fuse_nfs.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -index ad15579..d84b590 100644 ---- a/examples/fuse_nfs.c -+++ b/examples/fuse_nfs.c -@@ -222,8 +222,14 @@ static int fuse_nfs_chmod(const char *path, mode_t mode) - return nfs_chmod(nfs, path, mode); - } - -+static int fuse_nfs_chown(const char *path, uid_t uid, gid_t gid) -+{ -+ return nfs_chown(nfs, path, uid, gid); -+} -+ - static struct fuse_operations nfs_oper = { - .chmod = fuse_nfs_chmod, -+ .chown = fuse_nfs_chown, - .create = fuse_nfs_create, - .getattr = fuse_nfs_getattr, - .link = fuse_nfs_link, - -From 9439361243c7e35a2cfcb66fad21a107e5e64609 Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Fri, 11 Sep 2015 11:24:07 +0200 -Subject: [PATCH 16/22] fuse_nfs: Add truncate - -Libnfs already has exports for truncate, hook them up to the fuse example. - -Signed-off-by: Alexander Graf ---- - examples/fuse_nfs.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -index d84b590..acc8806 100644 ---- a/examples/fuse_nfs.c -+++ b/examples/fuse_nfs.c -@@ -227,6 +227,11 @@ static int fuse_nfs_chown(const char *path, uid_t uid, gid_t gid) - return nfs_chown(nfs, path, uid, gid); - } - -+static int fuse_nfs_truncate(const char *path, off_t size) -+{ -+ return nfs_truncate(nfs, path, size); -+} -+ - static struct fuse_operations nfs_oper = { - .chmod = fuse_nfs_chmod, - .chown = fuse_nfs_chown, -@@ -245,6 +250,7 @@ static struct fuse_operations nfs_oper = { - .utime = fuse_nfs_utime, - .rename = fuse_nfs_rename, - .symlink = fuse_nfs_symlink, -+ .truncate = fuse_nfs_truncate, - .write = fuse_nfs_write, - }; - - -From 883f660430f1be1f7796c275f4ae0d85101ed478 Mon Sep 17 00:00:00 2001 -From: Alexander Graf -Date: Fri, 11 Sep 2015 11:24:45 +0200 -Subject: [PATCH 17/22] fuse_nfs: Add fsync - -Libnfs already has exports for fsync, hook them up to the fuse example. - -Signed-off-by: Alexander Graf ---- - examples/fuse_nfs.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -index acc8806..5f7eb7b 100644 ---- a/examples/fuse_nfs.c -+++ b/examples/fuse_nfs.c -@@ -232,10 +232,19 @@ static int fuse_nfs_truncate(const char *path, off_t size) - return nfs_truncate(nfs, path, size); - } - -+static int fuse_nfs_fsync(const char *path, int isdatasync, -+ struct fuse_file_info *fi) -+{ -+ struct nfsfh *nfsfh = (struct nfsfh *)fi->fh; -+ -+ return nfs_fsync(nfs, nfsfh); -+} -+ - static struct fuse_operations nfs_oper = { - .chmod = fuse_nfs_chmod, - .chown = fuse_nfs_chown, - .create = fuse_nfs_create, -+ .fsync = fuse_nfs_fsync, - .getattr = fuse_nfs_getattr, - .link = fuse_nfs_link, - .mkdir = fuse_nfs_mkdir, - -From 7b7aef6b6d48c5403f939449aa0f88cd82c54c7d Mon Sep 17 00:00:00 2001 -From: Peter Lieven -Date: Tue, 22 Sep 2015 14:40:59 +0200 -Subject: [PATCH 18/22] socket: keep reconnecting if a reconnect fails - -otherwise we end up eating up all socket errors in rpc_service and then -believe we are connected, but the next call to rpc_read_from_socket -fails because the socket is closed. we then reconnect anyway. - -Signed-off-by: Peter Lieven ---- - lib/socket.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/lib/socket.c b/lib/socket.c -index d578cc2..091d195 100644 ---- a/lib/socket.c -+++ b/lib/socket.c -@@ -336,7 +336,7 @@ int rpc_service(struct rpc_context *rpc, int revents) - } - - rpc->is_connected = 1; -- RPC_LOG(rpc, 2, "connection established"); -+ RPC_LOG(rpc, 2, "connection established on fd %d", rpc->fd); - if (rpc->connect_cb != NULL) { - rpc->connect_cb(rpc, RPC_STATUS_SUCCESS, NULL, rpc->connect_data); - } -@@ -572,7 +572,8 @@ static void reconnect_cb(struct rpc_context *rpc, int status, void *data _U_, vo - assert(rpc->magic == RPC_CONTEXT_MAGIC); - - if (status != RPC_STATUS_SUCCESS) { -- rpc_error_all_pdus(rpc, "RPC ERROR: Failed to reconnect async"); -+ rpc_set_error(rpc, "Failed to reconnect async"); -+ rpc_reconnect_requeue(rpc); - return; - } - - -From ddd9e2f7e9b14248da45fbe9d02e188751206950 Mon Sep 17 00:00:00 2001 -From: Peter Lieven -Date: Tue, 22 Sep 2015 14:54:48 +0200 -Subject: [PATCH 19/22] socket: keep fd the same across reconnects - -There is no guarantee that we get the same fd again when -reestablishing a session. But if the fd changes during a -reconnect we might up with a client application busy polling -on the old fd. - -Qemu registers a read handler on the current fd, but is -not realizing fd changes. So we busy poll on the old fd for good. -Things are working (except for the busy polling) until -a drain all is issued. At this point Qemu deadlocks. - -Signed-off-by: Peter Lieven ---- - include/libnfs-private.h | 1 + - lib/socket.c | 15 ++++++++++++++- - 2 files changed, 15 insertions(+), 1 deletion(-) - -diff --git a/include/libnfs-private.h b/include/libnfs-private.h -index bc84f53..6d778c6 100644 ---- a/include/libnfs-private.h -+++ b/include/libnfs-private.h -@@ -79,6 +79,7 @@ struct rpc_queue { - struct rpc_context { - uint32_t magic; - int fd; -+ int old_fd; - int is_connected; - - char *error_string; -diff --git a/lib/socket.c b/lib/socket.c -index 091d195..b409cf6 100644 ---- a/lib/socket.c -+++ b/lib/socket.c -@@ -132,6 +132,10 @@ int rpc_get_fd(struct rpc_context *rpc) - { - assert(rpc->magic == RPC_CONTEXT_MAGIC); - -+ if (rpc->old_fd) { -+ return rpc->old_fd; -+ } -+ - return rpc->fd; - } - -@@ -418,6 +422,14 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s - return -1; - } - -+ if (rpc->old_fd) { -+ if (dup2(rpc->fd, rpc->old_fd) == -1) { -+ return -1; -+ } -+ close(rpc->fd); -+ rpc->fd = rpc->old_fd; -+ } -+ - /* Some systems allow you to set capabilities on an executable - * to allow the file to be executed with privilege to bind to - * privileged system ports, even if the user is not root. -@@ -579,6 +591,7 @@ static void reconnect_cb(struct rpc_context *rpc, int status, void *data _U_, vo - - rpc->is_connected = 1; - rpc->connect_cb = NULL; -+ rpc->old_fd = 0; - } - - /* disconnect but do not error all PDUs, just move pdus in-flight back to the outqueue and reconnect */ -@@ -590,7 +603,7 @@ static int rpc_reconnect_requeue(struct rpc_context *rpc) - assert(rpc->magic == RPC_CONTEXT_MAGIC); - - if (rpc->fd != -1) { -- close(rpc->fd); -+ rpc->old_fd = rpc->fd; - } - rpc->fd = -1; - rpc->is_connected = 0; - -From d73d4f3305aaf962635abb9f5b5233cc23dd4747 Mon Sep 17 00:00:00 2001 -From: Ronnie Sahlberg -Date: Wed, 14 Oct 2015 06:44:22 -0700 -Subject: [PATCH 20/22] rpc_reconnect_requeue: return -1 if autoreconnect is - not enabled - -This funciton is called from rpc_service when it has detected that -a socket has errored out during reading/writing. -However, since this fucntion returns 0 (==success) for the case where -autoreconnect is not enabled, this means that for an errored socket we -will return 0 (==success) from rpc_service() back to the application. - -Change rpc_reconnect_requeue to return -1 when invoked and autoreconnect -is disabled so that applications will receive an error back from rpc_service. - -Signed-off-by: Ronnie Sahlberg ---- - lib/socket.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/lib/socket.c b/lib/socket.c -index b409cf6..72ffe92 100644 ---- a/lib/socket.c -+++ b/lib/socket.c -@@ -636,6 +636,7 @@ static int rpc_reconnect_requeue(struct rpc_context *rpc) - } - } else { - RPC_LOG(rpc, 1, "reconnect NOT initiated, auto-reconnect is disabled"); -+ return -1; - } - - return 0; - -From 4d102bd24dc2b48f67db055251bf6763faeaa8a4 Mon Sep 17 00:00:00 2001 -From: Ronnie Sahlberg -Date: Wed, 14 Oct 2015 07:01:10 -0700 -Subject: [PATCH 21/22] Improve the documentation for - *_get_fd/*_which_events/*_service - -Signed-off-by: Ronnie Sahlberg ---- - include/nfsc/libnfs-raw.h | 33 +++++++++++++++++++++++++++++++-- - include/nfsc/libnfs.h | 25 ++++++++++++++++++++++++- - 2 files changed, 55 insertions(+), 3 deletions(-) - -diff --git a/include/nfsc/libnfs-raw.h b/include/nfsc/libnfs-raw.h -index 1556f54..ce88dd2 100644 ---- a/include/nfsc/libnfs-raw.h -+++ b/include/nfsc/libnfs-raw.h -@@ -40,13 +40,42 @@ void rpc_destroy_context(struct rpc_context *rpc); - - void rpc_set_auth(struct rpc_context *rpc, struct AUTH *auth); - -+/* -+ * Used for interfacing the api into an external eventsystem. -+ * -+ * rpc_get_fd() returns the file descriptor for the context we need to -+ * listen for events from. -+ * -+ * rpc_which_events() returns which events that we need to poll for. -+ * This is a combination of the POLLIN and POLLOUT flags. -+ * -+ * rpc_service() This function should be called once there are events triggered -+ * for the filedescriptor. This function takes POLLIN/POLLOUT/POLLHUP/POLLERR -+ * as arguments. -+ * This function returns 0 on success or -1 on error. If it returns -1 it -+ * means that the socket is in an unrecoverable error state (disconnected?) -+ * and that no further commands can be used. -+ * When this happens the application should destroy the now errored context -+ * re-create a new context and reconnect. -+ * -+ */ - int rpc_get_fd(struct rpc_context *rpc); - int rpc_which_events(struct rpc_context *rpc); - int rpc_service(struct rpc_context *rpc, int revents); --char *rpc_get_error(struct rpc_context *rpc); -+ -+/* -+ * Returns the number of commands in-flight. Can be used by the application -+ * to check if there are any more responses we are awaiting for the server -+ * or if the connection is completely idle. -+ */ - int rpc_queue_length(struct rpc_context *rpc); - --/* Utility function to get an RPC context from a NFS context. Useful for doing low level NFSACL -+/* -+ * When an operation failed, this function can extract a detailed error string. -+ */ -+char *rpc_get_error(struct rpc_context *rpc); -+ -+ /* Utility function to get an RPC context from a NFS context. Useful for doing low level NFSACL - * calls on a NFS context. - */ - struct rpc_context *nfs_get_rpc_context(struct nfs_context *nfs); -diff --git a/include/nfsc/libnfs.h b/include/nfsc/libnfs.h -index 356263c..55cec1d 100644 ---- a/include/nfsc/libnfs.h -+++ b/include/nfsc/libnfs.h -@@ -79,11 +79,34 @@ struct utimbuf { - #endif - - /* -- * Used for interfacing the async version of the api into an external eventsystem -+ * Used for interfacing the async version of the api into an external -+ * eventsystem. -+ * -+ * nfs_get_fd() returns the file descriptor for the context we need to -+ * listen for events from. -+ * -+ * nfs_which_events() returns which events that we need to poll for. -+ * This is a combination of the POLLIN and POLLOUT flags. -+ * -+ * nfs_service() This function should be called once there are events triggered -+ * for the filedescriptor. This function takes POLLIN/POLLOUT/POLLHUP/POLLERR -+ * as arguments. -+ * This function returns 0 on success or -1 on error. If it returns -1 it -+ * means that the socket is in an unrecoverable error state (disconnected?) -+ * and that no further commands can be used. -+ * When this happens the application should destroy the now errored context -+ * re-create a new context and reconnect. -+ * - */ - EXTERN int nfs_get_fd(struct nfs_context *nfs); - EXTERN int nfs_which_events(struct nfs_context *nfs); - EXTERN int nfs_service(struct nfs_context *nfs, int revents); -+ -+/* -+ * Returns the number of commands in-flight. Can be used by the application -+ * to check if there are any more responses we are awaiting for the server -+ * or if the connection is completely idle. -+ */ - EXTERN int nfs_queue_length(struct nfs_context *nfs); - - /* - -From dc8d86628d2f67cb4b7a9e5e5d7a1259f065b3c7 Mon Sep 17 00:00:00 2001 -From: Ronnie Sahlberg -Date: Mon, 19 Oct 2015 18:59:38 -0700 -Subject: [PATCH 22/22] Remove FUSE NFS filesystem - -Remove the fuse module from the examples subdirectory. -This module is now a standalone repo : -https://github.com/sahlberg/fuse-nfs - -And it comes with proper build rules, documentation etc etc. -It is a useful module and it has now graduated to become its own -repo. - -Signed-off-by: Ronnie Sahlberg ---- - README | 8 -- - examples/fuse_nfs.c | 397 ---------------------------------------------------- - 2 files changed, 405 deletions(-) - delete mode 100644 examples/fuse_nfs.c - -diff --git a/README b/README -index 01c0654..34715f4 100644 ---- a/README -+++ b/README -@@ -90,14 +90,6 @@ manpages by running - cd doc - make doc - --FUSE --==== --A simple FUSE filesystem built on libnfs can be found in --examples/fuse_nfs.c -- --Compile using : gcc fuse_nfs.c -o fuse_nfs -lfuse -lnfs --Mount using : sudo ./fuse_nfs -n nfs:/// -m -- - - PLATFORM support - ================= -diff --git a/examples/fuse_nfs.c b/examples/fuse_nfs.c -deleted file mode 100644 -index 5f7eb7b..0000000 ---- a/examples/fuse_nfs.c -+++ /dev/null -@@ -1,397 +0,0 @@ --/* -- Copyright (C) by Ronnie Sahlberg 2013 -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, see . --*/ --/* A FUSE filesystem based on libnfs. */ -- --#define FUSE_USE_VERSION 26 --#define _FILE_OFFSET_BITS 64 -- --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#define discard_const(ptr) ((void *)((intptr_t)(ptr))) -- --struct nfs_context *nfs = NULL; -- --static int fuse_nfs_getattr(const char *path, struct stat *stbuf) --{ -- int ret = 0; -- struct nfs_stat_64 nfs_st; -- -- ret = nfs_lstat64(nfs, path, &nfs_st); -- -- stbuf->st_dev = nfs_st.nfs_dev; -- stbuf->st_ino = nfs_st.nfs_ino; -- stbuf->st_mode = nfs_st.nfs_mode; -- stbuf->st_nlink = nfs_st.nfs_nlink; -- stbuf->st_uid = nfs_st.nfs_uid; -- stbuf->st_gid = nfs_st.nfs_gid; -- stbuf->st_rdev = nfs_st.nfs_rdev; -- stbuf->st_size = nfs_st.nfs_size; -- stbuf->st_blksize = nfs_st.nfs_blksize; -- stbuf->st_blocks = nfs_st.nfs_blocks; -- stbuf->st_atim.tv_sec = nfs_st.nfs_atime; -- stbuf->st_atim.tv_nsec = nfs_st.nfs_atime_nsec; -- stbuf->st_mtim.tv_sec = nfs_st.nfs_mtime; -- stbuf->st_mtim.tv_nsec = nfs_st.nfs_mtime_nsec; -- stbuf->st_ctim.tv_sec = nfs_st.nfs_ctime; -- stbuf->st_ctim.tv_nsec = nfs_st.nfs_ctime_nsec; -- -- return ret; --} -- --static int fuse_nfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, -- off_t offset, struct fuse_file_info *fi) --{ -- struct nfsdir *nfsdir; -- struct nfsdirent *nfsdirent; -- -- int ret = 0; -- -- ret = nfs_opendir(nfs, path, &nfsdir); -- if (ret < 0) { -- return ret; -- } -- while ((nfsdirent = nfs_readdir(nfs, nfsdir)) != NULL) { -- filler(buf, nfsdirent->name, NULL, 0); -- } -- -- return ret; --} -- --static int fuse_nfs_readlink(const char *path, char *buf, size_t size) --{ -- return nfs_readlink(nfs, path, buf, size); --} -- --static int fuse_nfs_open(const char *path, struct fuse_file_info *fi) --{ -- int ret = 0; -- struct nfsfh *nfsfh; -- -- fi->fh = 0; -- ret = nfs_open(nfs, path, fi->flags, &nfsfh); -- if (ret < 0) { -- return ret; -- } -- -- fi->fh = (uint64_t)nfsfh; -- -- return ret; --} -- --static int fuse_nfs_release(const char *path, struct fuse_file_info *fi) --{ -- struct nfsfh *nfsfh = (struct nfsfh *)fi->fh; -- -- nfs_close(nfs, nfsfh); -- return 0; --} -- --static int fuse_nfs_read(const char *path, char *buf, size_t size, -- off_t offset, struct fuse_file_info *fi) --{ -- int ret = 0; -- struct nfsfh *nfsfh = (struct nfsfh *)fi->fh; -- -- ret = nfs_pread(nfs, nfsfh, offset, size, buf); -- -- return ret; --} -- --static int fuse_nfs_write(const char *path, const char *buf, size_t size, -- off_t offset, struct fuse_file_info *fi) --{ -- int ret = 0; -- struct nfsfh *nfsfh = (struct nfsfh *)fi->fh; -- -- ret = nfs_pwrite(nfs, nfsfh, offset, size, discard_const(buf)); -- -- return ret; --} -- --static int fuse_nfs_create(const char *path, mode_t mode, struct fuse_file_info *fi) --{ -- int ret = 0; -- struct nfsfh *nfsfh; -- -- ret = nfs_creat(nfs, path, mode, &nfsfh); -- if (ret < 0) { -- return ret; -- } -- -- fi->fh = (uint64_t)nfsfh; -- -- return ret; --} -- --static int fuse_nfs_utime(const char *path, struct utimbuf *times) --{ -- int ret = 0; -- -- ret = nfs_utime(nfs, path, times); -- if (ret < 0) { -- return ret; -- } -- -- return ret; --} -- --static int fuse_nfs_unlink(const char *path) --{ -- int ret = 0; -- -- ret = nfs_unlink(nfs, path); -- if (ret < 0) { -- return ret; -- } -- -- return ret; --} -- --static int fuse_nfs_rmdir(const char *path) --{ -- int ret = 0; -- -- ret = nfs_rmdir(nfs, path); -- if (ret < 0) { -- return ret; -- } -- -- return ret; --} -- --static int fuse_nfs_mkdir(const char *path, mode_t mode) --{ -- int ret = 0; -- -- ret = nfs_mkdir(nfs, path); -- if (ret < 0) { -- return ret; -- } -- ret = nfs_chmod(nfs, path, mode); -- if (ret < 0) { -- return ret; -- } -- -- return ret; --} -- --static int fuse_nfs_mknod(const char *path, mode_t mode, dev_t rdev) --{ -- return nfs_mknod(nfs, path, mode, rdev); --} -- --static int fuse_nfs_symlink(const char *from, const char *to) --{ -- return nfs_symlink(nfs, from, to); --} -- --static int fuse_nfs_rename(const char *from, const char *to) --{ -- return nfs_rename(nfs, from, to); --} -- --static int fuse_nfs_link(const char *from, const char *to) --{ -- return nfs_link(nfs, from, to); --} -- --static int fuse_nfs_chmod(const char *path, mode_t mode) --{ -- return nfs_chmod(nfs, path, mode); --} -- --static int fuse_nfs_chown(const char *path, uid_t uid, gid_t gid) --{ -- return nfs_chown(nfs, path, uid, gid); --} -- --static int fuse_nfs_truncate(const char *path, off_t size) --{ -- return nfs_truncate(nfs, path, size); --} -- --static int fuse_nfs_fsync(const char *path, int isdatasync, -- struct fuse_file_info *fi) --{ -- struct nfsfh *nfsfh = (struct nfsfh *)fi->fh; -- -- return nfs_fsync(nfs, nfsfh); --} -- --static struct fuse_operations nfs_oper = { -- .chmod = fuse_nfs_chmod, -- .chown = fuse_nfs_chown, -- .create = fuse_nfs_create, -- .fsync = fuse_nfs_fsync, -- .getattr = fuse_nfs_getattr, -- .link = fuse_nfs_link, -- .mkdir = fuse_nfs_mkdir, -- .mknod = fuse_nfs_mknod, -- .open = fuse_nfs_open, -- .read = fuse_nfs_read, -- .readdir = fuse_nfs_readdir, -- .readlink = fuse_nfs_readlink, -- .release = fuse_nfs_release, -- .rmdir = fuse_nfs_rmdir, -- .unlink = fuse_nfs_unlink, -- .utime = fuse_nfs_utime, -- .rename = fuse_nfs_rename, -- .symlink = fuse_nfs_symlink, -- .truncate = fuse_nfs_truncate, -- .write = fuse_nfs_write, --}; -- --void print_usage(char *name) --{ -- printf("Usage: %s [-?|--help] [-n|--nfs-share=nfs-url] [-m|--mountpoint=mountpoint]\n", -- name); -- exit(0); --} -- --int main(int argc, char *argv[]) --{ -- int ret = 0; -- static struct option long_opts[] = { -- { "help", no_argument, 0, '?' }, -- { "nfs-share", required_argument, 0, 'n' }, -- { "mountpoint", required_argument, 0, 'm' }, -- { NULL, 0, 0, 0 } -- }; -- int c; -- int opt_idx = 0; -- char *url = NULL; -- char *mnt = NULL; -- char *server = NULL, *export = NULL, *strp; -- int fuse_nfs_argc = 6; -- char *fuse_nfs_argv[16] = { -- "fuse-nfs", -- "", -- "-oallow_other", -- "-odefault_permissions", -- "-omax_write=32768", -- "-s", -- NULL, -- NULL, -- NULL, -- NULL, -- NULL, -- NULL, -- NULL, -- NULL, -- NULL, -- NULL, -- }; -- -- while ((c = getopt_long(argc, argv, "?hm:n:", long_opts, -- &opt_idx)) > 0) { -- switch (c) { -- case 'h': -- case '?': -- print_usage(argv[0]); -- return 0; -- case 'm': -- mnt = strdup(optarg); -- break; -- case 'n': -- url = strdup(optarg); -- break; -- } -- } -- -- if (url == NULL) { -- fprintf(stderr, "-n was not specified.\n"); -- print_usage(argv[0]); -- ret = 10; -- goto finished; -- } -- if (mnt == NULL) { -- fprintf(stderr, "-m was not specified.\n"); -- print_usage(argv[0]); -- ret = 10; -- goto finished; -- } -- -- -- if (strncmp(url, "nfs://", 6)) { -- fprintf(stderr, "Invalid URL specified.\n"); -- ret = 10; -- goto finished; -- } -- server = strdup(url + 6); -- if (server == NULL) { -- fprintf(stderr, "Failed to strdup server string\n"); -- ret = 10; -- goto finished; -- } -- if (server[0] == '/' || server[0] == '\0') { -- fprintf(stderr, "Invalid server string.\n"); -- ret = 10; -- goto finished; -- } -- strp = strchr(server, '/'); -- if (strp == NULL) { -- fprintf(stderr, "Invalid URL specified.\n"); -- ret = 10; -- goto finished; -- } -- export = strdup(strp); -- if (export == NULL) { -- fprintf(stderr, "Failed to strdup server string\n"); -- ret = 10; -- goto finished; -- } -- if (export[0] != '/') { -- fprintf(stderr, "Invalid export.\n"); -- ret = 10; -- goto finished; -- } -- *strp = 0; -- -- nfs = nfs_init_context(); -- if (nfs == NULL) { -- printf("failed to init context\n"); -- goto finished; -- } -- -- ret = nfs_mount(nfs, server, export); -- if (ret != 0) { -- printf("Failed to mount nfs share : %s\n", nfs_get_error(nfs)); -- goto finished; -- } -- -- -- fuse_nfs_argv[1] = mnt; -- return fuse_main(fuse_nfs_argc, fuse_nfs_argv, &nfs_oper, NULL); -- --finished: -- if (nfs != NULL) { -- nfs_destroy_context(nfs); -- } -- free(server); -- free(export); -- free(url); -- free(mnt); -- return ret; --}