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

Commit 9d1c0213 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
  net/9p: Fix the msize calculation.
  fs/9p: add 9P2000.L unlinkat operation
  fs/9p: add 9P2000.L renameat operation
  fs/9p: Always ask new inode in create
  fs/9p: Clean-up get_protocol_version() to use strcmp
  fs/9p: Fix invalid mount options/args
  fs/9p: When doing inode lookup compare qid details and inode mode bits.
  fs/9p: Fid is not valid after a failed clunk.
  net/9p: Remove structure not used in the code
  VirtIO can transfer VIRTQUEUE_NUM of pages.
  Fix the size of receive buffer packing onto VirtIO ring.
  9p: clean up packet dump code
  fs/9p: remove rename work around in 9p
  net/9p: fix client code to fail more gracefully on protocol error
parents 807094c0 c9ffb05c
Loading
Loading
Loading
Loading
+9 −11
Original line number Original line Diff line number Diff line
@@ -108,11 +108,10 @@ static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data,
					 void *buffer, uint16_t bufmax)
					 void *buffer, uint16_t bufmax)
{
{
	const struct v9fs_inode *v9inode = cookie_netfs_data;
	const struct v9fs_inode *v9inode = cookie_netfs_data;
	memcpy(buffer, &v9inode->fscache_key->path,
	memcpy(buffer, &v9inode->qid.path, sizeof(v9inode->qid.path));
	       sizeof(v9inode->fscache_key->path));
	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &v9inode->vfs_inode,
	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &v9inode->vfs_inode,
		   v9inode->fscache_key->path);
		   v9inode->qid.path);
	return sizeof(v9inode->fscache_key->path);
	return sizeof(v9inode->qid.path);
}
}


static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data,
static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data,
@@ -129,11 +128,10 @@ static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data,
					 void *buffer, uint16_t buflen)
					 void *buffer, uint16_t buflen)
{
{
	const struct v9fs_inode *v9inode = cookie_netfs_data;
	const struct v9fs_inode *v9inode = cookie_netfs_data;
	memcpy(buffer, &v9inode->fscache_key->version,
	memcpy(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version));
	       sizeof(v9inode->fscache_key->version));
	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &v9inode->vfs_inode,
	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &v9inode->vfs_inode,
		   v9inode->fscache_key->version);
		   v9inode->qid.version);
	return sizeof(v9inode->fscache_key->version);
	return sizeof(v9inode->qid.version);
}
}


static enum
static enum
@@ -143,11 +141,11 @@ fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
{
{
	const struct v9fs_inode *v9inode = cookie_netfs_data;
	const struct v9fs_inode *v9inode = cookie_netfs_data;


	if (buflen != sizeof(v9inode->fscache_key->version))
	if (buflen != sizeof(v9inode->qid.version))
		return FSCACHE_CHECKAUX_OBSOLETE;
		return FSCACHE_CHECKAUX_OBSOLETE;


	if (memcmp(buffer, &v9inode->fscache_key->version,
	if (memcmp(buffer, &v9inode->qid.version,
		   sizeof(v9inode->fscache_key->version)))
		   sizeof(v9inode->qid.version)))
		return FSCACHE_CHECKAUX_OBSOLETE;
		return FSCACHE_CHECKAUX_OBSOLETE;


	return FSCACHE_CHECKAUX_OKAY;
	return FSCACHE_CHECKAUX_OKAY;
+0 −9
Original line number Original line Diff line number Diff line
@@ -93,15 +93,6 @@ static inline void v9fs_uncache_page(struct inode *inode, struct page *page)
	BUG_ON(PageFsCache(page));
	BUG_ON(PageFsCache(page));
}
}


static inline void v9fs_fscache_set_key(struct inode *inode,
					struct p9_qid *qid)
{
	struct v9fs_inode *v9inode = V9FS_I(inode);
	spin_lock(&v9inode->fscache_lock);
	v9inode->fscache_key = qid;
	spin_unlock(&v9inode->fscache_lock);
}

static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
						   struct page *page)
						   struct page *page)
{
{
+35 −10
Original line number Original line Diff line number Diff line
@@ -78,6 +78,25 @@ static const match_table_t tokens = {
	{Opt_err, NULL}
	{Opt_err, NULL}
};
};


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

	if (!strcmp(s, "loose")) {
		version = CACHE_LOOSE;
		P9_DPRINTK(P9_DEBUG_9P, "Cache mode: loose\n");
	} else if (!strcmp(s, "fscache")) {
		version = CACHE_FSCACHE;
		P9_DPRINTK(P9_DEBUG_9P, "Cache mode: fscache\n");
	} else if (!strcmp(s, "none")) {
		version = CACHE_NONE;
		P9_DPRINTK(P9_DEBUG_9P, "Cache mode: none\n");
	} else
		printk(KERN_INFO "9p: Unknown Cache mode %s.\n", s);
	return version;
}

