[patch 11/12] fuse: add bmap support

From: Miklos Szeredi
Date: Mon Oct 16 2006 - 12:29:59 EST


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@xxxxxxxxxx>

---
Index: linux/fs/fuse/file.c
===================================================================
--- linux.orig/fs/fuse/file.c 2006-10-16 16:17:30.000000000 +0200
+++ linux/fs/fuse/file.c 2006-10-16 16:21:39.000000000 +0200
@@ -757,6 +757,42 @@ static int fuse_file_lock(struct file *f
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,
@@ -790,6 +826,7 @@ static const struct address_space_operat
.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)
Index: linux/fs/fuse/fuse_i.h
===================================================================
--- linux.orig/fs/fuse/fuse_i.h 2006-10-16 16:17:36.000000000 +0200
+++ linux/fs/fuse/fuse_i.h 2006-10-16 16:21:39.000000000 +0200
@@ -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;

Index: linux/include/linux/fuse.h
===================================================================
--- linux.orig/include/linux/fuse.h 2006-10-16 16:21:26.000000000 +0200
+++ linux/include/linux/fuse.h 2006-10-16 16:21:39.000000000 +0200
@@ -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;
Index: linux/fs/fuse/dir.c
===================================================================
--- linux.orig/fs/fuse/dir.c 2006-10-16 16:21:29.000000000 +0200
+++ linux/fs/fuse/dir.c 2006-10-16 16:21:39.000000000 +0200
@@ -1000,6 +1000,8 @@ static int fuse_setattr(struct dentry *e
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);

--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/