Skip to content

Commit

Permalink
[PATCH] fuse: add DESTROY operation
Browse files Browse the repository at this point in the history
Add a DESTROY operation for block device based filesystems.  With the help of
this operation, such a filesystem can flush dirty data to the device
synchronously before the umount returns.

This is needed in situations where the filesystem is assumed to be clean
immediately after unmount (e.g.  ejecting removable media).

Signed-off-by: Miklos Szeredi <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
szmi authored and Linus Torvalds committed Dec 7, 2006
1 parent b2d2272 commit 0ec7ca4
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 0 deletions.
6 changes: 6 additions & 0 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@ struct fuse_conn {
reply, before any other request, and never cleared */
unsigned conn_error : 1;

/** Connection successful. Only set in INIT */
unsigned conn_init : 1;

/** Do readpages asynchronously? Only set in INIT */
unsigned async_read : 1;

Expand Down Expand Up @@ -368,6 +371,9 @@ struct fuse_conn {

/** Key for lock owner ID scrambling */
u32 scramble_key[4];

/** Reserved request for the DESTROY message */
struct fuse_req *destroy_req;
};

static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
Expand Down
22 changes: 22 additions & 0 deletions fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,23 @@ static void fuse_umount_begin(struct vfsmount *vfsmnt, int flags)
fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb));
}

static void fuse_send_destroy(struct fuse_conn *fc)
{
struct fuse_req *req = fc->destroy_req;
if (req && fc->conn_init) {
fc->destroy_req = NULL;
req->in.h.opcode = FUSE_DESTROY;
req->force = 1;
request_send(fc, req);
fuse_put_request(fc, req);
}
}

static void fuse_put_super(struct super_block *sb)
{
struct fuse_conn *fc = get_fuse_conn_super(sb);

fuse_send_destroy(fc);
spin_lock(&fc->lock);
fc->connected = 0;
fc->blocked = 0;
Expand Down Expand Up @@ -410,6 +423,8 @@ static struct fuse_conn *new_conn(void)
void fuse_conn_put(struct fuse_conn *fc)
{
if (atomic_dec_and_test(&fc->count)) {
if (fc->destroy_req)
fuse_request_free(fc->destroy_req);
mutex_destroy(&fc->inst_mutex);
kfree(fc);
}
Expand Down Expand Up @@ -466,6 +481,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
fc->minor = arg->minor;
fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
fc->conn_init = 1;
}
fuse_put_request(fc, req);
fc->blocked = 0;
Expand Down Expand Up @@ -563,6 +579,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
if (!init_req)
goto err_put_root;

if (is_bdev) {
fc->destroy_req = fuse_request_alloc();
if (!fc->destroy_req)
goto err_put_root;
}

mutex_lock(&fuse_mutex);
err = -EINVAL;
if (file->private_data)
Expand Down
1 change: 1 addition & 0 deletions include/linux/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ enum fuse_opcode {
FUSE_CREATE = 35,
FUSE_INTERRUPT = 36,
FUSE_BMAP = 37,
FUSE_DESTROY = 38,
};

/* The read buffer is required to be at least 8k, but may be much larger */
Expand Down

0 comments on commit 0ec7ca4

Please sign in to comment.