Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/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()
This commit is contained in:
commit
16d70e1529
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -1529,7 +1535,6 @@ 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);
|
||||
|
@ -1537,6 +1542,8 @@ static int fuse_writepage_locked(struct page *page)
|
|||
fuse_flush_writepages(inode);
|
||||
spin_unlock(&fc->lock);
|
||||
|
||||
end_page_writeback(page);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue