Add DESTROY message

This commit is contained in:
Miklos Szeredi 2006-10-08 17:35:40 +00:00
parent 7e7fa1fb94
commit b9ea32fc3b
5 changed files with 58 additions and 2 deletions

View File

@ -19,6 +19,15 @@
* Minor clean up of udev rules
* Add a synchronous DESTROY message to kernel interface. This is
invoked from umount, when the final instance of the filesystem is
released. It is only sent for filesystems mounted with the
'blkdev' option for security reasons.
* If the DESTROY message is received, call the filesystem's
->destroy() method. In this case it's not called from session
destruction as it would be otherwise.
2006-10-01 Miklos Szeredi <miklos@szeredi.hu>
* Released 2.6.0-rc2

View File

@ -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)

View File

@ -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 */

View File

@ -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)

View File

@ -57,6 +57,7 @@ struct fuse_ll {
struct fuse_req list;
struct fuse_req interrupts;
pthread_mutex_t lock;
int got_destroy;
};
static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
@ -995,6 +996,20 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
}
static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
struct fuse_ll *f = req->f;
(void) nodeid;
(void) inarg;
f->got_destroy = 1;
if (f->op.destroy)
f->op.destroy(f->userdata);
send_reply_ok(req, NULL, 0);
}
void *fuse_req_userdata(fuse_req_t req)
{
return req->f->userdata;
@ -1066,6 +1081,7 @@ static struct {
[FUSE_CREATE] = { do_create, "CREATE" },
[FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" },
[FUSE_BMAP] = { do_bmap, "BMAP" },
[FUSE_DESTROY] = { do_destroy, "DESTROY" },
};
#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
@ -1200,8 +1216,10 @@ static void fuse_ll_destroy(void *data)
{
struct fuse_ll *f = (struct fuse_ll *) data;
if (f->op.destroy)
f->op.destroy(f->userdata);
if (f->got_init && !f->got_destroy) {
if (f->op.destroy)
f->op.destroy(f->userdata);
}
pthread_mutex_destroy(&f->lock);
free(f);