[PATCH] fuse: add bmap support
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>
This commit is contained in:
committed by
Linus Torvalds
parent
d809161402
commit
b2d2272fae
@@ -1024,6 +1024,8 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
|
|||||||
if (attr->ia_valid & ATTR_SIZE) {
|
if (attr->ia_valid & ATTR_SIZE) {
|
||||||
unsigned long limit;
|
unsigned long limit;
|
||||||
is_truncate = 1;
|
is_truncate = 1;
|
||||||
|
if (IS_SWAPFILE(inode))
|
||||||
|
return -ETXTBSY;
|
||||||
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
|
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
|
||||||
if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
|
if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
|
||||||
send_sig(SIGXFSZ, current, 0);
|
send_sig(SIGXFSZ, current, 0);
|
||||||
|
@@ -754,6 +754,42 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
|
|||||||
return err;
|
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 = {
|
static const struct file_operations fuse_file_operations = {
|
||||||
.llseek = generic_file_llseek,
|
.llseek = generic_file_llseek,
|
||||||
.read = do_sync_read,
|
.read = do_sync_read,
|
||||||
@@ -787,6 +823,7 @@ static const struct address_space_operations fuse_file_aops = {
|
|||||||
.commit_write = fuse_commit_write,
|
.commit_write = fuse_commit_write,
|
||||||
.readpages = fuse_readpages,
|
.readpages = fuse_readpages,
|
||||||
.set_page_dirty = fuse_set_page_dirty,
|
.set_page_dirty = fuse_set_page_dirty,
|
||||||
|
.bmap = fuse_bmap,
|
||||||
};
|
};
|
||||||
|
|
||||||
void fuse_init_file_inode(struct inode *inode)
|
void fuse_init_file_inode(struct inode *inode)
|
||||||
|
@@ -339,6 +339,9 @@ struct fuse_conn {
|
|||||||
/** Is interrupt not implemented by fs? */
|
/** Is interrupt not implemented by fs? */
|
||||||
unsigned no_interrupt : 1;
|
unsigned no_interrupt : 1;
|
||||||
|
|
||||||
|
/** Is bmap not implemented by fs? */
|
||||||
|
unsigned no_bmap : 1;
|
||||||
|
|
||||||
/** The number of requests waiting for completion */
|
/** The number of requests waiting for completion */
|
||||||
atomic_t num_waiting;
|
atomic_t num_waiting;
|
||||||
|
|
||||||
|
@@ -132,6 +132,7 @@ enum fuse_opcode {
|
|||||||
FUSE_ACCESS = 34,
|
FUSE_ACCESS = 34,
|
||||||
FUSE_CREATE = 35,
|
FUSE_CREATE = 35,
|
||||||
FUSE_INTERRUPT = 36,
|
FUSE_INTERRUPT = 36,
|
||||||
|
FUSE_BMAP = 37,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The read buffer is required to be at least 8k, but may be much larger */
|
/* The read buffer is required to be at least 8k, but may be much larger */
|
||||||
@@ -302,6 +303,16 @@ struct fuse_interrupt_in {
|
|||||||
__u64 unique;
|
__u64 unique;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fuse_bmap_in {
|
||||||
|
__u64 block;
|
||||||
|
__u32 blocksize;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fuse_bmap_out {
|
||||||
|
__u64 block;
|
||||||
|
};
|
||||||
|
|
||||||
struct fuse_in_header {
|
struct fuse_in_header {
|
||||||
__u32 len;
|
__u32 len;
|
||||||
__u32 opcode;
|
__u32 opcode;
|
||||||
|
Reference in New Issue
Block a user