diff options
| -rw-r--r-- | fs/fuse/dir.c | 17 | ||||
| -rw-r--r-- | fs/fuse/file.c | 22 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 3 |
3 files changed, 32 insertions, 10 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index ff15522481d4..254df56b847b 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -1562,10 +1562,9 @@ void fuse_release_nowrite(struct inode *inode) | |||
| 1562 | * vmtruncate() doesn't allow for this case, so do the rlimit checking | 1562 | * vmtruncate() doesn't allow for this case, so do the rlimit checking |
| 1563 | * and the actual truncation by hand. | 1563 | * and the actual truncation by hand. |
| 1564 | */ | 1564 | */ |
| 1565 | static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, | 1565 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, |
| 1566 | struct file *file) | 1566 | struct file *file) |
| 1567 | { | 1567 | { |
| 1568 | struct inode *inode = entry->d_inode; | ||
| 1569 | struct fuse_conn *fc = get_fuse_conn(inode); | 1568 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 1570 | struct fuse_req *req; | 1569 | struct fuse_req *req; |
| 1571 | struct fuse_setattr_in inarg; | 1570 | struct fuse_setattr_in inarg; |
| @@ -1574,9 +1573,6 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, | |||
| 1574 | loff_t oldsize; | 1573 | loff_t oldsize; |
| 1575 | int err; | 1574 | int err; |
| 1576 | 1575 | ||
| 1577 | if (!fuse_allow_current_process(fc)) | ||
| 1578 | return -EACCES; | ||
| 1579 | |||
| 1580 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) | 1576 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) |
| 1581 | attr->ia_valid |= ATTR_FORCE; | 1577 | attr->ia_valid |= ATTR_FORCE; |
| 1582 | 1578 | ||
| @@ -1671,10 +1667,15 @@ error: | |||
| 1671 | 1667 | ||
| 1672 | static int fuse_setattr(struct dentry *entry, struct iattr *attr) | 1668 | static int fuse_setattr(struct dentry *entry, struct iattr *attr) |
| 1673 | { | 1669 | { |
| 1670 | struct inode *inode = entry->d_inode; | ||
| 1671 | |||
| 1672 | if (!fuse_allow_current_process(get_fuse_conn(inode))) | ||
| 1673 | return -EACCES; | ||
| 1674 | |||
| 1674 | if (attr->ia_valid & ATTR_FILE) | 1675 | if (attr->ia_valid & ATTR_FILE) |
| 1675 | return fuse_do_setattr(entry, attr, attr->ia_file); | 1676 | return fuse_do_setattr(inode, attr, attr->ia_file); |
| 1676 | else | 1677 | else |
| 1677 | return fuse_do_setattr(entry, attr, NULL); | 1678 | return fuse_do_setattr(inode, attr, NULL); |
| 1678 | } | 1679 | } |
| 1679 | 1680 | ||
| 1680 | static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, | 1681 | static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 8f39f7b8cef2..1f8e3d60dc07 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -2352,6 +2352,20 @@ int fuse_notify_poll_wakeup(struct fuse_conn *fc, | |||
| 2352 | return 0; | 2352 | return 0; |
| 2353 | } | 2353 | } |
| 2354 | 2354 | ||
| 2355 | static void fuse_do_truncate(struct file *file) | ||
| 2356 | { | ||
| 2357 | struct inode *inode = file->f_mapping->host; | ||
| 2358 | struct iattr attr; | ||
| 2359 | |||
| 2360 | attr.ia_valid = ATTR_SIZE; | ||
| 2361 | attr.ia_size = i_size_read(inode); | ||
| 2362 | |||
| 2363 | attr.ia_file = file; | ||
| 2364 | attr.ia_valid |= ATTR_FILE; | ||
| 2365 | |||
| 2366 | fuse_do_setattr(inode, &attr, file); | ||
| 2367 | } | ||
| 2368 | |||
| 2355 | static ssize_t | 2369 | static ssize_t |
| 2356 | fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | 2370 | fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, |
| 2357 | loff_t offset, unsigned long nr_segs) | 2371 | loff_t offset, unsigned long nr_segs) |
| @@ -2419,8 +2433,12 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
| 2419 | kfree(io); | 2433 | kfree(io); |
| 2420 | } | 2434 | } |
| 2421 | 2435 | ||
| 2422 | if (rw == WRITE && ret > 0) | 2436 | if (rw == WRITE) { |
| 2423 | fuse_write_update_size(inode, pos); | 2437 | if (ret > 0) |
| 2438 | fuse_write_update_size(inode, pos); | ||
| 2439 | else if (ret < 0 && offset + count > i_size) | ||
| 2440 | fuse_do_truncate(file); | ||
| 2441 | } | ||
| 2424 | 2442 | ||
| 2425 | return ret; | 2443 | return ret; |
| 2426 | } | 2444 | } |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 337169a406c9..53b830e3b38f 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
| @@ -863,4 +863,7 @@ int fuse_dev_release(struct inode *inode, struct file *file); | |||
| 863 | 863 | ||
| 864 | void fuse_write_update_size(struct inode *inode, loff_t pos); | 864 | void fuse_write_update_size(struct inode *inode, loff_t pos); |
| 865 | 865 | ||
| 866 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, | ||
| 867 | struct file *file); | ||
| 868 | |||
| 866 | #endif /* _FS_FUSE_I_H */ | 869 | #endif /* _FS_FUSE_I_H */ |