/**
/**
 * v9fs_parse_options - parse mount options into session structure
 * v9fs_parse_options - parse mount options into session structure
 * @v9ses: existing v9fs session information
 * @v9ses: existing v9fs session information
@@ -97,7 +116,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
	/* setup defaults */
	/* setup defaults */
	v9ses->afid = ~0;
	v9ses->afid = ~0;
	v9ses->debug = 0;
	v9ses->debug = 0;
	v9ses->cache = 0;
	v9ses->cache = CACHE_NONE;
#ifdef CONFIG_9P_FSCACHE
#ifdef CONFIG_9P_FSCACHE
	v9ses->cachetag = NULL;
	v9ses->cachetag = NULL;
#endif
#endif
@@ -171,13 +190,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
				  "problem allocating copy of cache arg\n");
				  "problem allocating copy of cache arg\n");
				goto free_and_return;
				goto free_and_return;
			}
			}
			ret = get_cache_mode(s);
			if (ret == -EINVAL) {
				kfree(s);
				goto free_and_return;
			}


			if (strcmp(s, "loose") == 0)
			v9ses->cache = ret;
				v9ses->cache = CACHE_LOOSE;
			else if (strcmp(s, "fscache") == 0)
				v9ses->cache = CACHE_FSCACHE;
			else
				v9ses->cache = CACHE_NONE;
			kfree(s);
			kfree(s);
			break;
			break;


@@ -200,9 +219,15 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
			} else {
			} else {
				v9ses->flags |= V9FS_ACCESS_SINGLE;
				v9ses->flags |= V9FS_ACCESS_SINGLE;
				v9ses->uid = simple_strtoul(s, &e, 10);
				v9ses->uid = simple_strtoul(s, &e, 10);
				if (*e != '\0')
				if (*e != '\0') {
					v9ses->uid = ~0;
					ret = -EINVAL;
					printk(KERN_INFO "9p: Unknown access "
							"argument %s.\n", s);
					kfree(s);
					goto free_and_return;
				}
				}
			}

			kfree(s);
			kfree(s);
			break;
			break;


@@ -487,8 +512,8 @@ static void v9fs_inode_init_once(void *foo)
	struct v9fs_inode *v9inode = (struct v9fs_inode *)foo;
	struct v9fs_inode *v9inode = (struct v9fs_inode *)foo;
#ifdef CONFIG_9P_FSCACHE
#ifdef CONFIG_9P_FSCACHE
	v9inode->fscache = NULL;
	v9inode->fscache = NULL;
	v9inode->fscache_key = NULL;
#endif
#endif
	memset(&v9inode->qid, 0, sizeof(v9inode->qid));
	inode_init_once(&v9inode->vfs_inode);
	inode_init_once(&v9inode->vfs_inode);
}
}


+24 −5
Original line number Original line Diff line number Diff line
@@ -125,8 +125,8 @@ struct v9fs_inode {
#ifdef CONFIG_9P_FSCACHE
#ifdef CONFIG_9P_FSCACHE
	spinlock_t fscache_lock;
	spinlock_t fscache_lock;
	struct fscache_cookie *fscache;
	struct fscache_cookie *fscache;
	struct p9_qid *fscache_key;
#endif
#endif
	struct p9_qid qid;
	unsigned int cache_validity;
	unsigned int cache_validity;
	struct p9_fid *writeback_fid;
	struct p9_fid *writeback_fid;
	struct mutex v_mutex;
	struct mutex v_mutex;
@@ -153,13 +153,13 @@ extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd,
			void *p);
			void *p);
extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
					 struct p9_fid *fid,
					 struct p9_fid *fid,
					 struct super_block *sb);
					 struct super_block *sb, int new);
extern const struct inode_operations v9fs_dir_inode_operations_dotl;
extern const struct inode_operations v9fs_dir_inode_operations_dotl;
extern const struct inode_operations v9fs_file_inode_operations_dotl;
extern const struct inode_operations v9fs_file_inode_operations_dotl;
extern const struct inode_operations v9fs_symlink_inode_operations_dotl;
extern const struct inode_operations v9fs_symlink_inode_operations_dotl;
extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses,
extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses,
					      struct p9_fid *fid,
					      struct p9_fid *fid,
					      struct super_block *sb);
					      struct super_block *sb, int new);


/* other default globals */
/* other default globals */
#define V9FS_PORT	564
#define V9FS_PORT	564
@@ -201,8 +201,27 @@ v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
			struct super_block *sb)
			struct super_block *sb)
{
{
	if (v9fs_proto_dotl(v9ses))
	if (v9fs_proto_dotl(v9ses))
		return v9fs_inode_from_fid_dotl(v9ses, fid, sb);
		return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 0);
	else
	else
		return v9fs_inode_from_fid(v9ses, fid, sb);
		return v9fs_inode_from_fid(v9ses, fid, sb, 0);
}
}

