aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse')
-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)