diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 12:18:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 12:18:23 -0400 |
commit | 16d70e15295953b19ecf59e943723a181782b856 (patch) | |
tree | 3d8cc1991b02ed703dc551c5558452b5c5f462f5 /fs | |
parent | 6c337ad6cccf3365c89152896217be9d953121c6 (diff) | |
parent | 05726acabef10faffcbc400c109ddb6c9d7560e4 (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.c | 6 | ||||
-rw-r--r-- | fs/fuse/dir.c | 15 | ||||
-rw-r--r-- | fs/fuse/file.c | 11 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 2 | ||||
-rw-r--r-- | fs/fuse/inode.c | 3 |
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 */ |
1766 | static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique) | 1766 | static 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 | ||
1680 | error: | 1688 | error: |
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 | ||
1542 | err_free: | 1549 | err_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 { | |||
115 | enum { | 115 | enum { |
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 | ||
120 | struct fuse_conn; | 122 | struct 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 | } |