From 377f3d1b8b418f4497dac97fb8b6c433348330ce Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 9 Jun 2008 10:52:50 +0000 Subject: [PATCH] Don't allow bigger than 4kB writes by default... --- ChangeLog | 8 ++++++++ include/fuse_common.h | 24 +++++++++++++++++++++--- kernel/fuse_kernel.h | 1 + lib/fuse_lowlevel.c | 38 +++++++++++++++++++++++++++++--------- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 411df3c..84d92ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,14 @@ * Fix mounting over symlink. Reported by Szabolcs Szakacsits +2008-05-09 Miklos Szeredi + + * Don't allow bigger than 4kB writes by default on 2.6.26 and + later kernels, so that filesystems not expecting this are not + broken on a kernel upgrade. Provide a 'big_writes' mount option + to enable this feature. In future API revisions this may become + the default. + 2008-04-09 Miklos Szeredi * Update warning message for missing newline at end of fuse.conf diff --git a/include/fuse_common.h b/include/fuse_common.h index 1030139..2543225 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -76,6 +76,19 @@ struct fuse_file_info { uint64_t lock_owner; }; +/** + * Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' + * + * FUSE_CAP_ASYNC_READ: filesystem supports asynchronous read requests + * FUSE_CAP_POSIX_LOCKS: filesystem supports "remote" locking + * FUSE_CAP_ATOMIC_O_TRUNC: filesystem handles the O_TRUNC open flag + * FUSE_CAP_BIG_WRITES: filesystem can handle write size larger than 4kB + */ +#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_BIG_WRITES (1 << 5) + /** * Connection information, passed to the ->init() method * @@ -110,14 +123,19 @@ struct fuse_conn_info { unsigned max_readahead; /** - * Is atomic open+truncate supported + * Capability flags, that the kernel supports + */ + unsigned capable; + + /** + * Capability flags, that the filesystem wants to enable */ - unsigned atomic_o_trunc; + unsigned want; /** * For future use. */ - unsigned reserved[26]; + unsigned reserved[25]; }; struct fuse_session; diff --git a/kernel/fuse_kernel.h b/kernel/fuse_kernel.h index 53682cf..c9c4c7e 100644 --- a/kernel/fuse_kernel.h +++ b/kernel/fuse_kernel.h @@ -142,6 +142,7 @@ struct fuse_file_lock { #define FUSE_POSIX_LOCKS (1 << 1) #define FUSE_FILE_OPS (1 << 2) #define FUSE_ATOMIC_O_TRUNC (1 << 3) +#define FUSE_BIG_WRITES (1 << 5) /** * Release flags diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index bae6199..048b2cc 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -51,6 +51,8 @@ struct fuse_req { struct fuse_ll { int debug; int allow_root; + int atomic_o_trunc; + int big_writes; struct fuse_lowlevel_ops op; int got_init; void *userdata; @@ -1009,6 +1011,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) } f->conn.proto_major = arg->major; f->conn.proto_minor = arg->minor; + f->conn.capable = 0; + f->conn.want = 0; if (arg->major < 7) { fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n", @@ -1022,14 +1026,26 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.async_read = arg->flags & FUSE_ASYNC_READ; if (arg->max_readahead < f->conn.max_readahead) f->conn.max_readahead = arg->max_readahead; - if (f->conn.atomic_o_trunc) - f->conn.atomic_o_trunc = arg->flags & FUSE_ATOMIC_O_TRUNC; + if (arg->flags & FUSE_ASYNC_READ) + f->conn.capable |= FUSE_CAP_ASYNC_READ; + if (arg->flags & FUSE_POSIX_LOCKS) + f->conn.capable |= FUSE_CAP_POSIX_LOCKS; + if (arg->flags & FUSE_ATOMIC_O_TRUNC) + f->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC; + if (arg->flags & FUSE_BIG_WRITES) + f->conn.capable |= FUSE_CAP_BIG_WRITES; } else { f->conn.async_read = 0; f->conn.max_readahead = 0; - f->conn.atomic_o_trunc = 0; } + if (f->atomic_o_trunc) + f->conn.want |= FUSE_CAP_ATOMIC_O_TRUNC; + if (f->op.getlk && f->op.setlk) + f->conn.want |= FUSE_CAP_POSIX_LOCKS; + if (f->big_writes) + f->conn.want |= FUSE_CAP_BIG_WRITES; + if (bufsize < FUSE_MIN_READ_BUFFER) { fprintf(stderr, "fuse: warning: buffer size too small: %zu\n", bufsize); @@ -1047,12 +1063,14 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&outarg, 0, sizeof(outarg)); outarg.major = FUSE_KERNEL_VERSION; outarg.minor = FUSE_KERNEL_MINOR_VERSION; - if (f->conn.async_read) + if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ)) outarg.flags |= FUSE_ASYNC_READ; - if (f->op.getlk && f->op.setlk) + if (f->conn.want & FUSE_CAP_POSIX_LOCKS) outarg.flags |= FUSE_POSIX_LOCKS; - if (f->conn.atomic_o_trunc) + if (f->conn.want & FUSE_CAP_ATOMIC_O_TRUNC) outarg.flags |= FUSE_ATOMIC_O_TRUNC; + if (f->conn.want & FUSE_CAP_BIG_WRITES) + outarg.flags |= FUSE_BIG_WRITES; outarg.max_readahead = f->conn.max_readahead; outarg.max_write = f->conn.max_write; @@ -1233,7 +1251,8 @@ static struct fuse_opt fuse_ll_opts[] = { { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 }, { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 }, { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 }, - { "atomic_o_trunc", offsetof(struct fuse_ll, conn.atomic_o_trunc), 1}, + { "atomic_o_trunc", offsetof(struct fuse_ll, atomic_o_trunc), 1}, + { "big_writes", offsetof(struct fuse_ll, big_writes), 1}, FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD), FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP), @@ -1255,7 +1274,8 @@ static void fuse_ll_help(void) " -o max_readahead=N set maximum readahead\n" " -o async_read perform reads asynchronously (default)\n" " -o sync_read perform reads synchronously\n" -" -o atomic_o_trunc enable atomic open+truncate support\n"); +" -o atomic_o_trunc enable atomic open+truncate support\n" +" -o big_writes enable larger than 4kB writes\n"); } static int fuse_ll_opt_proc(void *data, const char *arg, int key, @@ -1327,7 +1347,7 @@ struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args, f->conn.async_read = 1; f->conn.max_write = UINT_MAX; f->conn.max_readahead = UINT_MAX; - f->conn.atomic_o_trunc = 0; + f->atomic_o_trunc = 0; list_init_req(&f->list); list_init_req(&f->interrupts); fuse_mutex_init(&f->lock); -- 2.30.2