/**
 * v9fs_get_new_inode_from_fid - Helper routine to populate an inode by
 * issuing a attribute request
 * @v9ses: session information
 * @fid: fid to issue attribute request for
 * @sb: superblock on which to create inode
 *
 */
static inline struct inode *
v9fs_get_new_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
			    struct super_block *sb)
{
	if (v9fs_proto_dotl(v9ses))
		return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 1);
	else
		return v9fs_inode_from_fid(v9ses, fid, sb, 1);
}

#endif
#endif
+85 −33
Original line number Original line Diff line number Diff line
@@ -216,7 +216,6 @@ struct inode *v9fs_alloc_inode(struct super_block *sb)
		return NULL;
		return NULL;
#ifdef CONFIG_9P_FSCACHE
#ifdef CONFIG_9P_FSCACHE
	v9inode->fscache = NULL;
	v9inode->fscache = NULL;
	v9inode->fscache_key = NULL;
	spin_lock_init(&v9inode->fscache_lock);
	spin_lock_init(&v9inode->fscache_lock);
#endif
#endif
	v9inode->writeback_fid = NULL;
	v9inode->writeback_fid = NULL;
@@ -433,17 +432,60 @@ void v9fs_evict_inode(struct inode *inode)
	}
	}
}
}


static int v9fs_test_inode(struct inode *inode, void *data)
{
	int umode;
	struct v9fs_inode *v9inode = V9FS_I(inode);
	struct p9_wstat *st = (struct p9_wstat *)data;
	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);

	umode = p9mode2unixmode(v9ses, st->mode);
	/* don't match inode of different type */
	if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
		return 0;

	/* compare qid details */
	if (memcmp(&v9inode->qid.version,
		   &st->qid.version, sizeof(v9inode->qid.version)))
		return 0;

	if (v9inode->qid.type != st->qid.type)
		return 0;
	return 1;
}

static int v9fs_test_new_inode(struct inode *inode, void *data)
{
	return 0;
}

static int v9fs_set_inode(struct inode *inode,  void *data)
{
	struct v9fs_inode *v9inode = V9FS_I(inode);
	struct p9_wstat *st = (struct p9_wstat *)data;

	memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
	return 0;
}

