Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b2d2272f authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Linus Torvalds
Browse files

[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: default avatarMiklos Szeredi <miklos@szeredi.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d8091614
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+37 −0
Original line number Diff line number Diff line
@@ -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)
+3 −0
Original line number Diff line number Diff line
@@ -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;

+11 −0
Original line number Diff line number Diff line
@@ -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 */
@@ -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;