aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/fuse/fuse_i.h6
-rw-r--r--fs/fuse/inode.c22
2 files changed, 28 insertions, 0 deletions
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 58d482d9f6bb..b98b20de7405 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -298,6 +298,9 @@ struct fuse_conn {
298 reply, before any other request, and never cleared */ 298 reply, before any other request, and never cleared */
299 unsigned conn_error : 1; 299 unsigned conn_error : 1;
300 300
301 /** Connection successful. Only set in INIT */
302 unsigned conn_init : 1;
303
301 /** Do readpages asynchronously? Only set in INIT */ 304 /** Do readpages asynchronously? Only set in INIT */
302 unsigned async_read : 1; 305 unsigned async_read : 1;
303 306
@@ -368,6 +371,9 @@ struct fuse_conn {
368 371
369 /** Key for lock owner ID scrambling */ 372 /** Key for lock owner ID scrambling */
370 u32 scramble_key[4]; 373 u32 scramble_key[4];
374
375 /** Reserved request for the DESTROY message */
376 struct fuse_req *destroy_req;
371}; 377};
372 378
373static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) 379static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
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)