static struct inode *v9fs_qid_iget(struct super_block *sb,
static struct inode *v9fs_qid_iget(struct super_block *sb,
				   struct p9_qid *qid,
				   struct p9_qid *qid,
				   struct p9_wstat *st)
				   struct p9_wstat *st,
				   int new)
{
{
	int retval, umode;
	int retval, umode;
	unsigned long i_ino;
	unsigned long i_ino;
	struct inode *inode;
	struct inode *inode;
	struct v9fs_session_info *v9ses = sb->s_fs_info;
	struct v9fs_session_info *v9ses = sb->s_fs_info;
	int (*test)(struct inode *, void *);

	if (new)
		test = v9fs_test_new_inode;
	else
		test = v9fs_test_inode;


	i_ino = v9fs_qid2ino(qid);
	i_ino = v9fs_qid2ino(qid);
	inode = iget_locked(sb, i_ino);
	inode = iget5_locked(sb, i_ino, test, v9fs_set_inode, st);
	if (!inode)
	if (!inode)
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);
	if (!(inode->i_state & I_NEW))
	if (!(inode->i_state & I_NEW))
@@ -453,6 +495,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
	 * FIXME!! we may need support for stale inodes
	 * FIXME!! we may need support for stale inodes
	 * later.
	 * later.
	 */
	 */
	inode->i_ino = i_ino;
	umode = p9mode2unixmode(v9ses, st->mode);
	umode = p9mode2unixmode(v9ses, st->mode);
	retval = v9fs_init_inode(v9ses, inode, umode);
	retval = v9fs_init_inode(v9ses, inode, umode);
	if (retval)
	if (retval)
@@ -460,7 +503,6 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,


	v9fs_stat2inode(st, inode, sb);
	v9fs_stat2inode(st, inode, sb);
#ifdef CONFIG_9P_FSCACHE
#ifdef CONFIG_9P_FSCACHE
	v9fs_fscache_set_key(inode, &st->qid);
	v9fs_cache_inode_get_cookie(inode);
	v9fs_cache_inode_get_cookie(inode);
#endif
#endif
	unlock_new_inode(inode);
	unlock_new_inode(inode);
@@ -474,7 +516,7 @@ error:


struct inode *
struct inode *
v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
		    struct super_block *sb)
		    struct super_block *sb, int new)
{
{
	struct p9_wstat *st;
	struct p9_wstat *st;
	struct inode *inode = NULL;
	struct inode *inode = NULL;
@@ -483,7 +525,7 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
	if (IS_ERR(st))
	if (IS_ERR(st))
		return ERR_CAST(st);
		return ERR_CAST(st);


	inode = v9fs_qid_iget(sb, &st->qid, st);
	inode = v9fs_qid_iget(sb, &st->qid, st, new);
	p9stat_free(st);
	p9stat_free(st);
	kfree(st);
	kfree(st);
	return inode;
	return inode;
@@ -492,38 +534,50 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
/**
/**
 * v9fs_remove - helper function to remove files and directories
 * v9fs_remove - helper function to remove files and directories
 * @dir: directory inode that is being deleted
 * @dir: directory inode that is being deleted
 * @file:  dentry that is being deleted
 * @dentry:  dentry that is being deleted
 * @rmdir: removing a directory
 * @rmdir: removing a directory
 *
 *
 */
 */


static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
{
{
	int retval;
	struct inode *inode;
	struct p9_fid *v9fid;
	int retval = -EOPNOTSUPP;
	struct inode *file_inode;
	struct p9_fid *v9fid, *dfid;
	struct v9fs_session_info *v9ses;


	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n",
		rmdir);
		   dir, dentry, flags);


	file_inode = file->d_inode;
	v9ses = v9fs_inode2v9ses(dir);
	v9fid = v9fs_fid_clone(file);
	inode = dentry->d_inode;
	dfid = v9fs_fid_lookup(dentry->d_parent);
	if (IS_ERR(dfid)) {
		retval = PTR_ERR(dfid);
		P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
		return retval;
	}
	if (v9fs_proto_dotl(v9ses))
		retval = p9_client_unlinkat(dfid, dentry->d_name.name, flags);
	if (retval == -EOPNOTSUPP) {
		/* Try the one based on path */
		v9fid = v9fs_fid_clone(dentry);
		if (IS_ERR(v9fid))
		if (IS_ERR(v9fid))
			return PTR_ERR(v9fid);
			return PTR_ERR(v9fid);

		retval = p9_client_remove(v9fid);
		retval = p9_client_remove(v9fid);
	}
	if (!retval) {
	if (!retval) {
		/*
		/*
		 * directories on unlink should have zero
		 * directories on unlink should have zero
		 * link count
		 * link count
		 */
		 */
		if (rmdir) {
		if (flags & AT_REMOVEDIR) {
			clear_nlink(file_inode);
			clear_nlink(inode);
			drop_nlink(dir);
			drop_nlink(dir);
		} else
		} else
			drop_nlink(file_inode);
			drop_nlink(inode);


		v9fs_invalidate_inode_attr(file_inode);
		v9fs_invalidate_inode_attr(inode);
		v9fs_invalidate_inode_attr(dir);
		v9fs_invalidate_inode_attr(dir);
	}
	}
	return retval;
	return retval;
@@ -585,7 +639,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
	}
	}


	/* instantiate inode and assign the unopened fid to the dentry */
	/* instantiate inode and assign the unopened fid to the dentry */
	inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
	inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
	if (IS_ERR(inode)) {
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		err = PTR_ERR(inode);
		P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
		P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
@@ -814,7 +868,7 @@ int v9fs_vfs_unlink(struct inode *i, struct dentry *d)


int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
{
{
	return v9fs_remove(i, d, 1);
	return v9fs_remove(i, d, AT_REMOVEDIR);
}
}


/**
/**
@@ -862,9 +916,12 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,


	down_write(&v9ses->rename_sem);
	down_write(&v9ses->rename_sem);
	if (v9fs_proto_dotl(v9ses)) {
	if (v9fs_proto_dotl(v9ses)) {
		retval = p9_client_renameat(olddirfid, old_dentry->d_name.name,
					    newdirfid, new_dentry->d_name.name);
		if (retval == -EOPNOTSUPP)
			retval = p9_client_rename(oldfid, newdirfid,
			retval = p9_client_rename(oldfid, newdirfid,
					(char *) new_dentry->d_name.name);
						  new_dentry->d_name.name);
		if (retval != -ENOSYS)
		if (retval != -EOPNOTSUPP)
			goto clunk_newdir;
			goto clunk_newdir;
	}
	}
	if (old_dentry->d_parent != new_dentry->d_parent) {
	if (old_dentry->d_parent != new_dentry->d_parent) {
@@ -889,11 +946,6 @@ clunk_newdir:
				clear_nlink(new_inode);
				clear_nlink(new_inode);
			else
			else
				drop_nlink(new_inode);
				drop_nlink(new_inode);
			/*
			 * Work around vfs rename rehash bug with
			 * FS_RENAME_DOES_D_MOVE
			 */
			v9fs_invalidate_inode_attr(new_inode);
		}
		}
		if (S_ISDIR(old_inode->i_mode)) {
		if (S_ISDIR(old_inode->i_mode)) {
			if (!new_inode)
			if (!new_inode)
Loading