diff options
-rw-r--r-- | fs/fuse/dir.c | 2 | ||||
-rw-r--r-- | fs/fuse/file.c | 37 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 3 | ||||
-rw-r--r-- | include/linux/fuse.h | 11 |
4 files changed, 53 insertions, 0 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 677f3ed7f987..1cabdb229adb 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -1024,6 +1024,8 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) | |||
1024 | if (attr->ia_valid & ATTR_SIZE) { | 1024 | if (attr->ia_valid & ATTR_SIZE) { |
1025 | unsigned long limit; | 1025 | unsigned long limit; |
1026 | is_truncate = 1; | 1026 | is_truncate = 1; |
1027 | if (IS_SWAPFILE(inode)) | ||
1028 | return -ETXTBSY; | ||
1027 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; | 1029 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; |
1028 | if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) { | 1030 | if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) { |
1029 | send_sig(SIGXFSZ, current, 0); | 1031 | send_sig(SIGXFSZ, current, 0); |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 763a50daf1c0..128f79c40803 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -754,6 +754,42 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl) | |||
754 | return err; | 754 | return err; |
755 | } | 755 | } |
756 | 756 | ||
757 | static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | ||
758 | { | ||
759 | struct inode *inode = mapping->host; | ||
760 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
761 | struct fuse_req *req; | ||
762 | struct fuse_bmap_in inarg; | ||
763 | struct fuse_bmap_out outarg; | ||
764 | int err; | ||
765 | |||
766 | if (!inode->i_sb->s_bdev || fc->no_bmap) | ||
767 | return 0; | ||
768 | |||
769 | req = fuse_get_req(fc); | ||
770 | if (IS_ERR(req)) | ||
771 | return 0; | ||
772 | |||
773 | memset(&inarg, 0, sizeof(inarg)); | ||
774 | inarg.block = block; | ||
775 | inarg.blocksize = inode->i_sb->s_blocksize; | ||
776 | req->in.h.opcode = FUSE_BMAP; | ||
777 | req->in.h.nodeid = get_node_id(inode); | ||
778 | req->in.numargs = 1; | ||
779 | req->in.args[0].size = sizeof(inarg); | ||
780 | req->in.args[0].value = &inarg; | ||
781 | req->out.numargs = 1; | ||
782 | req->out.args[0].size = sizeof(outarg); | ||
783 | req->out.args[0].value = &outarg; | ||
784 | request_send(fc, req); | ||
785 | err = req->out.h.error; | ||
786 | fuse_put_request(fc, req); | ||
787 | if (err == -ENOSYS) | ||
788 | fc->no_bmap = 1; | ||
789 | |||
790 | return err ? 0 : outarg.block; | ||
791 | } | ||
792 | |||
757 | static const struct file_operations fuse_file_operations = { | 793 | static const struct file_operations fuse_file_operations = { |
758 | .llseek = generic_file_llseek, | 794 | .llseek = generic_file_llseek, |
759 | .read = do_sync_read, | 795 | .read = do_sync_read, |
@@ -787,6 +823,7 @@ static const struct address_space_operations fuse_file_aops = { | |||
787 | .commit_write = fuse_commit_write, | 823 | .commit_write = fuse_commit_write, |
788 | .readpages = fuse_readpages, | 824 | .readpages = fuse_readpages, |
789 | .set_page_dirty = fuse_set_page_dirty, | 825 | .set_page_dirty = fuse_set_page_dirty, |
826 | .bmap = fuse_bmap, | ||
790 | }; | 827 | }; |
791 | 828 | ||
792 | void fuse_init_file_inode(struct inode *inode) | 829 | void fuse_init_file_inode(struct inode *inode) |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 91edb8932d90..58d482d9f6bb 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -339,6 +339,9 @@ struct fuse_conn { | |||
339 | /** Is interrupt not implemented by fs? */ | 339 | /** Is interrupt not implemented by fs? */ |
340 | unsigned no_interrupt : 1; | 340 | unsigned no_interrupt : 1; |
341 | 341 | ||
342 | /** Is bmap not implemented by fs? */ | ||
343 | unsigned no_bmap : 1; | ||
344 | |||
342 | /** The number of requests waiting for completion */ | 345 | /** The number of requests waiting for completion */ |
343 | atomic_t num_waiting; | 346 | atomic_t num_waiting; |
344 | 347 | ||
diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 76336327a941..162a754f4db7 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h | |||
@@ -132,6 +132,7 @@ enum fuse_opcode { | |||
132 | FUSE_ACCESS = 34, | 132 | FUSE_ACCESS = 34, |
133 | FUSE_CREATE = 35, | 133 | FUSE_CREATE = 35, |
134 | FUSE_INTERRUPT = 36, | 134 | FUSE_INTERRUPT = 36, |
135 | FUSE_BMAP = 37, | ||
135 | }; | 136 | }; |
136 | 137 | ||
137 | /* The read buffer is required to be at least 8k, but may be much larger */ | 138 | /* The read buffer is required to be at least 8k, but may be much larger */ |
@@ -302,6 +303,16 @@ struct fuse_interrupt_in { | |||
302 | __u64 unique; | 303 | __u64 unique; |
303 | }; | 304 | }; |
304 | 305 | ||
306 | struct fuse_bmap_in { | ||
307 | __u64 block; | ||
308 | __u32 blocksize; | ||
309 | __u32 padding; | ||
310 | }; | ||
311 | |||
312 | struct fuse_bmap_out { | ||
313 | __u64 block; | ||
314 | }; | ||
315 | |||
305 | struct fuse_in_header { | 316 | struct fuse_in_header { |
306 | __u32 len; | 317 | __u32 len; |
307 | __u32 opcode; | 318 | __u32 opcode; |