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

Commit 051732bc 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: check size of FUSE_NOTIFY_INVAL_ENTRY message
  fuse: mark pages accessed when written to
  fuse: delete dead .write_begin and .write_end aops
  fuse: fix flock
  fuse: fix non-ANSI void function notation
parents 2983573e c2183d1e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1358,6 +1358,10 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
	if (outarg.namelen > FUSE_NAME_MAX)
		goto err;

	err = -EINVAL;
	if (size != sizeof(outarg) + outarg.namelen + 1)
		goto err;

	name.name = buf;
	name.len = outarg.namelen;
	err = fuse_copy_one(cs, buf, outarg.namelen + 1);
+13 −71
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/compat.h>
#include <linux/swap.h>

static const struct file_operations fuse_direct_io_file_operations;

@@ -245,6 +246,12 @@ void fuse_release_common(struct file *file, int opcode)
	req = ff->reserved_req;
	fuse_prepare_release(ff, file->f_flags, opcode);

	if (ff->flock) {
		struct fuse_release_in *inarg = &req->misc.release.in;
		inarg->release_flags |= FUSE_RELEASE_FLOCK_UNLOCK;
		inarg->lock_owner = fuse_lock_owner_id(ff->fc,
						       (fl_owner_t) file);
	}
	/* Hold vfsmount and dentry until release is finished */
	path_get(&file->f_path);
	req->misc.release.path = file->f_path;
@@ -755,18 +762,6 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file,
	return req->misc.write.out.size;
}

static int fuse_write_begin(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned flags,
			struct page **pagep, void **fsdata)
{
	pgoff_t index = pos >> PAGE_CACHE_SHIFT;

	*pagep = grab_cache_page_write_begin(mapping, index, flags);
	if (!*pagep)
		return -ENOMEM;
	return 0;
}

void fuse_write_update_size(struct inode *inode, loff_t pos)
{
	struct fuse_conn *fc = get_fuse_conn(inode);
@@ -779,62 +774,6 @@ void fuse_write_update_size(struct inode *inode, loff_t pos)
	spin_unlock(&fc->lock);
}

static int fuse_buffered_write(struct file *file, struct inode *inode,
			       loff_t pos, unsigned count, struct page *page)
{
	int err;
	size_t nres;
	struct fuse_conn *fc = get_fuse_conn(inode);
	unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
	struct fuse_req *req;

	if (is_bad_inode(inode))
		return -EIO;

	/*
	 * Make sure writepages on the same page are not mixed up with
	 * plain writes.
	 */
	fuse_wait_on_page_writeback(inode, page->index);

	req = fuse_get_req(fc);
	if (IS_ERR(req))
		return PTR_ERR(req);

	req->in.argpages = 1;
	req->num_pages = 1;
	req->pages[0] = page;
	req->page_offset = offset;
	nres = fuse_send_write(req, file, pos, count, NULL);
	err = req->out.h.error;
	fuse_put_request(fc, req);
	if (!err && !nres)
		err = -EIO;
	if (!err) {
		pos += nres;
		fuse_write_update_size(inode, pos);
		if (count == PAGE_CACHE_SIZE)
			SetPageUptodate(page);
	}
	fuse_invalidate_attr(inode);
	return err ? err : nres;
}

static int fuse_write_end(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned copied,
			struct page *page, void *fsdata)
{
	struct inode *inode = mapping->host;
	int res = 0;

	if (copied)
		res = fuse_buffered_write(file, inode, pos, copied, page);

	unlock_page(page);
	page_cache_release(page);
	return res;
}

static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
				    struct inode *inode, loff_t pos,
				    size_t count)
