Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/mszeredi/fuse

Pull fuse bugfixes from Miklos Szeredi:
 "Just a bunch of bugfixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
  fuse: use list_for_each_entry() for list traversing
  fuse: readdir: check for slash in names
  fuse: hotfix truncate_pagecache() issue
  fuse: invalidate inode attributes on xattr modification
  fuse: postpone end_page_writeback() in fuse_writepage_locked()
  • Loading branch information
Linus Torvalds committed Sep 9, 2013
2 parents 6c337ad + 05726ac commit 16d70e1
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 8 deletions.
6 changes: 2 additions & 4 deletions fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1765,11 +1765,9 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
/* Look up request on processing list by unique ID */
static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
{
struct list_head *entry;
struct fuse_req *req;

list_for_each(entry, &fc->processing) {
struct fuse_req *req;
req = list_entry(entry, struct fuse_req, list);
list_for_each_entry(req, &fc->processing, list) {
if (req->in.h.unique == unique || req->intr_unique == unique)
return req;
}
Expand Down
15 changes: 14 additions & 1 deletion fs/fuse/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,8 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
return -EIO;
if (reclen > nbytes)
break;
if (memchr(dirent->name, '/', dirent->namelen) != NULL)
return -EIO;

if (!dir_emit(ctx, dirent->name, dirent->namelen,
dirent->ino, dirent->type))
Expand Down Expand Up @@ -1315,6 +1317,8 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
return -EIO;
if (reclen > nbytes)
break;
if (memchr(dirent->name, '/', dirent->namelen) != NULL)
return -EIO;

if (!over) {
/* We fill entries into dstbuf only as much as
Expand Down Expand Up @@ -1585,6 +1589,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
struct file *file)
{
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_req *req;
struct fuse_setattr_in inarg;
struct fuse_attr_out outarg;
Expand Down Expand Up @@ -1612,8 +1617,10 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
if (IS_ERR(req))
return PTR_ERR(req);

if (is_truncate)
if (is_truncate) {
fuse_set_nowrite(inode);
set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
}

memset(&inarg, 0, sizeof(inarg));
memset(&outarg, 0, sizeof(outarg));
Expand Down Expand Up @@ -1675,12 +1682,14 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
invalidate_inode_pages2(inode->i_mapping);
}

clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
return 0;

error:
if (is_truncate)
fuse_release_nowrite(inode);

clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
return err;
}

Expand Down Expand Up @@ -1744,6 +1753,8 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
fc->no_setxattr = 1;
err = -EOPNOTSUPP;
}
if (!err)
fuse_invalidate_attr(inode);
return err;
}

Expand Down Expand Up @@ -1873,6 +1884,8 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
fc->no_removexattr = 1;
err = -EOPNOTSUPP;
}
if (!err)
fuse_invalidate_attr(inode);
return err;
}

Expand Down
11 changes: 9 additions & 2 deletions fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,8 @@ static void fuse_read_update_size(struct inode *inode, loff_t size,
struct fuse_inode *fi = get_fuse_inode(inode);

spin_lock(&fc->lock);
if (attr_ver == fi->attr_version && size < inode->i_size) {
if (attr_ver == fi->attr_version && size < inode->i_size &&
!test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) {
fi->attr_version = ++fc->attr_version;
i_size_write(inode, size);
}
Expand Down Expand Up @@ -1032,12 +1033,16 @@ static ssize_t fuse_perform_write(struct file *file,
{
struct inode *inode = mapping->host;
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_inode *fi = get_fuse_inode(inode);
int err = 0;
ssize_t res = 0;

if (is_bad_inode(inode))
return -EIO;

if (inode->i_size < pos + iov_iter_count(ii))
set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);

do {
struct fuse_req *req;
ssize_t count;
Expand Down Expand Up @@ -1073,6 +1078,7 @@ static ssize_t fuse_perform_write(struct file *file,
if (res > 0)
fuse_write_update_size(inode, pos);

clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
fuse_invalidate_attr(inode);

return res > 0 ? res : err;
Expand Down Expand Up @@ -1529,14 +1535,15 @@ static int fuse_writepage_locked(struct page *page)

inc_bdi_stat(mapping->backing_dev_info, BDI_WRITEBACK);
inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP);
end_page_writeback(page);

spin_lock(&fc->lock);
list_add(&req->writepages_entry, &fi->writepages);
list_add_tail(&req->list, &fi->queued_writes);
fuse_flush_writepages(inode);
spin_unlock(&fc->lock);

end_page_writeback(page);

return 0;

err_free:
Expand Down
2 changes: 2 additions & 0 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ struct fuse_inode {
enum {
/** Advise readdirplus */
FUSE_I_ADVISE_RDPLUS,
/** An operation changing file size is in progress */
FUSE_I_SIZE_UNSTABLE,
};

struct fuse_conn;
Expand Down
3 changes: 2 additions & 1 deletion fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
struct timespec old_mtime;

spin_lock(&fc->lock);
if (attr_version != 0 && fi->attr_version > attr_version) {
if ((attr_version != 0 && fi->attr_version > attr_version) ||
test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) {
spin_unlock(&fc->lock);
return;
}
Expand Down

0 comments on commit 16d70e1

Please sign in to comment.