aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-10-08 17:35:40 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2006-10-08 17:35:40 +0000
commitb9ea32fc3bb3410c5f436c1f1f90558ff189bf23 (patch)
tree667f201f103569f79dcefcddc4ec699dc6418f04 /kernel
parent7e7fa1fb9429adf2061670c97ce30a39685daadd (diff)
downloadlibfuse-b9ea32fc3bb3410c5f436c1f1f90558ff189bf23.tar.gz
Add DESTROY message
Diffstat (limited to 'kernel')
-rw-r--r--kernel/fuse_i.h6
-rw-r--r--kernel/fuse_kernel.h1
-rw-r--r--kernel/inode.c22
3 files changed, 29 insertions, 0 deletions
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 0841e44..9be2de1 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -357,6 +357,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;
@@ -427,6 +430,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)
diff --git a/kernel/fuse_kernel.h b/kernel/fuse_kernel.h
index 94154b1..00026a6 100644
--- a/kernel/fuse_kernel.h
+++ b/kernel/fuse_kernel.h
@@ -168,6 +168,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 */
diff --git a/kernel/inode.c b/kernel/inode.c
index 7800892..be72f80 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -226,10 +226,23 @@ static void fuse_umount_begin(struct super_block *sb)
}
#endif
+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;
@@ -447,6 +460,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);
}
@@ -565,6 +580,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;
@@ -665,6 +681,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)