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

Commit 7da4221b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '9p-for-4.20' of git://github.com/martinetd/linux

Pull 9p updates from Dominique Martinet:
 "Highlights this time around are the end of Matthew's work to remove
  the custom 9p request cache and use a slab directly for requests, with
  some extra patches on my end to not degrade performance, but it's a
  very good cleanup.

  Tomas and I fixed a few more syzkaller bugs (refcount is the big one),
  and I had a go at the coverity bugs and at some of the bugzilla
  reports we had open for a while.

  I'm a bit disappointed that I couldn't get much reviews for a few of
  my own patches, but the big ones got some and it's all been soaking in
  linux-next for quite a while so I think it should be OK.

  Summary:

   - Finish removing the custom 9p request cache mechanism

   - Embed part of the fcall in the request to have better slab
     performance (msize usually is power of two aligned)

   - syzkaller fixes:
      * add a refcount to 9p requests to avoid use after free
      * a few double free issues

   - A few coverity fixes

   - Some old patches that were in the bugzilla:
      * do not trust pdu content for size header
      * mount option for lock retry interval"

* tag '9p-for-4.20' of git://github.com/martinetd/linux: (21 commits)
  9p/trans_fd: put worker reqs on destroy
  9p/trans_fd: abort p9_read_work if req status changed
  9p: potential NULL dereference
  9p locks: fix glock.client_id leak in do_lock
  9p: p9dirent_read: check network-provided name length
  9p/rdma: remove useless check in cm_event_handler
  9p: acl: fix uninitialized iattr access
  9p locks: add mount option for lock retry interval
  9p: do not trust pdu content for stat item size
  9p: Rename req to rreq in trans_fd
  9p: fix spelling mistake in fall-through annotation
  9p/rdma: do not disconnect on down_interruptible EAGAIN
  9p: Add refcount to p9_req_t
  9p: rename p9_free_req() function
  9p: add a per-client fcall kmem_cache
  9p: embed fcall in req to round down buffer allocs
  9p: Remove p9_idpool
  9p: Use a slab for allocating requests
  9p: clear dangling pointers in p9stat_free
  v9fs_dir_readdir: fix double-free on p9stat_read error
  ...
parents 673c790e fb488fc1
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -276,7 +276,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
	switch (handler->flags) {
	switch (handler->flags) {
	case ACL_TYPE_ACCESS:
	case ACL_TYPE_ACCESS:
		if (acl) {
		if (acl) {
			struct iattr iattr;
			struct iattr iattr = { 0 };
			struct posix_acl *old_acl = acl;
			struct posix_acl *old_acl = acl;


			retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
			retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
+21 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,8 @@ enum {
	Opt_cache_loose, Opt_fscache, Opt_mmap,
	Opt_cache_loose, Opt_fscache, Opt_mmap,
	/* Access options */
	/* Access options */
	Opt_access, Opt_posixacl,
	Opt_access, Opt_posixacl,
	/* Lock timeout option */
	Opt_locktimeout,
	/* Error token */
	/* Error token */
	Opt_err
	Opt_err
};
};
@@ -80,6 +82,7 @@ static const match_table_t tokens = {
	{Opt_cachetag, "cachetag=%s"},
	{Opt_cachetag, "cachetag=%s"},
	{Opt_access, "access=%s"},
	{Opt_access, "access=%s"},
	{Opt_posixacl, "posixacl"},
	{Opt_posixacl, "posixacl"},
	{Opt_locktimeout, "locktimeout=%u"},
	{Opt_err, NULL}
	{Opt_err, NULL}
};
};


@@ -187,6 +190,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
#ifdef CONFIG_9P_FSCACHE
#ifdef CONFIG_9P_FSCACHE
	v9ses->cachetag = NULL;
	v9ses->cachetag = NULL;
#endif
#endif
	v9ses->session_lock_timeout = P9_LOCK_TIMEOUT;


	if (!opts)
	if (!opts)
		return 0;
		return 0;
@@ -359,6 +363,23 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
#endif
#endif
			break;
			break;


		case Opt_locktimeout:
			r = match_int(&args[0], &option);
			if (r < 0) {
				p9_debug(P9_DEBUG_ERROR,
					 "integer field, but no integer?\n");
				ret = r;
				continue;
			}
			if (option < 1) {
				p9_debug(P9_DEBUG_ERROR,
					 "locktimeout must be a greater than zero integer.\n");
				ret = -EINVAL;
				continue;
			}
			v9ses->session_lock_timeout = (long)option * HZ;
			break;

		default:
		default:
			continue;
			continue;
		}
		}
+1 −0
Original line number Original line Diff line number Diff line
@@ -116,6 +116,7 @@ struct v9fs_session_info {
	struct p9_client *clnt;	/* 9p client */
	struct p9_client *clnt;	/* 9p client */
	struct list_head slist; /* list of sessions registered with v9fs */
	struct list_head slist; /* list of sessions registered with v9fs */
	struct rw_semaphore rename_sem;
	struct rw_semaphore rename_sem;
	long session_lock_timeout; /* retry interval for blocking locks */
};
};


/* cache_validity flags */
/* cache_validity flags */
+3 −16
Original line number Original line Diff line number Diff line
@@ -76,15 +76,6 @@ static inline int dt_type(struct p9_wstat *mistat)
	return rettype;
	return rettype;
}
}


static void p9stat_init(struct p9_wstat *stbuf)
{
	stbuf->name  = NULL;
	stbuf->uid   = NULL;
	stbuf->gid   = NULL;
	stbuf->muid  = NULL;
	stbuf->extension = NULL;
}

/**
/**
 * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir
 * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir
 * @filp: opened file structure
 * @filp: opened file structure
@@ -114,7 +105,6 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
	int err = 0;
	int err = 0;
	struct p9_fid *fid;
	struct p9_fid *fid;
	int buflen;
	int buflen;
	int reclen = 0;
	struct p9_rdir *rdir;
	struct p9_rdir *rdir;
	struct kvec kvec;
	struct kvec kvec;


@@ -145,15 +135,12 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
			rdir->tail = n;
			rdir->tail = n;
		}
		}
		while (rdir->head < rdir->tail) {
		while (rdir->head < rdir->tail) {
			p9stat_init(&st);
			err = p9stat_read(fid->clnt, rdir->buf + rdir->head,
			err = p9stat_read(fid->clnt, rdir->buf + rdir->head,
					  rdir->tail - rdir->head, &st);
					  rdir->tail - rdir->head, &st);
			if (err) {
			if (err <= 0) {
				p9_debug(P9_DEBUG_VFS, "returned %d\n", err);
				p9_debug(P9_DEBUG_VFS, "returned %d\n", err);
				p9stat_free(&st);
				return -EIO;
				return -EIO;
			}
			}
			reclen = st.size+2;


			over = !dir_emit(ctx, st.name, strlen(st.name),
			over = !dir_emit(ctx, st.name, strlen(st.name),
					 v9fs_qid2ino(&st.qid), dt_type(&st));
					 v9fs_qid2ino(&st.qid), dt_type(&st));
@@ -161,8 +148,8 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
			if (over)
			if (over)
				return 0;
				return 0;


			rdir->head += reclen;
			rdir->head += err;
			ctx->pos += reclen;
			ctx->pos += err;
		}
		}
	}
	}
}
}
+20 −4
Original line number Original line Diff line number Diff line
@@ -154,6 +154,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
	uint8_t status = P9_LOCK_ERROR;
	uint8_t status = P9_LOCK_ERROR;
	int res = 0;
	int res = 0;
	unsigned char fl_type;
	unsigned char fl_type;
	struct v9fs_session_info *v9ses;


	fid = filp->private_data;
	fid = filp->private_data;
	BUG_ON(fid == NULL);
	BUG_ON(fid == NULL);
@@ -189,6 +190,8 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
	if (IS_SETLKW(cmd))
	if (IS_SETLKW(cmd))
		flock.flags = P9_LOCK_FLAGS_BLOCK;
		flock.flags = P9_LOCK_FLAGS_BLOCK;


	v9ses = v9fs_inode2v9ses(file_inode(filp));

	/*
	/*
	 * if its a blocked request and we get P9_LOCK_BLOCKED as the status
	 * if its a blocked request and we get P9_LOCK_BLOCKED as the status
	 * for lock request, keep on trying
	 * for lock request, keep on trying
@@ -202,8 +205,17 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
			break;
			break;
		if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd))
		if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd))
			break;
			break;
		if (schedule_timeout_interruptible(P9_LOCK_TIMEOUT) != 0)
		if (schedule_timeout_interruptible(v9ses->session_lock_timeout)
				!= 0)
			break;
			break;
		/*
		 * p9_client_lock_dotl overwrites flock.client_id with the
		 * server message, free and reuse the client name
		 */
		if (flock.client_id != fid->clnt->name) {
			kfree(flock.client_id);
			flock.client_id = fid->clnt->name;
		}
	}
	}


	/* map 9p status to VFS status */
	/* map 9p status to VFS status */
@@ -216,7 +228,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
		break;
		break;
	default:
	default:
		WARN_ONCE(1, "unknown lock status code: %d\n", status);
		WARN_ONCE(1, "unknown lock status code: %d\n", status);
		/* fallthough */
		/* fall through */
	case P9_LOCK_ERROR:
	case P9_LOCK_ERROR:
	case P9_LOCK_GRACE:
	case P9_LOCK_GRACE:
		res = -ENOLCK;
		res = -ENOLCK;
@@ -235,6 +247,8 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
		locks_lock_file_wait(filp, fl);
		locks_lock_file_wait(filp, fl);
		fl->fl_type = fl_type;
		fl->fl_type = fl_type;
	}
	}
	if (flock.client_id != fid->clnt->name)
		kfree(flock.client_id);
out:
out:
	return res;
	return res;
}
}
@@ -269,7 +283,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)


	res = p9_client_getlock_dotl(fid, &glock);
	res = p9_client_getlock_dotl(fid, &glock);
	if (res < 0)
	if (res < 0)
		return res;
		goto out;
	/* map 9p lock type to os lock type */
	/* map 9p lock type to os lock type */
	switch (glock.type) {
	switch (glock.type) {
	case P9_LOCK_TYPE_RDLCK:
	case P9_LOCK_TYPE_RDLCK:
@@ -290,6 +304,8 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
			fl->fl_end = glock.start + glock.length - 1;
			fl->fl_end = glock.start + glock.length - 1;
		fl->fl_pid = -glock.proc_id;
		fl->fl_pid = -glock.proc_id;
	}
	}
out:
	if (glock.client_id != fid->clnt->name)
		kfree(glock.client_id);
		kfree(glock.client_id);
	return res;
	return res;
}
}
Loading