Skip to content

Commit 16d70e1

Browse files
committed
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()
2 parents 6c337ad + 05726ac commit 16d70e1

File tree

5 files changed

+29
-8
lines changed

5 files changed

+29
-8
lines changed

fs/fuse/dev.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,11 +1765,9 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
17651765
/* Look up request on processing list by unique ID */
17661766
static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
17671767
{
1768-
struct list_head *entry;
1768+
struct fuse_req *req;
17691769

1770-
list_for_each(entry, &fc->processing) {
1771-
struct fuse_req *req;
1772-
req = list_entry(entry, struct fuse_req, list);
1770+
list_for_each_entry(req, &fc->processing, list) {
17731771
if (req->in.h.unique == unique || req->intr_unique == unique)
17741772
return req;
17751773
}

fs/fuse/dir.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,8 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
11771177
return -EIO;
11781178
if (reclen > nbytes)
11791179
break;
1180+
if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1181+
return -EIO;
11801182

11811183
if (!dir_emit(ctx, dirent->name, dirent->namelen,
11821184
dirent->ino, dirent->type))
@@ -1315,6 +1317,8 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
13151317
return -EIO;
13161318
if (reclen > nbytes)
13171319
break;
1320+
if (memchr(dirent->name, '/', dirent->namelen) != NULL)
1321+
return -EIO;
13181322

13191323
if (!over) {
13201324
/* We fill entries into dstbuf only as much as
@@ -1585,6 +1589,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
15851589
struct file *file)
15861590
{
15871591
struct fuse_conn *fc = get_fuse_conn(inode);
1592+
struct fuse_inode *fi = get_fuse_inode(inode);
15881593
struct fuse_req *req;
15891594
struct fuse_setattr_in inarg;
15901595
struct fuse_attr_out outarg;
@@ -1612,8 +1617,10 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
16121617
if (IS_ERR(req))
16131618
return PTR_ERR(req);
16141619

1615-
if (is_truncate)
1620+
if (is_truncate) {
16161621
fuse_set_nowrite(inode);
1622+
set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1623+
}
16171624

16181625
memset(&inarg, 0, sizeof(inarg));
16191626
memset(&outarg, 0, sizeof(outarg));
@@ -1675,12 +1682,14 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
16751682
invalidate_inode_pages2(inode->i_mapping);
16761683
}
16771684

1685+
clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
16781686
return 0;
16791687

16801688
error:
16811689
if (is_truncate)
16821690
fuse_release_nowrite(inode);
16831691

1692+
clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
16841693
return err;
16851694
}
16861695

@@ -1744,6 +1753,8 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
17441753
fc->no_setxattr = 1;
17451754
err = -EOPNOTSUPP;
17461755
}
1756+
if (!err)
1757+
fuse_invalidate_attr(inode);
17471758
return err;
17481759
}
17491760

@@ -1873,6 +1884,8 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
18731884
fc->no_removexattr = 1;
18741885
err = -EOPNOTSUPP;
18751886
}
1887+
if (!err)
1888+
fuse_invalidate_attr(inode);
18761889
return err;
18771890
}
18781891

fs/fuse/file.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,8 @@ static void fuse_read_update_size(struct inode *inode, loff_t size,
629629
struct fuse_inode *fi = get_fuse_inode(inode);
630630

631631
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)) {
633634
fi->attr_version = ++fc->attr_version;
634635
i_size_write(inode, size);
635636
}
@@ -1032,12 +1033,16 @@ static ssize_t fuse_perform_write(struct file *file,
10321033
{
10331034
struct inode *inode = mapping->host;
10341035
struct fuse_conn *fc = get_fuse_conn(inode);
1036+
struct fuse_inode *fi = get_fuse_inode(inode);
10351037
int err = 0;
10361038
ssize_t res = 0;
10371039

10381040
if (is_bad_inode(inode))
10391041
return -EIO;
10401042

1043+
if (inode->i_size < pos + iov_iter_count(ii))
1044+
set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
1045+
10411046
do {
10421047
struct fuse_req *req;
10431048
ssize_t count;
@@ -1073,6 +1078,7 @@ static ssize_t fuse_perform_write(struct file *file,
10731078
if (res > 0)
10741079
fuse_write_update_size(inode, pos);
10751080

1081+
clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
10761082
fuse_invalidate_attr(inode);
10771083

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

15301536
inc_bdi_stat(mapping->backing_dev_info, BDI_WRITEBACK);
15311537
inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP);
1532-
end_page_writeback(page);
15331538

15341539
spin_lock(&fc->lock);
15351540
list_add(&req->writepages_entry, &fi->writepages);
15361541
list_add_tail(&req->list, &fi->queued_writes);
15371542
fuse_flush_writepages(inode);
15381543
spin_unlock(&fc->lock);
15391544

1545+
end_page_writeback(page);
1546+
15401547
return 0;
15411548

15421549
err_free:

fs/fuse/fuse_i.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ struct fuse_inode {
115115
enum {
116116
/** Advise readdirplus */
117117
FUSE_I_ADVISE_RDPLUS,
118+
/** An operation changing file size is in progress */
119+
FUSE_I_SIZE_UNSTABLE,
118120
};
119121

120122
struct fuse_conn;

fs/fuse/inode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
201201
struct timespec old_mtime;
202202

203203
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)) {
205206
spin_unlock(&fc->lock);
206207
return;
207208
}

0 commit comments

Comments
 (0)