mirror of
https://github.com/libfuse/libfuse.git
synced 2024-11-26 21:54:30 +08:00
Add DESTROY message
This commit is contained in:
parent
7e7fa1fb94
commit
b9ea32fc3b
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user