|
@@ -754,6 +754,42 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
|
|
|
+{
|
|
|
+ struct inode *inode = mapping->host;
|
|
|
+ struct fuse_conn *fc = get_fuse_conn(inode);
|
|
|
+ struct fuse_req *req;
|
|
|
+ struct fuse_bmap_in inarg;
|
|
|
+ struct fuse_bmap_out outarg;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (!inode->i_sb->s_bdev || fc->no_bmap)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ req = fuse_get_req(fc);
|
|
|
+ if (IS_ERR(req))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ memset(&inarg, 0, sizeof(inarg));
|
|
|
+ inarg.block = block;
|
|
|
+ inarg.blocksize = inode->i_sb->s_blocksize;
|
|
|
+ req->in.h.opcode = FUSE_BMAP;
|
|
|
+ req->in.h.nodeid = get_node_id(inode);
|
|
|
+ req->in.numargs = 1;
|
|
|
+ req->in.args[0].size = sizeof(inarg);
|
|
|
+ req->in.args[0].value = &inarg;
|
|
|
+ req->out.numargs = 1;
|
|
|
+ req->out.args[0].size = sizeof(outarg);
|
|
|
+ req->out.args[0].value = &outarg;
|
|
|
+ request_send(fc, req);
|
|
|
+ err = req->out.h.error;
|
|
|
+ fuse_put_request(fc, req);
|
|
|
+ if (err == -ENOSYS)
|
|
|
+ fc->no_bmap = 1;
|
|
|
+
|
|
|
+ return err ? 0 : outarg.block;
|
|
|
+}
|
|
|
+
|
|
|
static const struct file_operations fuse_file_operations = {
|
|
|
.llseek = generic_file_llseek,
|
|
|
.read = do_sync_read,
|
|
@@ -787,6 +823,7 @@ static const struct address_space_operations fuse_file_aops = {
|
|
|
.commit_write = fuse_commit_write,
|
|
|
.readpages = fuse_readpages,
|
|
|
.set_page_dirty = fuse_set_page_dirty,
|
|
|
+ .bmap = fuse_bmap,
|
|
|
};
|
|
|
|
|
|
void fuse_init_file_inode(struct inode *inode)
|