Commit 8e15605b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull 9p updates from Eric Van Hensbergen:
 "This includes a number of patches that didn't quite make the cut last
  merge window while we addressed some outstanding issues and review
  comments. It includes some new caching modes for those that only want
  readahead caches and reworks how we do writeback caching so we are not
  keeping extra references around which both causes performance problems
  and uses lots of additional resources on the server.

  It also includes a new flag to force disabling of xattrs which can
  also cause major performance issues, particularly if the underlying
  filesystem on the server doesn't support them.

  Finally it adds a couple of additional mount options to better support
  directio and enabling caches when the server doesn't support
  qid.version.

  There was one late-breaking bug report that has also been included as
  its own patch where I forgot to propagate an embarassing bit-logic fix
  to the various variations of open"

* tag '9p-6.4-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
  fs/9p: Fix bit operation logic error
  fs/9p: Rework cache modes and add new options to Documentation
  fs/9p: remove writeback fid and fix per-file modes
  fs/9p: Add new mount modes
  9p: Add additional debug flags and open modes
  fs/9p: allow disable of xattr support on mount
  fs/9p: Remove unnecessary superblock flags
  fs/9p: Consolidate file operations and add readahead and writeback
parents a1fd058b 21e26d5e
Loading
Loading
Loading
Loading
+39 −13
Original line number Diff line number Diff line
@@ -78,19 +78,39 @@ Options
  		offering several exported file systems.

  cache=mode	specifies a caching policy.  By default, no caches are used.

                        none
				default no cache policy, metadata and data
                                alike are synchronous.
			loose
				no attempts are made at consistency,
                                intended for exclusive, read-only mounts
                        fscache
				use FS-Cache for a persistent, read-only
				cache backend.
                        mmap
				minimal cache that is only used for read-write
                                mmap.  Northing else is cached, like cache=none
		The mode can be specified as a bitmask or by using one of the
		prexisting common 'shortcuts'.
		The bitmask is described below: (unspecified bits are reserved)

			==========  ====================================================
			0b00000000  all caches disabled, mmap disabled
			0b00000001  file caches enabled
			0b00000010  meta-data caches enabled
			0b00000100  writeback behavior (as opposed to writethrough)
			0b00001000  loose caches (no explicit consistency with server)
			0b10000000  fscache enabled for persistent caching
			==========  ====================================================

		The current shortcuts and their associated bitmask are:

			=========   ====================================================
			none        0b00000000 (no caching)
			readahead   0b00000001 (only read-ahead file caching)
			mmap        0b00000101 (read-ahead + writeback file cache)
			loose       0b00001111 (non-coherent file and meta-data caches)
			fscache     0b10001111 (persistent loose cache)
			=========   ====================================================

		NOTE: only these shortcuts are tested modes of operation at the
		moment, so using other combinations of bit-patterns is not
		known to work.  Work on better cache support is in progress.

		IMPORTANT: loose caches (and by extension at the moment fscache)
		do not necessarily validate cached values on the server.  In other
		words changes on the server are not guaranteed to be reflected
		on the client system.  Only use this mode of operation if you
		have an exclusive mount and the server will modify the filesystem
		underneath you.

  debug=n	specifies debug level.  The debug level is a bitmask.

@@ -137,6 +157,12 @@ Options
  		This can be used to share devices/named pipes/sockets between
		hosts.  This functionality will be expanded in later versions.

  directio	bypass page cache on all read/write operations

  ignoreqv	ignore qid.version==0 as a marker to ignore cache

  noxattr	do not offer xattr functions on this mount.

  access	there are four access modes.
			user
				if a user tries to access a file on v9fs
+1 −2
Original line number Diff line number Diff line
@@ -8,9 +8,8 @@
#ifndef _9P_CACHE_H
#define _9P_CACHE_H

#include <linux/fscache.h>

#ifdef CONFIG_9P_FSCACHE
#include <linux/fscache.h>

extern int v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses,
					  const char *dev_name);
+19 −29
Original line number Diff line number Diff line
@@ -41,14 +41,24 @@ void v9fs_fid_add(struct dentry *dentry, struct p9_fid **pfid)
	*pfid = NULL;
}

static bool v9fs_is_writeable(int mode)
{
	if (mode & (P9_OWRITE|P9_ORDWR))
		return true;
	else
		return false;
}

/**
 * v9fs_fid_find_inode - search for an open fid off of the inode list
 * @inode: return a fid pointing to a specific inode
 * @want_writeable: only consider fids which are writeable
 * @uid: return a fid belonging to the specified user
 * @any: ignore uid as a selection criteria
 *
 */

