Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: fuse: fix poll notify fuse: destroy bdi on umount fuse: fuse_fill_super error handling cleanup fuse: fix missing fput on error fuse: fix NULL deref in fuse_file_alloc()
This commit is contained in:
commit
2d07d4d1bb
|
@ -281,7 +281,8 @@ __releases(&fc->lock)
|
||||||
fc->blocked = 0;
|
fc->blocked = 0;
|
||||||
wake_up_all(&fc->blocked_waitq);
|
wake_up_all(&fc->blocked_waitq);
|
||||||
}
|
}
|
||||||
if (fc->num_background == FUSE_CONGESTION_THRESHOLD) {
|
if (fc->num_background == FUSE_CONGESTION_THRESHOLD &&
|
||||||
|
fc->connected) {
|
||||||
clear_bdi_congested(&fc->bdi, READ);
|
clear_bdi_congested(&fc->bdi, READ);
|
||||||
clear_bdi_congested(&fc->bdi, WRITE);
|
clear_bdi_congested(&fc->bdi, WRITE);
|
||||||
}
|
}
|
||||||
|
@ -825,16 +826,21 @@ static int fuse_notify_poll(struct fuse_conn *fc, unsigned int size,
|
||||||
struct fuse_copy_state *cs)
|
struct fuse_copy_state *cs)
|
||||||
{
|
{
|
||||||
struct fuse_notify_poll_wakeup_out outarg;
|
struct fuse_notify_poll_wakeup_out outarg;
|
||||||
int err;
|
int err = -EINVAL;
|
||||||
|
|
||||||
if (size != sizeof(outarg))
|
if (size != sizeof(outarg))
|
||||||
return -EINVAL;
|
goto err;
|
||||||
|
|
||||||
err = fuse_copy_one(cs, &outarg, sizeof(outarg));
|
err = fuse_copy_one(cs, &outarg, sizeof(outarg));
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto err;
|
||||||
|
|
||||||
|
fuse_copy_finish(cs);
|
||||||
return fuse_notify_poll_wakeup(fc, &outarg);
|
return fuse_notify_poll_wakeup(fc, &outarg);
|
||||||
|
|
||||||
|
err:
|
||||||
|
fuse_copy_finish(cs);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
|
static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
|
||||||
|
@ -845,6 +851,7 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
|
||||||
return fuse_notify_poll(fc, size, cs);
|
return fuse_notify_poll(fc, size, cs);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
fuse_copy_finish(cs);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -923,7 +930,6 @@ static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
|
||||||
*/
|
*/
|
||||||
if (!oh.unique) {
|
if (!oh.unique) {
|
||||||
err = fuse_notify(fc, oh.error, nbytes - sizeof(oh), &cs);
|
err = fuse_notify(fc, oh.error, nbytes - sizeof(oh), &cs);
|
||||||
fuse_copy_finish(&cs);
|
|
||||||
return err ? err : nbytes;
|
return err ? err : nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
|
||||||
ff->reserved_req = fuse_request_alloc();
|
ff->reserved_req = fuse_request_alloc();
|
||||||
if (!ff->reserved_req) {
|
if (!ff->reserved_req) {
|
||||||
kfree(ff);
|
kfree(ff);
|
||||||
ff = NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
INIT_LIST_HEAD(&ff->write_entry);
|
INIT_LIST_HEAD(&ff->write_entry);
|
||||||
atomic_set(&ff->count, 0);
|
atomic_set(&ff->count, 0);
|
||||||
|
|
|
@ -292,6 +292,7 @@ static void fuse_put_super(struct super_block *sb)
|
||||||
list_del(&fc->entry);
|
list_del(&fc->entry);
|
||||||
fuse_ctl_remove_conn(fc);
|
fuse_ctl_remove_conn(fc);
|
||||||
mutex_unlock(&fuse_mutex);
|
mutex_unlock(&fuse_mutex);
|
||||||
|
bdi_destroy(&fc->bdi);
|
||||||
fuse_conn_put(fc);
|
fuse_conn_put(fc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,7 +533,6 @@ void fuse_conn_put(struct fuse_conn *fc)
|
||||||
if (fc->destroy_req)
|
if (fc->destroy_req)
|
||||||
fuse_request_free(fc->destroy_req);
|
fuse_request_free(fc->destroy_req);
|
||||||
mutex_destroy(&fc->inst_mutex);
|
mutex_destroy(&fc->inst_mutex);
|
||||||
bdi_destroy(&fc->bdi);
|
|
||||||
fc->release(fc);
|
fc->release(fc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -805,16 +805,18 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
int err;
|
int err;
|
||||||
int is_bdev = sb->s_bdev != NULL;
|
int is_bdev = sb->s_bdev != NULL;
|
||||||
|
|
||||||
|
err = -EINVAL;
|
||||||
if (sb->s_flags & MS_MANDLOCK)
|
if (sb->s_flags & MS_MANDLOCK)
|
||||||
return -EINVAL;
|
goto err;
|
||||||
|
|
||||||
if (!parse_fuse_opt((char *) data, &d, is_bdev))
|
if (!parse_fuse_opt((char *) data, &d, is_bdev))
|
||||||
return -EINVAL;
|
goto err;
|
||||||
|
|
||||||
if (is_bdev) {
|
if (is_bdev) {
|
||||||
#ifdef CONFIG_BLOCK
|
#ifdef CONFIG_BLOCK
|
||||||
|
err = -EINVAL;
|
||||||
if (!sb_set_blocksize(sb, d.blksize))
|
if (!sb_set_blocksize(sb, d.blksize))
|
||||||
return -EINVAL;
|
goto err;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
sb->s_blocksize = PAGE_CACHE_SIZE;
|
sb->s_blocksize = PAGE_CACHE_SIZE;
|
||||||
|
@ -826,20 +828,22 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
sb->s_export_op = &fuse_export_operations;
|
sb->s_export_op = &fuse_export_operations;
|
||||||
|
|
||||||
file = fget(d.fd);
|
file = fget(d.fd);
|
||||||
|
err = -EINVAL;
|
||||||
if (!file)
|
if (!file)
|
||||||
return -EINVAL;
|
goto err;
|
||||||
|
|
||||||
if (file->f_op != &fuse_dev_operations)
|
if (file->f_op != &fuse_dev_operations)
|
||||||
return -EINVAL;
|
goto err_fput;
|
||||||
|
|
||||||
fc = kmalloc(sizeof(*fc), GFP_KERNEL);
|
fc = kmalloc(sizeof(*fc), GFP_KERNEL);
|
||||||
|
err = -ENOMEM;
|
||||||
if (!fc)
|
if (!fc)
|
||||||
return -ENOMEM;
|
goto err_fput;
|
||||||
|
|
||||||
err = fuse_conn_init(fc, sb);
|
err = fuse_conn_init(fc, sb);
|
||||||
if (err) {
|
if (err) {
|
||||||
kfree(fc);
|
kfree(fc);
|
||||||
return err;
|
goto err_fput;
|
||||||
}
|
}
|
||||||
|
|
||||||
fc->release = fuse_free_conn;
|
fc->release = fuse_free_conn;
|
||||||
|
@ -854,12 +858,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
root = fuse_get_root_inode(sb, d.rootmode);
|
root = fuse_get_root_inode(sb, d.rootmode);
|
||||||
if (!root)
|
if (!root)
|
||||||
goto err;
|
goto err_put_conn;
|
||||||
|
|
||||||
root_dentry = d_alloc_root(root);
|
root_dentry = d_alloc_root(root);
|
||||||
if (!root_dentry) {
|
if (!root_dentry) {
|
||||||
iput(root);
|
iput(root);
|
||||||
goto err;
|
goto err_put_conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_req = fuse_request_alloc();
|
init_req = fuse_request_alloc();
|
||||||
|
@ -903,9 +907,11 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
fuse_request_free(init_req);
|
fuse_request_free(init_req);
|
||||||
err_put_root:
|
err_put_root:
|
||||||
dput(root_dentry);
|
dput(root_dentry);
|
||||||
err:
|
err_put_conn:
|
||||||
fput(file);
|
|
||||||
fuse_conn_put(fc);
|
fuse_conn_put(fc);
|
||||||
|
err_fput:
|
||||||
|
fput(file);
|
||||||
|
err:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue