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

Commit 2eac9eb8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull fuse updates from Miklos Szeredi.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
  fuse: verify all ioctl retry iov elements
  fuse: add missing INIT flag descriptions
  fuse: add missing INIT flags
  fuse: update attributes on aio_read
  fuse: invalidate inode mapping if mtime changes
  fuse: add FUSE_AUTO_INVAL_DATA init flag
parents ad54e461 fb6ccff6
Loading
Loading
Loading
Loading
+9 −6
Original line number Original line Diff line number Diff line
@@ -703,13 +703,16 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
				  unsigned long nr_segs, loff_t pos)
				  unsigned long nr_segs, loff_t pos)
{
{
	struct inode *inode = iocb->ki_filp->f_mapping->host;
	struct inode *inode = iocb->ki_filp->f_mapping->host;
	struct fuse_conn *fc = get_fuse_conn(inode);


	if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) {
		int err;
	/*
	/*
		 * If trying to read past EOF, make sure the i_size
	 * In auto invalidate mode, always update attributes on read.
		 * attribute is up-to-date.
	 * Otherwise, only update if we attempt to read past EOF (to ensure
	 * i_size is up to date).
	 */
	 */
	if (fc->auto_inval_data ||
	    (pos + iov_length(iov, nr_segs) > i_size_read(inode))) {
		int err;
		err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL);
		err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL);
		if (err)
		if (err)
			return err;
			return err;
@@ -1700,7 +1703,7 @@ static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)
	size_t n;
	size_t n;
	u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;
	u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;


	for (n = 0; n < count; n++) {
	for (n = 0; n < count; n++, iov++) {
		if (iov->iov_len > (size_t) max)
		if (iov->iov_len > (size_t) max)
			return -ENOMEM;
			return -ENOMEM;
		max -= iov->iov_len;
		max -= iov->iov_len;
+3 −0
Original line number Original line Diff line number Diff line
@@ -484,6 +484,9 @@ struct fuse_conn {
	/** Is fallocate not implemented by fs? */
	/** Is fallocate not implemented by fs? */
	unsigned no_fallocate:1;
	unsigned no_fallocate:1;


	/** Use enhanced/automatic page cache invalidation. */
	unsigned auto_inval_data:1;

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


+28 −4
Original line number Original line Diff line number Diff line
@@ -197,6 +197,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
	struct fuse_conn *fc = get_fuse_conn(inode);
	struct fuse_conn *fc = get_fuse_conn(inode);
	struct fuse_inode *fi = get_fuse_inode(inode);
	struct fuse_inode *fi = get_fuse_inode(inode);
	loff_t oldsize;
	loff_t oldsize;
	struct timespec old_mtime;


	spin_lock(&fc->lock);
	spin_lock(&fc->lock);
	if (attr_version != 0 && fi->attr_version > attr_version) {
	if (attr_version != 0 && fi->attr_version > attr_version) {
@@ -204,14 +205,34 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
		return;
		return;
	}
	}


	old_mtime = inode->i_mtime;
	fuse_change_attributes_common(inode, attr, attr_valid);
	fuse_change_attributes_common(inode, attr, attr_valid);


	oldsize = inode->i_size;
	oldsize = inode->i_size;
	i_size_write(inode, attr->size);
	i_size_write(inode, attr->size);
	spin_unlock(&fc->lock);
	spin_unlock(&fc->lock);


	if (S_ISREG(inode->i_mode) && oldsize != attr->size) {
	if (S_ISREG(inode->i_mode)) {
		bool inval = false;

		if (oldsize != attr->size) {
			truncate_pagecache(inode, oldsize, attr->size);
			truncate_pagecache(inode, oldsize, attr->size);
			inval = true;
		} else if (fc->auto_inval_data) {
			struct timespec new_mtime = {
				.tv_sec = attr->mtime,
				.tv_nsec = attr->mtimensec,
			};

			/*
			 * Auto inval mode also checks and invalidates if mtime
			 * has changed.
			 */
			if (!timespec_equal(&old_mtime, &new_mtime))
				inval = true;
		}

		if (inval)
			invalidate_inode_pages2(inode->i_mapping);
			invalidate_inode_pages2(inode->i_mapping);
	}
	}
}
}
@@ -834,6 +855,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
				fc->big_writes = 1;
				fc->big_writes = 1;
			if (arg->flags & FUSE_DONT_MASK)
			if (arg->flags & FUSE_DONT_MASK)
				fc->dont_mask = 1;
				fc->dont_mask = 1;
			if (arg->flags & FUSE_AUTO_INVAL_DATA)
				fc->auto_inval_data = 1;
		} else {
		} else {
			ra_pages = fc->max_read / PAGE_CACHE_SIZE;
			ra_pages = fc->max_read / PAGE_CACHE_SIZE;
			fc->no_lock = 1;
			fc->no_lock = 1;
@@ -859,7 +882,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
	arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
	arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
	arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
	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;
		FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ |
		FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA;
	req->in.h.opcode = FUSE_INIT;
	req->in.h.opcode = FUSE_INIT;
	req->in.numargs = 1;
	req->in.numargs = 1;
	req->in.args[0].size = sizeof(*arg);
	req->in.args[0].size = sizeof(*arg);
+18 −1
Original line number Original line Diff line number Diff line
@@ -57,6 +57,9 @@
 *
 *
 * 7.19
 * 7.19
 *  - add FUSE_FALLOCATE
 *  - add FUSE_FALLOCATE
 *
 * 7.20
 *  - add FUSE_AUTO_INVAL_DATA
 */
 */


#ifndef _LINUX_FUSE_H
#ifndef _LINUX_FUSE_H
@@ -88,7 +91,7 @@
#define FUSE_KERNEL_VERSION 7
#define FUSE_KERNEL_VERSION 7


/** Minor version number of this interface */
/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 19
#define FUSE_KERNEL_MINOR_VERSION 20


/** The node ID of the root inode */
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
#define FUSE_ROOT_ID 1
@@ -163,10 +166,19 @@ struct fuse_file_lock {
/**
/**
 * INIT request/reply flags
 * INIT request/reply flags
 *
 *
 * FUSE_ASYNC_READ: asynchronous read requests
 * FUSE_POSIX_LOCKS: remote locking for POSIX file locks
 * FUSE_POSIX_LOCKS: remote locking for POSIX file locks
 * FUSE_FILE_OPS: kernel sends file handle for fstat, etc... (not yet supported)
 * FUSE_ATOMIC_O_TRUNC: handles the O_TRUNC open flag in the filesystem
 * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
 * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
 * FUSE_BIG_WRITES: filesystem can handle write size larger than 4kB
 * FUSE_DONT_MASK: don't apply umask to file mode on create operations
 * FUSE_DONT_MASK: don't apply umask to file mode on create operations
 * FUSE_SPLICE_WRITE: kernel supports splice write on the device
 * FUSE_SPLICE_MOVE: kernel supports splice move on the device
 * FUSE_SPLICE_READ: kernel supports splice read on the device
 * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks
 * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks
 * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories
 * FUSE_AUTO_INVAL_DATA: automatically invalidate cached pages
 */
 */
#define FUSE_ASYNC_READ		(1 << 0)
#define FUSE_ASYNC_READ		(1 << 0)
#define FUSE_POSIX_LOCKS	(1 << 1)
#define FUSE_POSIX_LOCKS	(1 << 1)
@@ -175,7 +187,12 @@ struct fuse_file_lock {
#define FUSE_EXPORT_SUPPORT	(1 << 4)
#define FUSE_EXPORT_SUPPORT	(1 << 4)
#define FUSE_BIG_WRITES		(1 << 5)
#define FUSE_BIG_WRITES		(1 << 5)
#define FUSE_DONT_MASK		(1 << 6)
#define FUSE_DONT_MASK		(1 << 6)
#define FUSE_SPLICE_WRITE	(1 << 7)
#define FUSE_SPLICE_MOVE	(1 << 8)
#define FUSE_SPLICE_READ	(1 << 9)
#define FUSE_FLOCK_LOCKS	(1 << 10)
#define FUSE_FLOCK_LOCKS	(1 << 10)
#define FUSE_HAS_IOCTL_DIR	(1 << 11)
#define FUSE_AUTO_INVAL_DATA	(1 << 12)


/**
/**
 * CUSE INIT request/reply flags
 * CUSE INIT request/reply flags