Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d07d4d1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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()
parents 3386c05b f6d47a17
Loading
Loading
Loading
Loading
+11 −5
Original line number Original line Diff line number Diff line
@@ -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;
	}
	}


+1 −1
Original line number Original line Diff line number Diff line
@@ -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);
+18 −12
Original line number Original line Diff line number Diff line
@@ -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;
}
}