Skip to content

Commit

Permalink
[PATCH] fuse: add bmap support
Browse files Browse the repository at this point in the history
Add support for the BMAP operation for block device based filesystems.  This
is needed to support swap-files and lilo.

Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Miklos Szeredi authored and Linus Torvalds committed Dec 7, 2006
1 parent d809161 commit b2d2272
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 0 deletions.
2 changes: 2 additions & 0 deletions fs/fuse/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,8 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
if (attr->ia_valid & ATTR_SIZE) {
unsigned long limit;
is_truncate = 1;
if (IS_SWAPFILE(inode))
return -ETXTBSY;
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
send_sig(SIGXFSZ, current, 0);
Expand Down
37 changes: 37 additions & 0 deletions fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,9 @@ struct fuse_conn {
/** Is interrupt not implemented by fs? */
unsigned no_interrupt : 1;

/** Is bmap not implemented by fs? */
unsigned no_bmap : 1;

/** The number of requests waiting for completion */
atomic_t num_waiting;

Expand Down
11 changes: 11 additions & 0 deletions include/linux/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ enum fuse_opcode {
FUSE_ACCESS = 34,
FUSE_CREATE = 35,
FUSE_INTERRUPT = 36,
FUSE_BMAP = 37,
};

/* The read buffer is required to be at least 8k, but may be much larger */
Expand Down Expand Up @@ -302,6 +303,16 @@ struct fuse_interrupt_in {
__u64 unique;
};

struct fuse_bmap_in {
__u64 block;
__u32 blocksize;
__u32 padding;
};

struct fuse_bmap_out {
__u64 block;
};

struct fuse_in_header {
__u32 len;
__u32 opcode;
Expand Down

0 comments on commit b2d2272

Please sign in to comment.