@@ -908,6 +847,8 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
		pagefault_enable();
		flush_dcache_page(page);

		mark_page_accessed(page);

		if (!tmp) {
			unlock_page(page);
			page_cache_release(page);
@@ -1559,11 +1500,14 @@ static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
	struct fuse_conn *fc = get_fuse_conn(inode);
	int err;

	if (fc->no_lock) {
	if (fc->no_flock) {
		err = flock_lock_file_wait(file, fl);
	} else {
		struct fuse_file *ff = file->private_data;

		/* emulate flock with POSIX locks */
		fl->fl_owner = (fl_owner_t) file;
		ff->flock = true;
		err = fuse_setlk(file, fl, 1);
	}

@@ -2201,8 +2145,6 @@ static const struct address_space_operations fuse_file_aops = {
	.readpage	= fuse_readpage,
	.writepage	= fuse_writepage,
	.launder_page	= fuse_launder_page,
	.write_begin	= fuse_write_begin,
	.write_end	= fuse_write_end,
	.readpages	= fuse_readpages,
	.set_page_dirty	= __set_page_dirty_nobuffers,
	.bmap		= fuse_bmap,
+7 −1
Original line number Diff line number Diff line
@@ -135,6 +135,9 @@ struct fuse_file {

	/** Wait queue head for poll */
	wait_queue_head_t poll_wait;

	/** Has flock been performed on this file? */
	bool flock:1;
};

/** One input argument of a request */
@@ -448,7 +451,7 @@ struct fuse_conn {
	/** Is removexattr not implemented by fs? */
	unsigned no_removexattr:1;

	/** Are file locking primitives not implemented by fs? */
	/** Are posix file locking primitives not implemented by fs? */
	unsigned no_lock:1;

	/** Is access not implemented by fs? */
@@ -472,6 +475,9 @@ struct fuse_conn {
	/** Don't apply umask to creation modes */
	unsigned dont_mask:1;

	/** Are BSD file locking primitives not implemented by fs? */
	unsigned no_flock:1;

	/** The number of requests waiting for completion */
	atomic_t num_waiting;

+8 −2
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ struct fuse_mount_data {
	unsigned blksize;
};

struct fuse_forget_link *fuse_alloc_forget()
struct fuse_forget_link *fuse_alloc_forget(void)
{
	return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL);
}
@@ -809,6 +809,10 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
				fc->async_read = 1;
			if (!(arg->flags & FUSE_POSIX_LOCKS))
				fc->no_lock = 1;
			if (arg->minor >= 17) {
				if (!(arg->flags & FUSE_FLOCK_LOCKS))
					fc->no_flock = 1;
			}
			if (arg->flags & FUSE_ATOMIC_O_TRUNC)
				fc->atomic_o_trunc = 1;
			if (arg->minor >= 9) {
@@ -823,6 +827,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
		} else {
			ra_pages = fc->max_read / PAGE_CACHE_SIZE;
			fc->no_lock = 1;
			fc->no_flock = 1;
		}

		fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
@@ -843,7 +848,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
	arg->minor = FUSE_KERNEL_MINOR_VERSION;
	arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
	arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
		FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK;
		FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK |
		FUSE_FLOCK_LOCKS;
	req->in.h.opcode = FUSE_INIT;
	req->in.numargs = 1;
	req->in.args[0].size = sizeof(*arg);
+8 −1
Original line number Diff line number Diff line
@@ -47,6 +47,9 @@
 *  - FUSE_IOCTL_UNRESTRICTED shall now return with array of 'struct
 *    fuse_ioctl_iovec' instead of ambiguous 'struct iovec'
 *  - add FUSE_IOCTL_32BIT flag
 *
 * 7.17
 *  - add FUSE_FLOCK_LOCKS and FUSE_RELEASE_FLOCK_UNLOCK
 */

#ifndef _LINUX_FUSE_H
@@ -78,7 +81,7 @@
#define FUSE_KERNEL_VERSION 7

/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 16
#define FUSE_KERNEL_MINOR_VERSION 17

/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -153,8 +156,10 @@ struct fuse_file_lock {
/**
 * INIT request/reply flags
 *
 * FUSE_POSIX_LOCKS: remote locking for POSIX file locks
 * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
 * FUSE_DONT_MASK: don't apply umask to file mode on create operations
 * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks
 */
#define FUSE_ASYNC_READ		(1 << 0)
#define FUSE_POSIX_LOCKS	(1 << 1)
@@ -163,6 +168,7 @@ struct fuse_file_lock {
#define FUSE_EXPORT_SUPPORT	(1 << 4)
#define FUSE_BIG_WRITES		(1 << 5)
#define FUSE_DONT_MASK		(1 << 6)
#define FUSE_FLOCK_LOCKS	(1 << 10)

/**
 * CUSE INIT request/reply flags
@@ -175,6 +181,7 @@ struct fuse_file_lock {
 * Release flags
 */
#define FUSE_RELEASE_FLUSH	(1 << 0)
#define FUSE_RELEASE_FLOCK_UNLOCK	(1 << 1)

/**
 * Getattr flags