From: Feng S. <ste...@gm...> - 2013-01-11 08:59:31
|
This patch set privdes support for readdirplus FUSE user space. It needs kernel support of the V2 patch from Miklos: http://sourceforge.net/mailarchive/message.php?msg_id=29707811 The patch set is based on Brian's [no_]auto_inval_data patch so I rebased it to fuse-3.0 and send it as the first patch in the sequence. Changed in V2 - Fix a bug in caculating readdirplus entry buffer size Feng Shuo (2): Add '[no_]auto_inval_data' mount option. Readdirplus support for fuse_lowlevel_ops include/fuse_common.h | 24 +++++++++++--------- include/fuse_kernel.h | 16 ++++++++++++++ include/fuse_lowlevel.h | 54 ++++++++++++++++++++++++++++++++++++++++++++ lib/fuse_i.h | 3 +++ lib/fuse_lowlevel.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++- lib/fuse_versionscript | 1 + test/stracedecode.c | 1 + 7 files changed, 146 insertions(+), 12 deletions(-) -- 1.7.12.4 |
From: Feng S. <ste...@gm...> - 2013-01-04 08:42:14
|
This patch set privdes support for readdirplus FUSE user space. It needs kernel support of the V2 patch from Miklos: http://sourceforge.net/mailarchive/message.php?msg_id=29707811 The patch set is based on Brian's [no_]auto_inval_data patch so I rebased it to fuse-3.0 and send it as the first patch in the sequence. Feng Shuo (2): Add '[no_]auto_inval_data' mount option. Add readdirplus support in fuse_lowlevel_ops and corresponding mount options include/fuse_common.h | 24 +++++++++++--------- include/fuse_kernel.h | 16 ++++++++++++++ include/fuse_lowlevel.h | 54 ++++++++++++++++++++++++++++++++++++++++++++ lib/fuse_i.h | 3 +++ lib/fuse_lowlevel.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++- lib/fuse_versionscript | 1 + test/stracedecode.c | 1 + 7 files changed, 146 insertions(+), 12 deletions(-) -- 1.7.12.4 |
From: Feng S. <ste...@gm...> - 2013-01-04 08:42:14
|
This patch implements readdirplus support in FUSE usersapce. It adds a new fuse lowlevel operations fuse_lowleve_ops::readdir_plus, corespoding mount options and helper functions to maintain buffer. Signed-off-by: Feng Shuo <ste...@gm...> --- include/fuse_common.h | 1 + include/fuse_kernel.h | 15 ++++++++++++++ include/fuse_lowlevel.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/fuse_i.h | 1 + lib/fuse_lowlevel.c | 48 ++++++++++++++++++++++++++++++++++++++++++- lib/fuse_versionscript | 1 + test/stracedecode.c | 1 + 7 files changed, 120 insertions(+), 1 deletion(-) diff --git a/include/fuse_common.h b/include/fuse_common.h index 58458ab..a86f048 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -112,6 +112,7 @@ struct fuse_file_info { #define FUSE_CAP_FLOCK_LOCKS (1 << 10) #define FUSE_CAP_IOCTL_DIR (1 << 11) #define FUSE_CAP_AUTO_INVAL_DATA (1 << 12) +#define FUSE_CAP_READDIR_PLUS (1 << 13) /** * Ioctl flags diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h index 60cd0c1..303384f 100644 --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -83,6 +83,9 @@ * * 7.19 * - add FUSE_FALLOCATE + * + * 7.20 + * - add FUSE_READDIRPLUS */ #ifndef _LINUX_FUSE_H @@ -208,6 +211,7 @@ struct fuse_file_lock { #define FUSE_DONT_MASK (1 << 6) #define FUSE_FLOCK_LOCKS (1 << 10) #define FUSE_AUTO_INVAL_DATA (1 << 12) +#define FUSE_DO_READDIRPLUS (1 << 13) /** * CUSE INIT request/reply flags @@ -314,6 +318,7 @@ enum fuse_opcode { FUSE_NOTIFY_REPLY = 41, FUSE_BATCH_FORGET = 42, FUSE_FALLOCATE = 43, + FUSE_READDIRPLUS = 44, /* CUSE specific operations */ CUSE_INIT = 4096, @@ -645,6 +650,16 @@ struct fuse_dirent { #define FUSE_DIRENT_SIZE(d) \ FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) +struct fuse_direntplus { + struct fuse_entry_out entry_out; + struct fuse_dirent dirent; +}; + +#define FUSE_NAME_OFFSET_DIRENTPLUS \ + offsetof(struct fuse_direntplus, dirent.name) +#define FUSE_DIRENTPLUS_SIZE(d) \ + FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen) + struct fuse_notify_inval_inode_out { __u64 ino; __s64 off; diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index 9a24bcc..7f30ef5 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -1016,6 +1016,32 @@ struct fuse_lowlevel_ops { */ void (*fallocate) (fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, off_t length, struct fuse_file_info *fi); + + /** + * Read directory with attributes + * + * Send a buffer filled using fuse_add_direntry_plus(), with size not + * exceeding the requested size. Send an empty buffer on end of + * stream. + * + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. + * + * Introduced in version 3.0 + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_data + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param size maximum number of bytes to send + * @param off offset to continue reading the directory stream + * @param fi file information + */ + void (*readdir_plus) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); }; /** @@ -1252,6 +1278,34 @@ size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, off_t off); /** + * Add a directory entry to the buffer with the attributes + * + * Buffer needs to be large enough to hold the entry. If it's not, + * then the entry is not filled in but the size of the entry is still + * returned. The caller can check this by comparing the bufsize + * parameter with the returned entry size. If the entry size is + * larger than the buffer size, the operation failed. + * + * From the 'stbuf' argument the st_ino field and bits 12-15 of the + * st_mode field are used. The other fields are ignored. + * + * Note: offsets do not necessarily represent physical offsets, and + * could be any marker, that enables the implementation to find a + * specific point in the directory stream. + * + * @param req request handle + * @param buf the point where the new entry will be added to the buffer + * @param bufsize remaining size of the buffer + * @param name the name of the entry + * @param e the directory entry + * @param off the offset of the next entry + * @return the space needed for the entry + */ +size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, + const char *name, + const struct fuse_entry_param *e, off_t off); + +/** * Reply to ask for data fetch and output buffer preparation. ioctl * will be retried with the specified input data fetched and output * buffer prepared. diff --git a/lib/fuse_i.h b/lib/fuse_i.h index 225ff7d..141eb3f 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -73,6 +73,7 @@ struct fuse_ll { int no_splice_read; int auto_inval_data; int no_auto_inval_data; + int no_readdir_plus; struct fuse_lowlevel_ops op; int got_init; struct cuse_data *cuse_data; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 4898a8a..8982eb1 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -338,6 +338,25 @@ static void fill_entry(struct fuse_entry_out *arg, convert_stat(&e->attr, &arg->attr); } +size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, + const char *name, + const struct fuse_entry_param *e, off_t off) +{ + struct fuse_entry_out *argp; + size_t entsize; + + (void) req; + entsize = FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + + fuse_dirent_size(strlen(name))); + if (entsize <= bufsize && buf){ + argp = (struct fuse_entry_out *)buf; + memset(argp, 0, sizeof(*argp)); + fill_entry(argp, e); + fuse_add_dirent(buf + sizeof(*argp), name, &(e->attr), off); + } + return entsize; +} + static void fill_open(struct fuse_open_out *arg, const struct fuse_file_info *f) { @@ -1388,6 +1407,21 @@ static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } +static void do_readdir_plus(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_read_in *arg = (struct fuse_read_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; + + if (req->f->op.readdir_plus) + req->f->op.readdir_plus(req, nodeid, arg->size, arg->offset, &fi); + else + fuse_reply_err(req, ENOSYS); +} + static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { struct fuse_release_in *arg = (struct fuse_release_in *) inarg; @@ -1788,6 +1822,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.capable |= FUSE_CAP_FLOCK_LOCKS; if (arg->flags & FUSE_AUTO_INVAL_DATA) f->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA; + if (arg->flags & FUSE_DO_READDIRPLUS) + f->conn.capable |= FUSE_CAP_READDIR_PLUS; } else { f->conn.async_read = 0; f->conn.max_readahead = 0; @@ -1820,6 +1856,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.want |= FUSE_CAP_BIG_WRITES; if (f->auto_inval_data) f->conn.want |= FUSE_CAP_AUTO_INVAL_DATA; + if (f->op.readdir_plus && !f->no_readdir_plus) + f->conn.want |= FUSE_CAP_READDIR_PLUS; if (bufsize < FUSE_MIN_READ_BUFFER) { fprintf(stderr, "fuse: warning: buffer size too small: %zu\n", @@ -1843,6 +1881,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.want &= ~FUSE_CAP_SPLICE_MOVE; if (f->no_auto_inval_data) f->conn.want &= ~FUSE_CAP_AUTO_INVAL_DATA; + if (f->no_readdir_plus) + f->conn.want &= ~FUSE_CAP_READDIR_PLUS; if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ)) outarg.flags |= FUSE_ASYNC_READ; @@ -1860,6 +1900,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) outarg.flags |= FUSE_FLOCK_LOCKS; if (f->conn.want & FUSE_CAP_AUTO_INVAL_DATA) outarg.flags |= FUSE_AUTO_INVAL_DATA; + if (f->conn.want & FUSE_CAP_READDIR_PLUS) + outarg.flags |= FUSE_DO_READDIRPLUS; outarg.max_readahead = f->conn.max_readahead; outarg.max_write = f->conn.max_write; if (f->conn.proto_minor >= 13) { @@ -2276,6 +2318,7 @@ static struct { [FUSE_DESTROY] = { do_destroy, "DESTROY" }, [FUSE_NOTIFY_REPLY] = { (void *) 1, "NOTIFY_REPLY" }, [FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" }, + [FUSE_READDIRPLUS] = { do_readdir_plus, "READDIRPLUS"}, [CUSE_INIT] = { cuse_lowlevel_init, "CUSE_INIT" }, }; @@ -2384,7 +2427,8 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC && in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR && in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR && - in->opcode != FUSE_NOTIFY_REPLY) + in->opcode != FUSE_NOTIFY_REPLY && + in->opcode != FUSE_READDIRPLUS) goto reply_err; err = ENOSYS; @@ -2483,6 +2527,7 @@ static const struct fuse_opt fuse_ll_opts[] = { { "no_splice_read", offsetof(struct fuse_ll, no_splice_read), 1}, { "auto_inval_data", offsetof(struct fuse_ll, auto_inval_data), 1}, { "no_auto_inval_data", offsetof(struct fuse_ll, no_auto_inval_data), 1}, + { "no_readdir_plus", offsetof(struct fuse_ll, no_readdir_plus), 1}, FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP), @@ -2515,6 +2560,7 @@ static void fuse_ll_help(void) " -o [no_]splice_move move data while splicing to the fuse device\n" " -o [no_]splice_read use splice to read from the fuse device\n" " -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n" +" -o [no_]readdir_plus use readdir_plus if possible.\n" ); } diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index ea2a1c8..ad5a940 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -51,6 +51,7 @@ FUSE_3.0 { fuse_reply_statfs; fuse_set_signal_handlers; fuse_add_direntry; + fuse_add_direntry_plus; fuse_chan_new; fuse_chan_recv; fuse_daemonize; diff --git a/test/stracedecode.c b/test/stracedecode.c index 27b883c..940438a 100644 --- a/test/stracedecode.c +++ b/test/stracedecode.c @@ -41,6 +41,7 @@ static struct { [FUSE_INTERRUPT] = { "INTERRUPT" }, [FUSE_BMAP] = { "BMAP" }, [FUSE_DESTROY] = { "DESTROY" }, + [FUSE_READDIRPLUS] = { "READDIRPLUS" }, }; #define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0])) -- 1.7.12.4 |
From: Feng S. <ste...@gm...> - 2013-01-04 08:42:14
|
Several caching logic changes have been made on the kernel side to better support network-based fuse filesystems. These include kernel side mtime checking and read path cache revalidation. The new caching logic is enabled through the FUSE_AUTO_INVAL_DATA init flag. Export this to the user via the '[no_]auto_inval_data' mount option. Changed in v2 - Rebase to FUSE 3.0. Signed-off-by: Feng Shuo <ste...@gm...> --- include/fuse_common.h | 23 ++++++++++++----------- include/fuse_kernel.h | 1 + lib/fuse_i.h | 2 ++ lib/fuse_lowlevel.c | 11 +++++++++++ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/fuse_common.h b/include/fuse_common.h index 0ae33a9..58458ab 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -100,17 +100,18 @@ struct fuse_file_info { * FUSE_CAP_SPLICE_READ: ability to use splice() to read from the fuse device * FUSE_CAP_IOCTL_DIR: ioctl support on directories */ -#define FUSE_CAP_ASYNC_READ (1 << 0) -#define FUSE_CAP_POSIX_LOCKS (1 << 1) -#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) -#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) -#define FUSE_CAP_BIG_WRITES (1 << 5) -#define FUSE_CAP_DONT_MASK (1 << 6) -#define FUSE_CAP_SPLICE_WRITE (1 << 7) -#define FUSE_CAP_SPLICE_MOVE (1 << 8) -#define FUSE_CAP_SPLICE_READ (1 << 9) -#define FUSE_CAP_FLOCK_LOCKS (1 << 10) -#define FUSE_CAP_IOCTL_DIR (1 << 11) +#define FUSE_CAP_ASYNC_READ (1 << 0) +#define FUSE_CAP_POSIX_LOCKS (1 << 1) +#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) +#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) +#define FUSE_CAP_BIG_WRITES (1 << 5) +#define FUSE_CAP_DONT_MASK (1 << 6) +#define FUSE_CAP_SPLICE_WRITE (1 << 7) +#define FUSE_CAP_SPLICE_MOVE (1 << 8) +#define FUSE_CAP_SPLICE_READ (1 << 9) +#define FUSE_CAP_FLOCK_LOCKS (1 << 10) +#define FUSE_CAP_IOCTL_DIR (1 << 11) +#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12) /** * Ioctl flags diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h index c632b58..60cd0c1 100644 --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -207,6 +207,7 @@ struct fuse_file_lock { #define FUSE_BIG_WRITES (1 << 5) #define FUSE_DONT_MASK (1 << 6) #define FUSE_FLOCK_LOCKS (1 << 10) +#define FUSE_AUTO_INVAL_DATA (1 << 12) /** * CUSE INIT request/reply flags diff --git a/lib/fuse_i.h b/lib/fuse_i.h index 1f1787e..225ff7d 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -71,6 +71,8 @@ struct fuse_ll { int no_splice_write; int no_splice_move; int no_splice_read; + int auto_inval_data; + int no_auto_inval_data; struct fuse_lowlevel_ops op; int got_init; struct cuse_data *cuse_data; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 4178d9a..4898a8a 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -1786,6 +1786,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.capable |= FUSE_CAP_DONT_MASK; if (arg->flags & FUSE_FLOCK_LOCKS) f->conn.capable |= FUSE_CAP_FLOCK_LOCKS; + if (arg->flags & FUSE_AUTO_INVAL_DATA) + f->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA; } else { f->conn.async_read = 0; f->conn.max_readahead = 0; @@ -1816,6 +1818,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.want |= FUSE_CAP_FLOCK_LOCKS; if (f->big_writes) f->conn.want |= FUSE_CAP_BIG_WRITES; + if (f->auto_inval_data) + f->conn.want |= FUSE_CAP_AUTO_INVAL_DATA; if (bufsize < FUSE_MIN_READ_BUFFER) { fprintf(stderr, "fuse: warning: buffer size too small: %zu\n", @@ -1837,6 +1841,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.want &= ~FUSE_CAP_SPLICE_WRITE; if (f->no_splice_move) f->conn.want &= ~FUSE_CAP_SPLICE_MOVE; + if (f->no_auto_inval_data) + f->conn.want &= ~FUSE_CAP_AUTO_INVAL_DATA; if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ)) outarg.flags |= FUSE_ASYNC_READ; @@ -1852,6 +1858,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) outarg.flags |= FUSE_DONT_MASK; if (f->conn.want & FUSE_CAP_FLOCK_LOCKS) outarg.flags |= FUSE_FLOCK_LOCKS; + if (f->conn.want & FUSE_CAP_AUTO_INVAL_DATA) + outarg.flags |= FUSE_AUTO_INVAL_DATA; outarg.max_readahead = f->conn.max_readahead; outarg.max_write = f->conn.max_write; if (f->conn.proto_minor >= 13) { @@ -2473,6 +2481,8 @@ static const struct fuse_opt fuse_ll_opts[] = { { "no_splice_move", offsetof(struct fuse_ll, no_splice_move), 1}, { "splice_read", offsetof(struct fuse_ll, splice_read), 1}, { "no_splice_read", offsetof(struct fuse_ll, no_splice_read), 1}, + { "auto_inval_data", offsetof(struct fuse_ll, auto_inval_data), 1}, + { "no_auto_inval_data", offsetof(struct fuse_ll, no_auto_inval_data), 1}, FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP), @@ -2504,6 +2514,7 @@ static void fuse_ll_help(void) " -o [no_]splice_write use splice to write to the fuse device\n" " -o [no_]splice_move move data while splicing to the fuse device\n" " -o [no_]splice_read use splice to read from the fuse device\n" +" -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n" ); } -- 1.7.12.4 |
From: Stef B. <st...@gm...> - 2013-01-10 09:08:05
|
Hi, I would like to test it, but is the version of fuse 3.0 required?? And if yes, how can I check this version out? I've been looking hwo but cannot find anything. Stef |
From: Feng S. <ste...@gm...> - 2013-01-10 14:32:54
|
3.0 is now in fuse git. https://sourceforge.net/projects/fuse/develop?source=navbar Actually I believe this patch should work on almost all 2.9.x versions. You can also check out my clone in github (in devel branch): https://github.com/openunix/fuse-cygwin/tree/devel. This already includes the patch. On Thu, Jan 10, 2013 at 5:07 PM, Stef Bon <st...@gm...> wrote: > Hi, > > I would like to test it, but is the version of fuse 3.0 required?? > > And if yes, how can I check this version out? I've been looking hwo but > cannot find anything. > > > Stef > > -- Feng Shuo Tel: (86)10-59851155-2116 Fax: (86)10-59851155-2008 Tianjin Zhongke Blue Whale Information Technologies Co., Ltd 10th Floor, Tower A, The GATE building, No. 19 Zhong-guan-cun Avenue Haidian District, Beijing, China Postcode 100080 |
From: Stef B. <st...@gm...> - 2013-01-10 20:22:44
|
Hi, I've already the latest branch. I did not expect that since it's a new branch, and normally with git you have to switch manually and I did not do that. I had the 2.8 or 2.9 branch. I've tried to use your patch, but : sbon [ ~/Source/fuse/git/fuse ]$ patch -Np1 -i /home/sbon/Programmeren/fuse-ll-readdirplus-patch patching file include/fuse_common.h Hunk #1 FAILED at 112. 1 out of 1 hunk FAILED -- saving rejects to file include/fuse_common.h.rej patching file include/fuse_kernel.h Hunk #2 FAILED at 211. Hunk #3 succeeded at 316 (offset -1 lines). Hunk #4 succeeded at 648 (offset -1 lines). 1 out of 4 hunks FAILED -- saving rejects to file include/fuse_kernel.h.rej patching file include/fuse_lowlevel.h patching file lib/fuse_i.h Hunk #1 FAILED at 73. 1 out of 1 hunk FAILED -- saving rejects to file lib/fuse_i.h.rej patching file lib/fuse_lowlevel.c Hunk #3 FAILED at 1822. Hunk #4 FAILED at 1854. Hunk #5 FAILED at 1877. Hunk #6 FAILED at 1894. Hunk #7 succeeded at 2302 (offset -8 lines). Hunk #8 succeeded at 2411 (offset -8 lines). Hunk #9 FAILED at 2519. Hunk #10 FAILED at 2551. 6 out of 10 hunks FAILED -- saving rejects to file lib/fuse_lowlevel.c.rej patching file lib/fuse_versionscript patching file test/stracedecode.c Huh do you know what happened? Stef > |
From: Feng S. <ste...@gm...> - 2013-01-11 00:53:33
|
Did you apply the first mtime patch I send in this patch set? On Fri, Jan 11, 2013 at 4:22 AM, Stef Bon <st...@gm...> wrote: > Hi, > > I've already the latest branch. I did not expect that since it's a new > branch, and normally with git you have to switch manually and I did not do > that. > > I had the 2.8 or 2.9 branch. > > I've tried to use your patch, but : > > sbon [ ~/Source/fuse/git/fuse ]$ patch -Np1 -i > /home/sbon/Programmeren/fuse-ll-readdirplus-patch > patching file include/fuse_common.h > Hunk #1 FAILED at 112. > 1 out of 1 hunk FAILED -- saving rejects to file include/fuse_common.h.rej > patching file include/fuse_kernel.h > Hunk #2 FAILED at 211. > Hunk #3 succeeded at 316 (offset -1 lines). > Hunk #4 succeeded at 648 (offset -1 lines). > 1 out of 4 hunks FAILED -- saving rejects to file include/fuse_kernel.h.rej > patching file include/fuse_lowlevel.h > patching file lib/fuse_i.h > Hunk #1 FAILED at 73. > 1 out of 1 hunk FAILED -- saving rejects to file lib/fuse_i.h.rej > patching file lib/fuse_lowlevel.c > Hunk #3 FAILED at 1822. > Hunk #4 FAILED at 1854. > Hunk #5 FAILED at 1877. > Hunk #6 FAILED at 1894. > Hunk #7 succeeded at 2302 (offset -8 lines). > Hunk #8 succeeded at 2411 (offset -8 lines). > Hunk #9 FAILED at 2519. > Hunk #10 FAILED at 2551. > 6 out of 10 hunks FAILED -- saving rejects to file lib/fuse_lowlevel.c.rej > patching file lib/fuse_versionscript > patching file test/stracedecode.c > > Huh do you know what happened? > > Stef > > >> > -- Feng Shuo Tel: (86)10-59851155-2116 Fax: (86)10-59851155-2008 Tianjin Zhongke Blue Whale Information Technologies Co., Ltd 10th Floor, Tower A, The GATE building, No. 19 Zhong-guan-cun Avenue Haidian District, Beijing, China Postcode 100080 |
From: Stef B. <st...@gm...> - 2013-01-12 13:00:02
|
No probably not. It was the standard fuse source. I've checked out your source from github, so I do not have to apply this patch. Where can I find the differences between your source en the mainstream fuse source? Stef |
From: Feng S. <ste...@gm...> - 2013-01-13 15:23:48
|
Well for the "master" branch of https://github.com/openunix/fuse-cygwin, it's upstream fuse (3.0 now) plus fix for compiling on cygwin. The "devel" branch is the "master" + "[PATCH V2 1/2] Add '[no_]auto_inval_data' mount option." + "[PATCH V2 2/2] Readdirplus support for fuse_lowlevel_ops". I was planning to run fuse on cygwin but finally found that I needed to learn more on fuse itself before that..... Now only the fuse userspace can compile on cygwin but kernel space is not finished. On Sat, Jan 12, 2013 at 8:59 PM, Stef Bon <st...@gm...> wrote: > No probably not. > > It was the standard fuse source. > I've checked out your source from github, so I do not have to apply this > patch. > Where can I find the differences between your source en the mainstream fuse > source? > > Stef > > > > -- Feng Shuo Tel: (86)10-59851155-2116 Fax: (86)10-59851155-2008 Tianjin Zhongke Blue Whale Information Technologies Co., Ltd 10th Floor, Tower A, The GATE building, No. 19 Zhong-guan-cun Avenue Haidian District, Beijing, China Postcode 100080 |
From: Miklos S. <mi...@sz...> - 2013-02-06 16:28:48
|
On Fri, Jan 4, 2013 at 9:23 AM, Feng Shuo <ste...@gm...> wrote: > Several caching logic changes have been made on the kernel side > to better support network-based fuse filesystems. These include > kernel side mtime checking and read path cache revalidation. The > new caching logic is enabled through the FUSE_AUTO_INVAL_DATA > init flag. Export this to the user via the '[no_]auto_inval_data' > mount option. > > Changed in v2 > - Rebase to FUSE 3.0. Thanks, applied. Miklos > > Signed-off-by: Feng Shuo <ste...@gm...> > --- > include/fuse_common.h | 23 ++++++++++++----------- > include/fuse_kernel.h | 1 + > lib/fuse_i.h | 2 ++ > lib/fuse_lowlevel.c | 11 +++++++++++ > 4 files changed, 26 insertions(+), 11 deletions(-) > > diff --git a/include/fuse_common.h b/include/fuse_common.h > index 0ae33a9..58458ab 100644 > --- a/include/fuse_common.h > +++ b/include/fuse_common.h > @@ -100,17 +100,18 @@ struct fuse_file_info { > * FUSE_CAP_SPLICE_READ: ability to use splice() to read from the fuse device > * FUSE_CAP_IOCTL_DIR: ioctl support on directories > */ > -#define FUSE_CAP_ASYNC_READ (1 << 0) > -#define FUSE_CAP_POSIX_LOCKS (1 << 1) > -#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) > -#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) > -#define FUSE_CAP_BIG_WRITES (1 << 5) > -#define FUSE_CAP_DONT_MASK (1 << 6) > -#define FUSE_CAP_SPLICE_WRITE (1 << 7) > -#define FUSE_CAP_SPLICE_MOVE (1 << 8) > -#define FUSE_CAP_SPLICE_READ (1 << 9) > -#define FUSE_CAP_FLOCK_LOCKS (1 << 10) > -#define FUSE_CAP_IOCTL_DIR (1 << 11) > +#define FUSE_CAP_ASYNC_READ (1 << 0) > +#define FUSE_CAP_POSIX_LOCKS (1 << 1) > +#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) > +#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) > +#define FUSE_CAP_BIG_WRITES (1 << 5) > +#define FUSE_CAP_DONT_MASK (1 << 6) > +#define FUSE_CAP_SPLICE_WRITE (1 << 7) > +#define FUSE_CAP_SPLICE_MOVE (1 << 8) > +#define FUSE_CAP_SPLICE_READ (1 << 9) > +#define FUSE_CAP_FLOCK_LOCKS (1 << 10) > +#define FUSE_CAP_IOCTL_DIR (1 << 11) > +#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12) > > /** > * Ioctl flags > diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h > index c632b58..60cd0c1 100644 > --- a/include/fuse_kernel.h > +++ b/include/fuse_kernel.h > @@ -207,6 +207,7 @@ struct fuse_file_lock { > #define FUSE_BIG_WRITES (1 << 5) > #define FUSE_DONT_MASK (1 << 6) > #define FUSE_FLOCK_LOCKS (1 << 10) > +#define FUSE_AUTO_INVAL_DATA (1 << 12) > > /** > * CUSE INIT request/reply flags > diff --git a/lib/fuse_i.h b/lib/fuse_i.h > index 1f1787e..225ff7d 100644 > --- a/lib/fuse_i.h > +++ b/lib/fuse_i.h > @@ -71,6 +71,8 @@ struct fuse_ll { > int no_splice_write; > int no_splice_move; > int no_splice_read; > + int auto_inval_data; > + int no_auto_inval_data; > struct fuse_lowlevel_ops op; > int got_init; > struct cuse_data *cuse_data; > diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c > index 4178d9a..4898a8a 100644 > --- a/lib/fuse_lowlevel.c > +++ b/lib/fuse_lowlevel.c > @@ -1786,6 +1786,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) > f->conn.capable |= FUSE_CAP_DONT_MASK; > if (arg->flags & FUSE_FLOCK_LOCKS) > f->conn.capable |= FUSE_CAP_FLOCK_LOCKS; > + if (arg->flags & FUSE_AUTO_INVAL_DATA) > + f->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA; > } else { > f->conn.async_read = 0; > f->conn.max_readahead = 0; > @@ -1816,6 +1818,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) > f->conn.want |= FUSE_CAP_FLOCK_LOCKS; > if (f->big_writes) > f->conn.want |= FUSE_CAP_BIG_WRITES; > + if (f->auto_inval_data) > + f->conn.want |= FUSE_CAP_AUTO_INVAL_DATA; > > if (bufsize < FUSE_MIN_READ_BUFFER) { > fprintf(stderr, "fuse: warning: buffer size too small: %zu\n", > @@ -1837,6 +1841,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) > f->conn.want &= ~FUSE_CAP_SPLICE_WRITE; > if (f->no_splice_move) > f->conn.want &= ~FUSE_CAP_SPLICE_MOVE; > + if (f->no_auto_inval_data) > + f->conn.want &= ~FUSE_CAP_AUTO_INVAL_DATA; > > if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ)) > outarg.flags |= FUSE_ASYNC_READ; > @@ -1852,6 +1858,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) > outarg.flags |= FUSE_DONT_MASK; > if (f->conn.want & FUSE_CAP_FLOCK_LOCKS) > outarg.flags |= FUSE_FLOCK_LOCKS; > + if (f->conn.want & FUSE_CAP_AUTO_INVAL_DATA) > + outarg.flags |= FUSE_AUTO_INVAL_DATA; > outarg.max_readahead = f->conn.max_readahead; > outarg.max_write = f->conn.max_write; > if (f->conn.proto_minor >= 13) { > @@ -2473,6 +2481,8 @@ static const struct fuse_opt fuse_ll_opts[] = { > { "no_splice_move", offsetof(struct fuse_ll, no_splice_move), 1}, > { "splice_read", offsetof(struct fuse_ll, splice_read), 1}, > { "no_splice_read", offsetof(struct fuse_ll, no_splice_read), 1}, > + { "auto_inval_data", offsetof(struct fuse_ll, auto_inval_data), 1}, > + { "no_auto_inval_data", offsetof(struct fuse_ll, no_auto_inval_data), 1}, > FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD), > FUSE_OPT_KEY("-h", KEY_HELP), > FUSE_OPT_KEY("--help", KEY_HELP), > @@ -2504,6 +2514,7 @@ static void fuse_ll_help(void) > " -o [no_]splice_write use splice to write to the fuse device\n" > " -o [no_]splice_move move data while splicing to the fuse device\n" > " -o [no_]splice_read use splice to read from the fuse device\n" > +" -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n" > ); > } > > -- > 1.7.12.4 > > > ------------------------------------------------------------------------------ > Master HTML5, CSS3, ASP.NET, MVC, AJAX, Knockout.js, Web API and > much more. Get web development skills now with LearnDevNow - > 350+ hours of step-by-step video tutorials by Microsoft MVPs and experts. > SALE $99.99 this month only -- learn more at: > http://p.sf.net/sfu/learnmore_122812 > _______________________________________________ > fuse-devel mailing list > fus...@li... > https://lists.sourceforge.net/lists/listinfo/fuse-devel |
From: Feng S. <ste...@gm...> - 2013-02-08 03:11:57
|
I just got time to pull the latest fuse git tree (it's nice to see so many updates :-). The author of this patch is not me but Brian Foster: http://sourceforge.net/mailarchive/message.php?msg_id=29549486 I rebased it to the latest fuse-3.0 and make my readdirplus patch based on it to avoid possible conflict. I think I got mess up the signed-off-by in formating patch but not knowing why. Sorry for that. :-( On Thu, Feb 7, 2013 at 12:28 AM, Miklos Szeredi <mi...@sz...> wrote: > On Fri, Jan 4, 2013 at 9:23 AM, Feng Shuo <ste...@gm...> wrote: >> Several caching logic changes have been made on the kernel side >> to better support network-based fuse filesystems. These include >> kernel side mtime checking and read path cache revalidation. The >> new caching logic is enabled through the FUSE_AUTO_INVAL_DATA >> init flag. Export this to the user via the '[no_]auto_inval_data' >> mount option. >> >> Changed in v2 >> - Rebase to FUSE 3.0. > > Thanks, applied. > > Miklos > >> >> Signed-off-by: Feng Shuo <ste...@gm...> >> --- >> include/fuse_common.h | 23 ++++++++++++----------- >> include/fuse_kernel.h | 1 + >> lib/fuse_i.h | 2 ++ >> lib/fuse_lowlevel.c | 11 +++++++++++ >> 4 files changed, 26 insertions(+), 11 deletions(-) >> >> diff --git a/include/fuse_common.h b/include/fuse_common.h >> index 0ae33a9..58458ab 100644 >> --- a/include/fuse_common.h >> +++ b/include/fuse_common.h >> @@ -100,17 +100,18 @@ struct fuse_file_info { >> * FUSE_CAP_SPLICE_READ: ability to use splice() to read from the fuse device >> * FUSE_CAP_IOCTL_DIR: ioctl support on directories >> */ >> -#define FUSE_CAP_ASYNC_READ (1 << 0) >> -#define FUSE_CAP_POSIX_LOCKS (1 << 1) >> -#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) >> -#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) >> -#define FUSE_CAP_BIG_WRITES (1 << 5) >> -#define FUSE_CAP_DONT_MASK (1 << 6) >> -#define FUSE_CAP_SPLICE_WRITE (1 << 7) >> -#define FUSE_CAP_SPLICE_MOVE (1 << 8) >> -#define FUSE_CAP_SPLICE_READ (1 << 9) >> -#define FUSE_CAP_FLOCK_LOCKS (1 << 10) >> -#define FUSE_CAP_IOCTL_DIR (1 << 11) >> +#define FUSE_CAP_ASYNC_READ (1 << 0) >> +#define FUSE_CAP_POSIX_LOCKS (1 << 1) >> +#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) >> +#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) >> +#define FUSE_CAP_BIG_WRITES (1 << 5) >> +#define FUSE_CAP_DONT_MASK (1 << 6) >> +#define FUSE_CAP_SPLICE_WRITE (1 << 7) >> +#define FUSE_CAP_SPLICE_MOVE (1 << 8) >> +#define FUSE_CAP_SPLICE_READ (1 << 9) >> +#define FUSE_CAP_FLOCK_LOCKS (1 << 10) >> +#define FUSE_CAP_IOCTL_DIR (1 << 11) >> +#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12) >> >> /** >> * Ioctl flags >> diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h >> index c632b58..60cd0c1 100644 >> --- a/include/fuse_kernel.h >> +++ b/include/fuse_kernel.h >> @@ -207,6 +207,7 @@ struct fuse_file_lock { >> #define FUSE_BIG_WRITES (1 << 5) >> #define FUSE_DONT_MASK (1 << 6) >> #define FUSE_FLOCK_LOCKS (1 << 10) >> +#define FUSE_AUTO_INVAL_DATA (1 << 12) >> >> /** >> * CUSE INIT request/reply flags >> diff --git a/lib/fuse_i.h b/lib/fuse_i.h >> index 1f1787e..225ff7d 100644 >> --- a/lib/fuse_i.h >> +++ b/lib/fuse_i.h >> @@ -71,6 +71,8 @@ struct fuse_ll { >> int no_splice_write; >> int no_splice_move; >> int no_splice_read; >> + int auto_inval_data; >> + int no_auto_inval_data; >> struct fuse_lowlevel_ops op; >> int got_init; >> struct cuse_data *cuse_data; >> diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c >> index 4178d9a..4898a8a 100644 >> --- a/lib/fuse_lowlevel.c >> +++ b/lib/fuse_lowlevel.c >> @@ -1786,6 +1786,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) >> f->conn.capable |= FUSE_CAP_DONT_MASK; >> if (arg->flags & FUSE_FLOCK_LOCKS) >> f->conn.capable |= FUSE_CAP_FLOCK_LOCKS; >> + if (arg->flags & FUSE_AUTO_INVAL_DATA) >> + f->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA; >> } else { >> f->conn.async_read = 0; >> f->conn.max_readahead = 0; >> @@ -1816,6 +1818,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) >> f->conn.want |= FUSE_CAP_FLOCK_LOCKS; >> if (f->big_writes) >> f->conn.want |= FUSE_CAP_BIG_WRITES; >> + if (f->auto_inval_data) >> + f->conn.want |= FUSE_CAP_AUTO_INVAL_DATA; >> >> if (bufsize < FUSE_MIN_READ_BUFFER) { >> fprintf(stderr, "fuse: warning: buffer size too small: %zu\n", >> @@ -1837,6 +1841,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) >> f->conn.want &= ~FUSE_CAP_SPLICE_WRITE; >> if (f->no_splice_move) >> f->conn.want &= ~FUSE_CAP_SPLICE_MOVE; >> + if (f->no_auto_inval_data) >> + f->conn.want &= ~FUSE_CAP_AUTO_INVAL_DATA; >> >> if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ)) >> outarg.flags |= FUSE_ASYNC_READ; >> @@ -1852,6 +1858,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) >> outarg.flags |= FUSE_DONT_MASK; >> if (f->conn.want & FUSE_CAP_FLOCK_LOCKS) >> outarg.flags |= FUSE_FLOCK_LOCKS; >> + if (f->conn.want & FUSE_CAP_AUTO_INVAL_DATA) >> + outarg.flags |= FUSE_AUTO_INVAL_DATA; >> outarg.max_readahead = f->conn.max_readahead; >> outarg.max_write = f->conn.max_write; >> if (f->conn.proto_minor >= 13) { >> @@ -2473,6 +2481,8 @@ static const struct fuse_opt fuse_ll_opts[] = { >> { "no_splice_move", offsetof(struct fuse_ll, no_splice_move), 1}, >> { "splice_read", offsetof(struct fuse_ll, splice_read), 1}, >> { "no_splice_read", offsetof(struct fuse_ll, no_splice_read), 1}, >> + { "auto_inval_data", offsetof(struct fuse_ll, auto_inval_data), 1}, >> + { "no_auto_inval_data", offsetof(struct fuse_ll, no_auto_inval_data), 1}, >> FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD), >> FUSE_OPT_KEY("-h", KEY_HELP), >> FUSE_OPT_KEY("--help", KEY_HELP), >> @@ -2504,6 +2514,7 @@ static void fuse_ll_help(void) >> " -o [no_]splice_write use splice to write to the fuse device\n" >> " -o [no_]splice_move move data while splicing to the fuse device\n" >> " -o [no_]splice_read use splice to read from the fuse device\n" >> +" -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n" >> ); >> } >> >> -- >> 1.7.12.4 >> >> >> ------------------------------------------------------------------------------ >> Master HTML5, CSS3, ASP.NET, MVC, AJAX, Knockout.js, Web API and >> much more. Get web development skills now with LearnDevNow - >> 350+ hours of step-by-step video tutorials by Microsoft MVPs and experts. >> SALE $99.99 this month only -- learn more at: >> http://p.sf.net/sfu/learnmore_122812 >> _______________________________________________ >> fuse-devel mailing list >> fus...@li... >> https://lists.sourceforge.net/lists/listinfo/fuse-devel -- Feng Shuo Tel: (86)10-59851155-2116 Fax: (86)10-59851155-2008 Tianjin Zhongke Blue Whale Information Technologies Co., Ltd 10th Floor, Tower A, The GATE building, No. 19 Zhong-guan-cun Avenue Haidian District, Beijing, China Postcode 100080 |
From: Miklos S. <mi...@sz...> - 2013-02-08 04:49:45
|
On Fri, Feb 8, 2013 at 4:11 AM, Feng Shuo <ste...@gm...> wrote: > I just got time to pull the latest fuse git tree (it's nice to see so > many updates :-). The author of this patch is not me but Brian Foster: > > http://sourceforge.net/mailarchive/message.php?msg_id=29549486 > > I rebased it to the latest fuse-3.0 and make my readdirplus patch > based on it to avoid possible conflict. I think I got mess up the > signed-off-by in formating patch but not knowing why. Sorry for that. > :-( Not a big problem. Signed-off-by indicates that you have a right to submitting that patch, tt does not indicate authorship. Authorship is indicated by a "From: ..." line at the beginning of the patch. See the documentation in linux/Documentation/SubmittingPatches, it describes these rules in detail. Thanks, Miklos |
From: Feng S. <ste...@gm...> - 2013-01-11 08:59:31
|
This patch implements readdirplus support in FUSE usersapce. It adds a new fuse lowlevel operations fuse_lowleve_ops::readdir_plus and also provides corespoding mount options and helper functions. Changed in V2 - Fix a bug in caculating readdirplus entry buffer size Signed-off-by: Feng Shuo <ste...@gm...> --- include/fuse_common.h | 1 + include/fuse_kernel.h | 15 ++++++++++++++ include/fuse_lowlevel.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/fuse_i.h | 1 + lib/fuse_lowlevel.c | 48 ++++++++++++++++++++++++++++++++++++++++++- lib/fuse_versionscript | 1 + test/stracedecode.c | 1 + 7 files changed, 120 insertions(+), 1 deletion(-) diff --git a/include/fuse_common.h b/include/fuse_common.h index 58458ab..a86f048 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -112,6 +112,7 @@ struct fuse_file_info { #define FUSE_CAP_FLOCK_LOCKS (1 << 10) #define FUSE_CAP_IOCTL_DIR (1 << 11) #define FUSE_CAP_AUTO_INVAL_DATA (1 << 12) +#define FUSE_CAP_READDIR_PLUS (1 << 13) /** * Ioctl flags diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h index 60cd0c1..303384f 100644 --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -83,6 +83,9 @@ * * 7.19 * - add FUSE_FALLOCATE + * + * 7.20 + * - add FUSE_READDIRPLUS */ #ifndef _LINUX_FUSE_H @@ -208,6 +211,7 @@ struct fuse_file_lock { #define FUSE_DONT_MASK (1 << 6) #define FUSE_FLOCK_LOCKS (1 << 10) #define FUSE_AUTO_INVAL_DATA (1 << 12) +#define FUSE_DO_READDIRPLUS (1 << 13) /** * CUSE INIT request/reply flags @@ -314,6 +318,7 @@ enum fuse_opcode { FUSE_NOTIFY_REPLY = 41, FUSE_BATCH_FORGET = 42, FUSE_FALLOCATE = 43, + FUSE_READDIRPLUS = 44, /* CUSE specific operations */ CUSE_INIT = 4096, @@ -645,6 +650,16 @@ struct fuse_dirent { #define FUSE_DIRENT_SIZE(d) \ FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) +struct fuse_direntplus { + struct fuse_entry_out entry_out; + struct fuse_dirent dirent; +}; + +#define FUSE_NAME_OFFSET_DIRENTPLUS \ + offsetof(struct fuse_direntplus, dirent.name) +#define FUSE_DIRENTPLUS_SIZE(d) \ + FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen) + struct fuse_notify_inval_inode_out { __u64 ino; __s64 off; diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index 9a24bcc..7f30ef5 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -1016,6 +1016,32 @@ struct fuse_lowlevel_ops { */ void (*fallocate) (fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, off_t length, struct fuse_file_info *fi); + + /** + * Read directory with attributes + * + * Send a buffer filled using fuse_add_direntry_plus(), with size not + * exceeding the requested size. Send an empty buffer on end of + * stream. + * + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. + * + * Introduced in version 3.0 + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_data + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param size maximum number of bytes to send + * @param off offset to continue reading the directory stream + * @param fi file information + */ + void (*readdir_plus) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); }; /** @@ -1252,6 +1278,34 @@ size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, off_t off); /** + * Add a directory entry to the buffer with the attributes + * + * Buffer needs to be large enough to hold the entry. If it's not, + * then the entry is not filled in but the size of the entry is still + * returned. The caller can check this by comparing the bufsize + * parameter with the returned entry size. If the entry size is + * larger than the buffer size, the operation failed. + * + * From the 'stbuf' argument the st_ino field and bits 12-15 of the + * st_mode field are used. The other fields are ignored. + * + * Note: offsets do not necessarily represent physical offsets, and + * could be any marker, that enables the implementation to find a + * specific point in the directory stream. + * + * @param req request handle + * @param buf the point where the new entry will be added to the buffer + * @param bufsize remaining size of the buffer + * @param name the name of the entry + * @param e the directory entry + * @param off the offset of the next entry + * @return the space needed for the entry + */ +size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, + const char *name, + const struct fuse_entry_param *e, off_t off); + +/** * Reply to ask for data fetch and output buffer preparation. ioctl * will be retried with the specified input data fetched and output * buffer prepared. diff --git a/lib/fuse_i.h b/lib/fuse_i.h index 225ff7d..141eb3f 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -73,6 +73,7 @@ struct fuse_ll { int no_splice_read; int auto_inval_data; int no_auto_inval_data; + int no_readdir_plus; struct fuse_lowlevel_ops op; int got_init; struct cuse_data *cuse_data; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 4898a8a..97adade 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -338,6 +338,25 @@ static void fill_entry(struct fuse_entry_out *arg, convert_stat(&e->attr, &arg->attr); } +size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize, + const char *name, + const struct fuse_entry_param *e, off_t off) +{ + struct fuse_entry_out *argp; + size_t entsize; + + (void) req; + entsize = FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + + (strlen(name))); + if (entsize <= bufsize && buf){ + argp = (struct fuse_entry_out *)buf; + memset(argp, 0, sizeof(*argp)); + fill_entry(argp, e); + fuse_add_dirent(buf + sizeof(*argp), name, &(e->attr), off); + } + return entsize; +} + static void fill_open(struct fuse_open_out *arg, const struct fuse_file_info *f) { @@ -1388,6 +1407,21 @@ static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } +static void do_readdir_plus(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_read_in *arg = (struct fuse_read_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; + + if (req->f->op.readdir_plus) + req->f->op.readdir_plus(req, nodeid, arg->size, arg->offset, &fi); + else + fuse_reply_err(req, ENOSYS); +} + static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { struct fuse_release_in *arg = (struct fuse_release_in *) inarg; @@ -1788,6 +1822,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.capable |= FUSE_CAP_FLOCK_LOCKS; if (arg->flags & FUSE_AUTO_INVAL_DATA) f->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA; + if (arg->flags & FUSE_DO_READDIRPLUS) + f->conn.capable |= FUSE_CAP_READDIR_PLUS; } else { f->conn.async_read = 0; f->conn.max_readahead = 0; @@ -1820,6 +1856,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.want |= FUSE_CAP_BIG_WRITES; if (f->auto_inval_data) f->conn.want |= FUSE_CAP_AUTO_INVAL_DATA; + if (f->op.readdir_plus && !f->no_readdir_plus) + f->conn.want |= FUSE_CAP_READDIR_PLUS; if (bufsize < FUSE_MIN_READ_BUFFER) { fprintf(stderr, "fuse: warning: buffer size too small: %zu\n", @@ -1843,6 +1881,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.want &= ~FUSE_CAP_SPLICE_MOVE; if (f->no_auto_inval_data) f->conn.want &= ~FUSE_CAP_AUTO_INVAL_DATA; + if (f->no_readdir_plus) + f->conn.want &= ~FUSE_CAP_READDIR_PLUS; if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ)) outarg.flags |= FUSE_ASYNC_READ; @@ -1860,6 +1900,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) outarg.flags |= FUSE_FLOCK_LOCKS; if (f->conn.want & FUSE_CAP_AUTO_INVAL_DATA) outarg.flags |= FUSE_AUTO_INVAL_DATA; + if (f->conn.want & FUSE_CAP_READDIR_PLUS) + outarg.flags |= FUSE_DO_READDIRPLUS; outarg.max_readahead = f->conn.max_readahead; outarg.max_write = f->conn.max_write; if (f->conn.proto_minor >= 13) { @@ -2276,6 +2318,7 @@ static struct { [FUSE_DESTROY] = { do_destroy, "DESTROY" }, [FUSE_NOTIFY_REPLY] = { (void *) 1, "NOTIFY_REPLY" }, [FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" }, + [FUSE_READDIRPLUS] = { do_readdir_plus, "READDIRPLUS"}, [CUSE_INIT] = { cuse_lowlevel_init, "CUSE_INIT" }, }; @@ -2384,7 +2427,8 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC && in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR && in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR && - in->opcode != FUSE_NOTIFY_REPLY) + in->opcode != FUSE_NOTIFY_REPLY && + in->opcode != FUSE_READDIRPLUS) goto reply_err; err = ENOSYS; @@ -2483,6 +2527,7 @@ static const struct fuse_opt fuse_ll_opts[] = { { "no_splice_read", offsetof(struct fuse_ll, no_splice_read), 1}, { "auto_inval_data", offsetof(struct fuse_ll, auto_inval_data), 1}, { "no_auto_inval_data", offsetof(struct fuse_ll, no_auto_inval_data), 1}, + { "no_readdir_plus", offsetof(struct fuse_ll, no_readdir_plus), 1}, FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP), @@ -2515,6 +2560,7 @@ static void fuse_ll_help(void) " -o [no_]splice_move move data while splicing to the fuse device\n" " -o [no_]splice_read use splice to read from the fuse device\n" " -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n" +" -o [no_]readdir_plus use readdir_plus if possible.\n" ); } diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index ea2a1c8..ad5a940 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -51,6 +51,7 @@ FUSE_3.0 { fuse_reply_statfs; fuse_set_signal_handlers; fuse_add_direntry; + fuse_add_direntry_plus; fuse_chan_new; fuse_chan_recv; fuse_daemonize; diff --git a/test/stracedecode.c b/test/stracedecode.c index 27b883c..940438a 100644 --- a/test/stracedecode.c +++ b/test/stracedecode.c @@ -41,6 +41,7 @@ static struct { [FUSE_INTERRUPT] = { "INTERRUPT" }, [FUSE_BMAP] = { "BMAP" }, [FUSE_DESTROY] = { "DESTROY" }, + [FUSE_READDIRPLUS] = { "READDIRPLUS" }, }; #define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0])) -- 1.7.12.4 |
From: Feng S. <ste...@gm...> - 2013-01-11 08:59:32
|
Several caching logic changes have been made on the kernel side to better support network-based fuse filesystems. These include kernel side mtime checking and read path cache revalidation. The new caching logic is enabled through the FUSE_AUTO_INVAL_DATA init flag. Export this to the user via the '[no_]auto_inval_data' mount option. Changed in v2 - Rebase to FUSE 3.0. Signed-off-by: Feng Shuo <ste...@gm...> --- include/fuse_common.h | 23 ++++++++++++----------- include/fuse_kernel.h | 1 + lib/fuse_i.h | 2 ++ lib/fuse_lowlevel.c | 11 +++++++++++ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/fuse_common.h b/include/fuse_common.h index 0ae33a9..58458ab 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -100,17 +100,18 @@ struct fuse_file_info { * FUSE_CAP_SPLICE_READ: ability to use splice() to read from the fuse device * FUSE_CAP_IOCTL_DIR: ioctl support on directories */ -#define FUSE_CAP_ASYNC_READ (1 << 0) -#define FUSE_CAP_POSIX_LOCKS (1 << 1) -#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) -#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) -#define FUSE_CAP_BIG_WRITES (1 << 5) -#define FUSE_CAP_DONT_MASK (1 << 6) -#define FUSE_CAP_SPLICE_WRITE (1 << 7) -#define FUSE_CAP_SPLICE_MOVE (1 << 8) -#define FUSE_CAP_SPLICE_READ (1 << 9) -#define FUSE_CAP_FLOCK_LOCKS (1 << 10) -#define FUSE_CAP_IOCTL_DIR (1 << 11) +#define FUSE_CAP_ASYNC_READ (1 << 0) +#define FUSE_CAP_POSIX_LOCKS (1 << 1) +#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) +#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) +#define FUSE_CAP_BIG_WRITES (1 << 5) +#define FUSE_CAP_DONT_MASK (1 << 6) +#define FUSE_CAP_SPLICE_WRITE (1 << 7) +#define FUSE_CAP_SPLICE_MOVE (1 << 8) +#define FUSE_CAP_SPLICE_READ (1 << 9) +#define FUSE_CAP_FLOCK_LOCKS (1 << 10) +#define FUSE_CAP_IOCTL_DIR (1 << 11) +#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12) /** * Ioctl flags diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h index c632b58..60cd0c1 100644 --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -207,6 +207,7 @@ struct fuse_file_lock { #define FUSE_BIG_WRITES (1 << 5) #define FUSE_DONT_MASK (1 << 6) #define FUSE_FLOCK_LOCKS (1 << 10) +#define FUSE_AUTO_INVAL_DATA (1 << 12) /** * CUSE INIT request/reply flags diff --git a/lib/fuse_i.h b/lib/fuse_i.h index 1f1787e..225ff7d 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -71,6 +71,8 @@ struct fuse_ll { int no_splice_write; int no_splice_move; int no_splice_read; + int auto_inval_data; + int no_auto_inval_data; struct fuse_lowlevel_ops op; int got_init; struct cuse_data *cuse_data; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 4178d9a..4898a8a 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -1786,6 +1786,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.capable |= FUSE_CAP_DONT_MASK; if (arg->flags & FUSE_FLOCK_LOCKS) f->conn.capable |= FUSE_CAP_FLOCK_LOCKS; + if (arg->flags & FUSE_AUTO_INVAL_DATA) + f->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA; } else { f->conn.async_read = 0; f->conn.max_readahead = 0; @@ -1816,6 +1818,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.want |= FUSE_CAP_FLOCK_LOCKS; if (f->big_writes) f->conn.want |= FUSE_CAP_BIG_WRITES; + if (f->auto_inval_data) + f->conn.want |= FUSE_CAP_AUTO_INVAL_DATA; if (bufsize < FUSE_MIN_READ_BUFFER) { fprintf(stderr, "fuse: warning: buffer size too small: %zu\n", @@ -1837,6 +1841,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.want &= ~FUSE_CAP_SPLICE_WRITE; if (f->no_splice_move) f->conn.want &= ~FUSE_CAP_SPLICE_MOVE; + if (f->no_auto_inval_data) + f->conn.want &= ~FUSE_CAP_AUTO_INVAL_DATA; if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ)) outarg.flags |= FUSE_ASYNC_READ; @@ -1852,6 +1858,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) outarg.flags |= FUSE_DONT_MASK; if (f->conn.want & FUSE_CAP_FLOCK_LOCKS) outarg.flags |= FUSE_FLOCK_LOCKS; + if (f->conn.want & FUSE_CAP_AUTO_INVAL_DATA) + outarg.flags |= FUSE_AUTO_INVAL_DATA; outarg.max_readahead = f->conn.max_readahead; outarg.max_write = f->conn.max_write; if (f->conn.proto_minor >= 13) { @@ -2473,6 +2481,8 @@ static const struct fuse_opt fuse_ll_opts[] = { { "no_splice_move", offsetof(struct fuse_ll, no_splice_move), 1}, { "splice_read", offsetof(struct fuse_ll, splice_read), 1}, { "no_splice_read", offsetof(struct fuse_ll, no_splice_read), 1}, + { "auto_inval_data", offsetof(struct fuse_ll, auto_inval_data), 1}, + { "no_auto_inval_data", offsetof(struct fuse_ll, no_auto_inval_data), 1}, FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP), @@ -2504,6 +2514,7 @@ static void fuse_ll_help(void) " -o [no_]splice_write use splice to write to the fuse device\n" " -o [no_]splice_move move data while splicing to the fuse device\n" " -o [no_]splice_read use splice to read from the fuse device\n" +" -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n" ); } -- 1.7.12.4 |