Skip to content

Commit

Permalink
Fix fuse device and data free.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ilya Putsikau authored and glk committed Oct 14, 2011
1 parent efbb506 commit 68764d7
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 129 deletions.
47 changes: 18 additions & 29 deletions fuse_module/fuse_device.c
Expand Up @@ -87,8 +87,8 @@ fuse_device_open(struct cdev *dev, int oflags, int devtype, struct thread *td)

FUSE_LOCK();
if (fuse_get_devdata(dev)) {
fdata_trydestroy(fdata);
FUSE_UNLOCK();
fdata_destroy(fdata);
goto busy;
} else {
fdata->dataflags |= FSESS_OPENED;
Expand All @@ -108,48 +108,37 @@ static int
fuse_device_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
struct fuse_data *data;
struct fuse_ticket *tick;

FUSE_LOCK();
data = fuse_get_devdata(dev);
if (! data)
if (!data)
panic("no fuse data upon fuse device close");
KASSERT(data->dataflags | FSESS_OPENED,
("fuse device is already closed upon close"));
fdata_set_dead(data);

FUSE_LOCK();
data->dataflags &= ~FSESS_OPENED;
fuse_lck_mtx_lock(data->aw_mtx);

fuse_lck_mtx_lock(data->aw_mtx);
/* wakup poll()ers */
selwakeuppri(&data->ks_rsel, PZERO + 1);

DEBUG("mntco %d\n", data->mntco);
if (data->mntco > 0) {
struct fuse_ticket *tick;

/* Don't let syscall handlers wait in vain */
while ((tick = fuse_aw_pop(data))) {
fuse_lck_mtx_lock(tick->tk_aw_mtx);
fticket_set_answered(tick);
tick->tk_aw_errno = ENOTCONN;
wakeup(tick);
fuse_lck_mtx_unlock(tick->tk_aw_mtx);
fuse_lck_mtx_unlock(data->aw_mtx);
FUSE_ASSERT_AW_DONE(tick);
fuse_ticket_drop(tick);
fuse_lck_mtx_lock(data->aw_mtx);
}
fuse_lck_mtx_unlock(data->aw_mtx);

FUSE_UNLOCK();
goto out;
/* Don't let syscall handlers wait in vain */
while ((tick = fuse_aw_pop(data))) {
fuse_lck_mtx_lock(tick->tk_aw_mtx);
fticket_set_answered(tick);
tick->tk_aw_errno = ENOTCONN;
wakeup(tick);
fuse_lck_mtx_unlock(tick->tk_aw_mtx);
FUSE_ASSERT_AW_DONE(tick);
fuse_ticket_drop(tick);
}
dev->si_drv1 = NULL;
fuse_lck_mtx_unlock(data->aw_mtx);
FUSE_UNLOCK();

fdata_destroy(data);
dev->si_drv1 = NULL;
fdata_trydestroy(data);
FUSE_UNLOCK();

out:
DEBUG("%s: device closed by thread %d.\n", dev->si_name, td->td_tid);
return(0);
}
Expand Down
30 changes: 20 additions & 10 deletions fuse_module/fuse_ipc.c
Expand Up @@ -341,14 +341,11 @@ fdata_alloc(struct cdev *fdev, struct ucred *cred)

data = malloc(sizeof(struct fuse_data), M_FUSEMSG, M_WAITOK | M_ZERO);

data->mpri = FM_NOMOUNTED;
data->fdev = fdev;
data->dataflags = 0;
mtx_init(&data->ms_mtx, "fuse message list mutex", NULL, MTX_DEF);
STAILQ_INIT(&data->ms_head);
mtx_init(&data->aw_mtx, "fuse answer list mutex", NULL, MTX_DEF);
TAILQ_INIT(&data->aw_head);
data->ticketer = 0;
data->daemoncred = crhold(cred);
data->daemon_timeout = FUSE_DEFAULT_DAEMON_TIMEOUT;

Expand All @@ -360,9 +357,23 @@ fdata_alloc(struct cdev *fdev, struct ucred *cred)
}

void
fdata_destroy(struct fuse_data *data)
fdata_trydestroy(struct fuse_data *data)
{
debug_printf("data=%p, destroy.mntco = %d\n", data, data->mntco);
DEBUG("data=%p data.mp=%p data.fdev=%p data.flags=%04x\n",
data, data->mp, data->fdev, data->dataflags);

if (data->mp != NULL) {
MPASS(data->mp->mnt_data == data);
return;
}

if (data->fdev->si_drv1 != NULL) {
MPASS(data->fdev->si_drv1 == data);
return;
}

DEBUG("destroy: data=%p\n", data);
MPASS((data->dataflags & FSESS_OPENED) == 0);

/* Driving off stage all that stuff thrown at device... */
mtx_destroy(&data->ms_mtx);
Expand All @@ -381,19 +392,18 @@ fdata_set_dead(struct fuse_data *data)
{
debug_printf("data=%p\n", data);

fuse_lck_mtx_lock(data->ms_mtx);
FUSE_LOCK();
if (fdata_get_dead(data)) {
fuse_lck_mtx_unlock(data->ms_mtx);
FUSE_UNLOCK();
return;
}

fuse_lck_mtx_lock(data->ms_mtx);
data->dataflags |= FSESS_DEAD;
wakeup_one(data);
selwakeuppri(&data->ks_rsel, PZERO + 1);
fuse_lck_mtx_unlock(data->ms_mtx);

FUSE_LOCK();
wakeup(&data->ticketer);
fuse_lck_mtx_unlock(data->ms_mtx);
FUSE_UNLOCK();
}

Expand Down
9 changes: 3 additions & 6 deletions fuse_module/fuse_ipc.h
Expand Up @@ -127,8 +127,6 @@ struct fuse_data {
struct cdev *fdev;
struct mount *mp;
struct vnode *vroot;
enum mountpri mpri;
int mntco;
struct ucred *daemoncred;
int dataflags;

Expand Down Expand Up @@ -179,15 +177,14 @@ static __inline__
struct fuse_data *
fuse_get_devdata(struct cdev *fdev)
{
return (fdev->si_drv1);
return fdev->si_drv1;
}

static __inline__
struct fuse_data *
fuse_get_mpdata(struct mount *mp)
{
struct fuse_data *data = mp->mnt_data;
return (data->mpri == FM_PRIMARY ? data : NULL);
return mp->mnt_data;
}

static __inline__
Expand Down Expand Up @@ -276,7 +273,7 @@ fuse_libabi_geq(struct fuse_data *data, uint32_t abi_maj, uint32_t abi_min)
}

struct fuse_data *fdata_alloc(struct cdev *dev, struct ucred *cred);
void fdata_destroy(struct fuse_data *data);
void fdata_trydestroy(struct fuse_data *data);
void fdata_set_dead(struct fuse_data *data);

static __inline__
Expand Down

0 comments on commit 68764d7

Please sign in to comment.