static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid)
struct p9_fid *v9fs_fid_find_inode(struct inode *inode, bool want_writeable,
	kuid_t uid, bool any)
{
	struct hlist_head *h;
	struct p9_fid *fid, *ret = NULL;
@@ -58,7 +68,12 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid)
	spin_lock(&inode->i_lock);
	h = (struct hlist_head *)&inode->i_private;
	hlist_for_each_entry(fid, h, ilist) {
		if (uid_eq(fid->uid, uid)) {
		if (any || uid_eq(fid->uid, uid)) {
			if (want_writeable && !v9fs_is_writeable(fid->mode)) {
				p9_debug(P9_DEBUG_VFS, " mode: %x not writeable?\n",
							fid->mode);
				continue;
			}
			p9_fid_get(fid);
			ret = fid;
			break;
@@ -118,7 +133,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any)
		spin_unlock(&dentry->d_lock);
	} else {
		if (dentry->d_inode)
			ret = v9fs_fid_find_inode(dentry->d_inode, uid);
			ret = v9fs_fid_find_inode(dentry->d_inode, false, uid, any);
	}

	return ret;
@@ -299,28 +314,3 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
	return v9fs_fid_lookup_with_uid(dentry, uid, any);
}
struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
{
	int err;
	struct p9_fid *fid, *ofid;

	ofid = v9fs_fid_lookup_with_uid(dentry, GLOBAL_ROOT_UID, 0);
	fid = clone_fid(ofid);
	if (IS_ERR(fid))
		goto error_out;
	p9_fid_put(ofid);
	/*
	 * writeback fid will only be used to write back the
	 * dirty pages. We always request for the open fid in read-write
	 * mode so that a partial page write which result in page
	 * read can work.
	 */
	err = p9_client_open(fid, O_RDWR);
	if (err < 0) {
		p9_fid_put(fid);
		fid = ERR_PTR(err);
		goto error_out;
	}
error_out:
	return fid;
}
+30 −1
Original line number Diff line number Diff line
@@ -7,14 +7,16 @@
#ifndef FS_9P_FID_H
#define FS_9P_FID_H
#include <linux/list.h>
#include "v9fs.h"

struct p9_fid *v9fs_fid_find_inode(struct inode *inode, bool want_writeable,
	kuid_t uid, bool any);
struct p9_fid *v9fs_fid_lookup(struct dentry *dentry);
static inline struct p9_fid *v9fs_parent_fid(struct dentry *dentry)
{
	return v9fs_fid_lookup(dentry->d_parent);
}
void v9fs_fid_add(struct dentry *dentry, struct p9_fid **fid);
struct p9_fid *v9fs_writeback_fid(struct dentry *dentry);
void v9fs_open_fid_add(struct inode *inode, struct p9_fid **fid);
static inline struct p9_fid *clone_fid(struct p9_fid *fid)
{
@@ -32,4 +34,31 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
	p9_fid_put(fid);
	return nfid;
}
/**
 * v9fs_fid_addmodes - add cache flags to fid mode (for client use only)
 * @fid: fid to augment
 * @s_flags: session info mount flags
 * @s_cache: session info cache flags
 * @f_flags: unix open flags
 *
 * make sure mode reflects flags of underlying mounts
 * also qid.version == 0 reflects a synthetic or legacy file system
 * NOTE: these are set after open so only reflect 9p client not
 * underlying file system on server.
 */
