aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/inode.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-12-06 23:35:52 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-07 11:39:32 -0500
commit0ec7ca41f6f0f74a394a7d686bc0ee8afef84887 (patch)
treebb4aac390be07d04b484fddc325598f05b498db0 /fs/fuse/inode.c
parentb2d2272fae1e1df26ec8f93a6d5baea891dcce37 (diff)
[PATCH] fuse: add DESTROY operation
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 <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r--fs/fuse/inode.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 1baaaeb2e850..437d61c65268 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -206,10 +206,23 @@ static void fuse_umount_begin(struct vfsmount *vfsmnt, int flags)
206 fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb)); 206 fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb));
207} 207}
208 208
209static void fuse_send_destroy(struct fuse_conn *fc)
210{
211 struct fuse_req *req = fc->destroy_req;
212 if (req && fc->conn_init) {
213 fc->destroy_req = NULL;
214 req->in.h.opcode = FUSE_DESTROY;
215 req->force = 1;
216 request_send(fc, req);
217 fuse_put_request(fc, req);
218 }
219}
220
209static void fuse_put_super(struct super_block *sb) 221static void fuse_put_super(struct super_block *sb)
210{ 222{
211 struct fuse_conn *fc = get_fuse_conn_super(sb); 223 struct fuse_conn *fc = get_fuse_conn_super(sb);
212 224
225 fuse_send_destroy(fc);
213 spin_lock(&fc->lock); 226 spin_lock(&fc->lock);
214 fc->connected = 0; 227 fc->connected = 0;
215 fc->blocked = 0; 228 fc->blocked = 0;
@@ -410,6 +423,8 @@ static struct fuse_conn *new_conn(void)
410void fuse_conn_put(struct fuse_conn *fc) 423void fuse_conn_put(struct fuse_conn *fc)
411{ 424{
412 if (atomic_dec_and_test(&fc->count)) { 425 if (atomic_dec_and_test(&fc->count)) {
426 if (fc->destroy_req)
427 fuse_request_free(fc->destroy_req);
413 mutex_destroy(&fc->inst_mutex); 428 mutex_destroy(&fc->inst_mutex);
414 kfree(fc); 429 kfree(fc);
415 } 430 }
@@ -466,6 +481,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
466 fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); 481 fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
467 fc->minor = arg->minor; 482 fc->minor = arg->minor;
468 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 483 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
484 fc->conn_init = 1;
469 } 485 }
470 fuse_put_request(fc, req); 486 fuse_put_request(fc, req);
471 fc->blocked = 0; 487 fc->blocked = 0;
@@ -563,6 +579,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
563 if (!init_req) 579 if (!init_req)
564 goto err_put_root; 580 goto err_put_root;
565 581
582 if (is_bdev) {
583 fc->destroy_req = fuse_request_alloc();
584 if (!fc->destroy_req)
585 goto err_put_root;
586 }
587
566 mutex_lock(&fuse_mutex); 588 mutex_lock(&fuse_mutex);
567 err = -EINVAL; 589 err = -EINVAL;
568 if (file->private_data) 590 if (file->private_data)