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:
Linus Torvalds 2009-01-26 09:49:22 -08:00
Родитель 3386c05bdb f6d47a1761
Коммит 2d07d4d1bb
3 изменённых файлов: 30 добавлений и 18 удалений

Просмотреть файл

@ -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;
} }