aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-09 12:18:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-09 12:18:23 -0400
commit16d70e15295953b19ecf59e943723a181782b856 (patch)
tree3d8cc1991b02ed703dc551c5558452b5c5f462f5 /fs
parent6c337ad6cccf3365c89152896217be9d953121c6 (diff)
parent05726acabef10faffcbc400c109ddb6c9d7560e4 (diff)
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()
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/dev.c6
-rw-r--r--fs/fuse/dir.c15
-rw-r--r--fs/fuse/file.c11
-rw-r--r--fs/fuse/fuse_i.h2
-rw-r--r--fs/fuse/inode.c3
5 files changed, 29 insertions, 8 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 1d55f9465400..ef74ad5fd362 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1765,11 +1765,9 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
1765/* Look up request on processing list by unique ID */ 1765/* Look up request on processing list by unique ID */
1766static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique) 1766static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
1767{ 1767{
1768 struct list_head *entry; 1768 struct fuse_req *req;
1769 1769
1770 list_for_each(entry, &fc->processing) { 1770 list_for_each_entry(req, &fc->processing, list) {
1771 struct fuse_req *req;
1772 req = list_entry(entry, struct fuse_req, list);
1773 if (req->in.h.unique == unique || req->intr_unique == unique) 1771 if (req->in.h.unique == unique || req->intr_unique == unique)
1774 return req; 1772 return req;
1775 } 1773 }
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 0e6961aae6c0..3ac91086f41f 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1177,6 +1177,8 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
1177 return -EIO; 1177 return -EIO;
1178 if (reclen > nbytes) 1178 if (reclen > nbytes)
1179 break; 1179 break;
1180 if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1181 return -EIO;
1180 1182
1181 if (!dir_emit(ctx, dirent->name, dirent->namelen, 1183 if (!dir_emit(ctx, dirent->name, dirent->namelen,
1182 dirent->ino, dirent->type)) 1184 dirent->ino, dirent->type))
@@ -1315,6 +1317,8 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
1315 return -EIO; 1317 return -EIO;
1316 if (reclen > nbytes) 1318 if (reclen > nbytes)
1317 break; 1319 break;
1320 if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1321 return -EIO;
1318 1322
1319 if (!over) { 1323 if (!over) {
1320 /* We fill entries into dstbuf only as much as 1324 /* We fill entries into dstbuf only as much as
@@ -1585,6 +1589,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
1585 struct file *file) 1589 struct file *file)
1586{ 1590{
1587 struct fuse_conn *fc = get_fuse_conn(inode); 1591 struct fuse_conn *fc = get_fuse_conn(inode);
1592 struct fuse_inode *fi = get_fuse_inode(inode);
1588 struct fuse_req *req; 1593 struct fuse_req *req;
1589 struct fuse_setattr_in inarg; 1594 struct fuse_setattr_in inarg;
1590 struct fuse_attr_out outarg; 1595 struct fuse_attr_out outarg;
@@ -1612,8 +1617,10 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
1612 if (IS_ERR(req)) 1617 if (IS_ERR(req))
1613 return PTR_ERR(req); 1618 return PTR_ERR(req);
1614 1619
1615 if (is_truncate) 1620 if (is_truncate) {
1616 fuse_set_nowrite(inode); 1621 fuse_set_nowrite(inode);
1622 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1623 }
1617 1624
1618 memset(&inarg, 0, sizeof(inarg)); 1625 memset(&inarg, 0, sizeof(inarg));
1619 memset(&outarg, 0, sizeof(outarg)); 1626 memset(&outarg, 0, sizeof(outarg));
@@ -1675,12 +1682,14 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
1675 invalidate_inode_pages2(inode->i_mapping); 1682 invalidate_inode_pages2(inode->i_mapping);
1676 } 1683 }
1677 1684
1685 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1678 return 0; 1686 return 0;
1679 1687
1680error: 1688error:
1681 if (is_truncate) 1689 if (is_truncate)
1682 fuse_release_nowrite(inode); 1690 fuse_release_nowrite(inode);
1683 1691
1692 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1684 return err; 1693 return err;
1685} 1694}
1686 1695
@@ -1744,6 +1753,8 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
1744 fc->no_setxattr = 1; 1753 fc->no_setxattr = 1;
1745 err = -EOPNOTSUPP; 1754 err = -EOPNOTSUPP;
1746 } 1755 }
1756 if (!err)
1757 fuse_invalidate_attr(inode);
1747 return err; 1758 return err;
1748} 1759}
1749 1760
@@ -1873,6 +1884,8 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
1873 fc->no_removexattr = 1; 1884 fc->no_removexattr = 1;
1874 err = -EOPNOTSUPP; 1885 err = -EOPNOTSUPP;
1875 } 1886 }
1887 if (!err)
1888 fuse_invalidate_attr(inode);
1876 return err; 1889 return err;
1877} 1890}
1878 1891
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 5c121fe19c5f..d409deafc67b 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -629,7 +629,8 @@ static void fuse_read_update_size(struct inode *inode, loff_t size,
629 struct fuse_inode *fi = get_fuse_inode(inode); 629 struct fuse_inode *fi = get_fuse_inode(inode);
630 630
631 spin_lock(&fc->lock); 631 spin_lock(&fc->lock);
632 if (attr_ver == fi->attr_version && size < inode->i_size) { 632 if (attr_ver == fi->attr_version && size < inode->i_size &&
633 !test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) {
633 fi->attr_version = ++fc->attr_version; 634 fi->attr_version = ++fc->attr_version;
634 i_size_write(inode, size); 635 i_size_write(inode, size);
635 } 636 }
@@ -1032,12 +1033,16 @@ static ssize_t fuse_perform_write(struct file *file,
1032{ 1033{
1033 struct inode *inode = mapping->host; 1034 struct inode *inode = mapping->host;
1034 struct fuse_conn *fc = get_fuse_conn(inode); 1035 struct fuse_conn *fc = get_fuse_conn(inode);
1036 struct fuse_inode *fi = get_fuse_inode(inode);
1035 int err = 0; 1037 int err = 0;
1036 ssize_t res = 0; 1038 ssize_t res = 0;
1037 1039
1038 if (is_bad_inode(inode)) 1040 if (is_bad_inode(inode))
1039 return -EIO; 1041 return -EIO;
1040 1042
1043 if (inode->i_size < pos + iov_iter_count(ii))
1044 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1045
1041 do { 1046 do {
1042 struct fuse_req *req; 1047 struct fuse_req *req;
1043 ssize_t count; 1048 ssize_t count;
@@ -1073,6 +1078,7 @@ static ssize_t fuse_perform_write(struct file *file,
1073 if (res > 0) 1078 if (res > 0)
1074 fuse_write_update_size(inode, pos); 1079 fuse_write_update_size(inode, pos);
1075 1080
1081 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1076 fuse_invalidate_attr(inode); 1082 fuse_invalidate_attr(inode);
1077 1083
1078 return res > 0 ? res : err; 1084 return res > 0 ? res : err;
@@ -1529,7 +1535,6 @@ static int fuse_writepage_locked(struct page *page)
1529 1535
1530 inc_bdi_stat(mapping->backing_dev_info, BDI_WRITEBACK); 1536 inc_bdi_stat(mapping->backing_dev_info, BDI_WRITEBACK);
1531 inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP); 1537 inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP);
1532 end_page_writeback(page);
1533 1538
1534 spin_lock(&fc->lock); 1539 spin_lock(&fc->lock);
1535 list_add(&req->writepages_entry, &fi->writepages); 1540 list_add(&req->writepages_entry, &fi->writepages);
@@ -1537,6 +1542,8 @@ static int fuse_writepage_locked(struct page *page)
1537 fuse_flush_writepages(inode); 1542 fuse_flush_writepages(inode);
1538 spin_unlock(&fc->lock); 1543 spin_unlock(&fc->lock);
1539 1544
1545 end_page_writeback(page);
1546
1540 return 0; 1547 return 0;
1541 1548
1542err_free: 1549err_free:
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index fde7249a3a96..5ced199b50bb 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -115,6 +115,8 @@ struct fuse_inode {
115enum { 115enum {
116 /** Advise readdirplus */ 116 /** Advise readdirplus */
117 FUSE_I_ADVISE_RDPLUS, 117 FUSE_I_ADVISE_RDPLUS,
118 /** An operation changing file size is in progress */
119 FUSE_I_SIZE_UNSTABLE,
118}; 120};
119 121
120struct fuse_conn; 122struct fuse_conn;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 0b578598c6ac..e0fe703ee3d6 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -201,7 +201,8 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
201 struct timespec old_mtime; 201 struct timespec old_mtime;
202 202
203 spin_lock(&fc->lock); 203 spin_lock(&fc->lock);
204 if (attr_version != 0 && fi->attr_version > attr_version) { 204 if ((attr_version != 0 && fi->attr_version > attr_version) ||
205 test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) {
205 spin_unlock(&fc->lock); 206 spin_unlock(&fc->lock);
206 return; 207 return;
207 } 208 }