diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-02-07 17:59:07 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-02-07 17:59:07 -0800 |
commit | f757165705e92db62f85a1ad287e9251d1f2cd82 (patch) | |
tree | 1b361224bb599a4e09df803b235ce75304825b58 /fs | |
parent | 175787e011cec507d8e2a1dbf37beef418499bc0 (diff) | |
parent | cabdb4fa2f666fad21b21b04c84709204f60af21 (diff) |
Merge tag 'fuse-fixes-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse fixes from Miklos Szeredi:
- Fix a regression introduced in v5.1 that triggers WARNINGs for some
fuse filesystems
- Fix an xfstest failure
- Allow overlayfs to be used on top of fuse/virtiofs
- Code and documentation cleanups
* tag 'fuse-fixes-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
fuse: use true,false for bool variable
Documentation: filesystems: convert fuse to RST
fuse: Support RENAME_WHITEOUT flag
fuse: don't overflow LLONG_MAX with end offset
fix up iter on short count in fuse_direct_io()
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fuse/cuse.c | 4 | ||||
-rw-r--r-- | fs/fuse/dir.c | 2 | ||||
-rw-r--r-- | fs/fuse/file.c | 21 | ||||
-rw-r--r-- | fs/fuse/inode.c | 14 | ||||
-rw-r--r-- | fs/fuse/readdir.c | 2 |
5 files changed, 29 insertions, 14 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 00015d851382..030f094910c3 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -451,8 +451,8 @@ static int cuse_send_init(struct cuse_conn *cc) ap->args.out_args[0].size = sizeof(ia->out); ap->args.out_args[0].value = &ia->out; ap->args.out_args[1].size = CUSE_INIT_INFO_MAX; - ap->args.out_argvar = 1; - ap->args.out_pages = 1; + ap->args.out_argvar = true; + ap->args.out_pages = true; ap->num_pages = 1; ap->pages = &ia->page; ap->descs = &ia->desc; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index ee190119f45c..de1e2fde60bd 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -818,7 +818,7 @@ static int fuse_rename2(struct inode *olddir, struct dentry *oldent, struct fuse_conn *fc = get_fuse_conn(olddir); int err; - if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) + if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) return -EINVAL; if (flags) { diff --git a/fs/fuse/file.c b/fs/fuse/file.c index ce715380143c..9d67b830fb7a 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -803,6 +803,10 @@ static int fuse_do_readpage(struct file *file, struct page *page) attr_ver = fuse_get_attr_version(fc); + /* Don't overflow end offset */ + if (pos + (desc.length - 1) == LLONG_MAX) + desc.length--; + fuse_read_args_fill(&ia, file, pos, desc.length, FUSE_READ); res = fuse_simple_request(fc, &ia.ap.args); if (res < 0) @@ -888,6 +892,14 @@ static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file) ap->args.out_pages = true; ap->args.page_zeroing = true; ap->args.page_replace = true; + + /* Don't overflow end offset */ + if (pos + (count - 1) == LLONG_MAX) { + count--; + ap->descs[ap->num_pages - 1].length--; + } + WARN_ON((loff_t) (pos + count) < 0); + fuse_read_args_fill(ia, file, pos, count, FUSE_READ); ia->read.attr_ver = fuse_get_attr_version(fc); if (fc->async_read) { @@ -1397,9 +1409,9 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, } if (write) - ap->args.in_pages = 1; + ap->args.in_pages = true; else - ap->args.out_pages = 1; + ap->args.out_pages = true; *nbytesp = nbytes; @@ -1465,6 +1477,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, } ia = NULL; if (nres < 0) { + iov_iter_revert(iter, nbytes); err = nres; break; } @@ -1473,8 +1486,10 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, count -= nres; res += nres; pos += nres; - if (nres != nbytes) + if (nres != nbytes) { + iov_iter_revert(iter, nbytes - nres); break; + } if (count) { max_pages = iov_iter_npages(iter, fc->max_pages); ia = fuse_io_alloc(io, max_pages); diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 16aec32f7f3d..77fef29ebe4f 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -494,36 +494,36 @@ static int fuse_parse_param(struct fs_context *fc, struct fs_parameter *param) case OPT_FD: ctx->fd = result.uint_32; - ctx->fd_present = 1; + ctx->fd_present = true; break; case OPT_ROOTMODE: if (!fuse_valid_type(result.uint_32)) return invalf(fc, "fuse: Invalid rootmode"); ctx->rootmode = result.uint_32; - ctx->rootmode_present = 1; + ctx->rootmode_present = true; break; case OPT_USER_ID: ctx->user_id = make_kuid(fc->user_ns, result.uint_32); if (!uid_valid(ctx->user_id)) return invalf(fc, "fuse: Invalid user_id"); - ctx->user_id_present = 1; + ctx->user_id_present = true; break; case OPT_GROUP_ID: ctx->group_id = make_kgid(fc->user_ns, result.uint_32); if (!gid_valid(ctx->group_id)) return invalf(fc, "fuse: Invalid group_id"); - ctx->group_id_present = 1; + ctx->group_id_present = true; break; case OPT_DEFAULT_PERMISSIONS: - ctx->default_permissions = 1; + ctx->default_permissions = true; break; case OPT_ALLOW_OTHER: - ctx->allow_other = 1; + ctx->allow_other = true; break; case OPT_MAX_READ: @@ -997,7 +997,7 @@ void fuse_send_init(struct fuse_conn *fc) /* Variable length argument used for backward compatibility with interface version < 7.5. Rest of init_out is zeroed by do_get_request(), so a short reply is not a problem */ - ia->args.out_argvar = 1; + ia->args.out_argvar = true; ia->args.out_args[0].size = sizeof(ia->out); ia->args.out_args[0].value = &ia->out; ia->args.force = true; diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c index 6a40f75a0d25..90e3f01bd796 100644 --- a/fs/fuse/readdir.c +++ b/fs/fuse/readdir.c @@ -332,7 +332,7 @@ static int fuse_readdir_uncached(struct file *file, struct dir_context *ctx) return -ENOMEM; plus = fuse_use_readdirplus(inode, ctx); - ap->args.out_pages = 1; + ap->args.out_pages = true; ap->num_pages = 1; ap->pages = &page; ap->descs = &desc; |