aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dir.c2
-rw-r--r--fs/fuse/file.c37
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--include/linux/fuse.h11
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
757static 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
757static const struct file_operations fuse_file_operations = { 793static 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
792void fuse_init_file_inode(struct inode *inode) 829void 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
306struct fuse_bmap_in {
307 __u64 block;
308 __u32 blocksize;
309 __u32 padding;
310};
311
312struct fuse_bmap_out {
313 __u64 block;
314};
315
305struct fuse_in_header { 316struct fuse_in_header {
306 __u32 len; 317 __u32 len;
307 __u32 opcode; 318 __u32 opcode;