static inline void v9fs_fid_add_modes(struct p9_fid *fid, int s_flags,
	int s_cache, unsigned int f_flags)
{
	if (fid->qid.type != P9_QTFILE)
		return;

	if ((!s_cache) ||
	   ((fid->qid.version == 0) && !(s_flags & V9FS_IGNORE_QV)) ||
	   (s_flags & V9FS_DIRECT_IO) || (f_flags & O_DIRECT)) {
		fid->mode |= P9L_DIRECT; /* no read or write cache */
	} else if ((!(s_cache & CACHE_WRITEBACK)) ||
				(f_flags & O_DSYNC) | (s_flags & V9FS_SYNC)) {
		fid->mode |= P9L_NOWRITECACHE;
	}
}
#endif
+31 −28
Original line number Diff line number Diff line
@@ -38,9 +38,7 @@ enum {
	/* String options */
	Opt_uname, Opt_remotename, Opt_cache, Opt_cachetag,
	/* Options that take no arguments */
	Opt_nodevmap,
	/* Cache options */
	Opt_cache_loose, Opt_fscache, Opt_mmap,
	Opt_nodevmap, Opt_noxattr, Opt_directio, Opt_ignoreqv,
	/* Access options */
	Opt_access, Opt_posixacl,
	/* Lock timeout option */
@@ -57,10 +55,10 @@ static const match_table_t tokens = {
	{Opt_uname, "uname=%s"},
	{Opt_remotename, "aname=%s"},
	{Opt_nodevmap, "nodevmap"},
	{Opt_noxattr, "noxattr"},
	{Opt_directio, "directio"},
	{Opt_ignoreqv, "ignoreqv"},
	{Opt_cache, "cache=%s"},
	{Opt_cache_loose, "loose"},
	{Opt_fscache, "fscache"},
	{Opt_mmap, "mmap"},
	{Opt_cachetag, "cachetag=%s"},
	{Opt_access, "access=%s"},
	{Opt_posixacl, "posixacl"},
@@ -68,32 +66,30 @@ static const match_table_t tokens = {
	{Opt_err, NULL}
};

static const char *const v9fs_cache_modes[nr__p9_cache_modes] = {
	[CACHE_NONE]	= "none",
	[CACHE_MMAP]	= "mmap",
	[CACHE_LOOSE]	= "loose",
	[CACHE_FSCACHE]	= "fscache",
};

/* Interpret mount options for cache mode */
static int get_cache_mode(char *s)
{
	int version = -EINVAL;

	if (!strcmp(s, "loose")) {
		version = CACHE_LOOSE;
		version = CACHE_SC_LOOSE;
		p9_debug(P9_DEBUG_9P, "Cache mode: loose\n");
	} else if (!strcmp(s, "fscache")) {
		version = CACHE_FSCACHE;
		version = CACHE_SC_FSCACHE;
		p9_debug(P9_DEBUG_9P, "Cache mode: fscache\n");
	} else if (!strcmp(s, "mmap")) {
		version = CACHE_MMAP;
		version = CACHE_SC_MMAP;
		p9_debug(P9_DEBUG_9P, "Cache mode: mmap\n");
	} else if (!strcmp(s, "readahead")) {
		version = CACHE_SC_READAHEAD;
		p9_debug(P9_DEBUG_9P, "Cache mode: readahead\n");
	} else if (!strcmp(s, "none")) {
		version = CACHE_NONE;
		version = CACHE_SC_NONE;
		p9_debug(P9_DEBUG_9P, "Cache mode: none\n");
	} else
		pr_info("Unknown Cache mode %s\n", s);
	} else if (kstrtoint(s, 0, &version) != 0) {
		version = -EINVAL;
		pr_info("Unknown Cache mode or invalid value %s\n", s);
	}
	return version;
}

@@ -121,9 +117,9 @@ int v9fs_show_options(struct seq_file *m, struct dentry *root)
	if (v9ses->nodev)
		seq_puts(m, ",nodevmap");
	if (v9ses->cache)
		seq_printf(m, ",%s", v9fs_cache_modes[v9ses->cache]);
		seq_printf(m, ",cache=%x", v9ses->cache);
#ifdef CONFIG_9P_FSCACHE
	if (v9ses->cachetag && v9ses->cache == CACHE_FSCACHE)
	if (v9ses->cachetag && (v9ses->cache & CACHE_FSCACHE))
		seq_printf(m, ",cachetag=%s", v9ses->cachetag);
#endif

@@ -143,9 +139,16 @@ int v9fs_show_options(struct seq_file *m, struct dentry *root)
		break;
	}

	if (v9ses->flags & V9FS_IGNORE_QV)
		seq_puts(m, ",ignoreqv");
	if (v9ses->flags & V9FS_DIRECT_IO)
		seq_puts(m, ",directio");
	if (v9ses->flags & V9FS_POSIX_ACL)
		seq_puts(m, ",posixacl");

	if (v9ses->flags & V9FS_NO_XATTR)
		seq_puts(m, ",noxattr");

	return p9_show_client_options(m, v9ses->clnt);
}

@@ -266,14 +269,14 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
		case Opt_nodevmap:
			v9ses->nodev = 1;
			break;
		case Opt_cache_loose:
			v9ses->cache = CACHE_LOOSE;
		case Opt_noxattr:
			v9ses->flags |= V9FS_NO_XATTR;
			break;
		case Opt_fscache:
			v9ses->cache = CACHE_FSCACHE;
		case Opt_directio:
			v9ses->flags |= V9FS_DIRECT_IO;
			break;
		case Opt_mmap:
			v9ses->cache = CACHE_MMAP;
		case Opt_ignoreqv:
			v9ses->flags |= V9FS_IGNORE_QV;
			break;
		case Opt_cachetag:
#ifdef CONFIG_9P_FSCACHE
@@ -468,7 +471,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,

#ifdef CONFIG_9P_FSCACHE
	/* register the session for caching */
	if (v9ses->cache == CACHE_FSCACHE) {
	if (v9ses->cache & CACHE_FSCACHE) {
		rc = v9fs_cache_session_get_cookie(v9ses, dev_name);
		if (rc < 0)
			goto err_clnt;
Loading