Commit 80b7065e authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '9p-for-6.18-rc1' of https://github.com/martinetd/linux

Pull 9p updates from Dominique Martinet:
 "A bunch of unrelated fixes:

   - polling fix for trans fd that ought to have been fixed otherwise
     back in March, but apparently came back somewhere else...

   - USB transport buffer overflow fix

   - Some dentry lifetime rework to handle metadata update for currently
     opened files in uncached mode, or inode type change in cached mode

   - a double-put on invalid flush found by syzbot

   - and finally /sys/fs/9p/caches not advancing buffer and overwriting
     itself for large contents

  Thanks to everyone involved!"

* tag '9p-for-6.18-rc1' of https://github.com/martinetd/linux:
  9p: sysfs_init: don't hardcode error to ENOMEM
  9p: fix /sys/fs/9p/caches overwriting itself
  9p: clean up comment typos
  9p/trans_fd: p9_fd_request: kick rx thread if EPOLLIN
  net/9p: fix double req put in p9_fd_cancelled
  net/9p: Fix buffer overflow in USB transport layer
  fs/9p: Add p9_debug(VFS) in d_revalidate
  fs/9p: Invalidate dentry if inode type change detected in cached mode
  fs/9p: Refresh metadata in d_revalidate for uncached mode too
parents 18a7e218 528f218b
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -438,8 +438,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
		v9ses->flags &= ~V9FS_ACCESS_MASK;
		v9ses->flags |= V9FS_ACCESS_USER;
	}
	/*FIXME !! */
	/* for legacy mode, fall back to V9FS_ACCESS_ANY */
	/* FIXME: for legacy mode, fall back to V9FS_ACCESS_ANY */
	if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) &&
		((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {

@@ -450,7 +449,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
	if (!v9fs_proto_dotl(v9ses) ||
		!((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
		/*
		 * We support ACL checks on clinet only if the protocol is
		 * We support ACL checks on client only if the protocol is
		 * 9P2000.L and access is V9FS_ACCESS_CLIENT.
		 */
		v9ses->flags &= ~V9FS_ACL_MASK;
@@ -561,7 +560,7 @@ static ssize_t caches_show(struct kobject *kobj,
	spin_lock(&v9fs_sessionlist_lock);
	list_for_each_entry(v9ses, &v9fs_sessionlist, slist) {
		if (v9ses->cachetag) {
			n = snprintf(buf, limit, "%s\n", v9ses->cachetag);
			n = snprintf(buf + count, limit, "%s\n", v9ses->cachetag);
			if (n < 0) {
				count = n;
				break;
@@ -597,13 +596,16 @@ static const struct attribute_group v9fs_attr_group = {

static int __init v9fs_sysfs_init(void)
{
	int ret;

	v9fs_kobj = kobject_create_and_add("9p", fs_kobj);
	if (!v9fs_kobj)
		return -ENOMEM;

	if (sysfs_create_group(v9fs_kobj, &v9fs_attr_group)) {
	ret = sysfs_create_group(v9fs_kobj, &v9fs_attr_group);
	if (ret) {
		kobject_put(v9fs_kobj);
		return -ENOMEM;
		return ret;
	}

	return 0;
@@ -669,7 +671,7 @@ static int __init init_v9fs(void)
	int err;

	pr_info("Installing v9fs 9p2000 file system support\n");
	/* TODO: Setup list of registered trasnport modules */
	/* TODO: Setup list of registered transport modules */

	err = v9fs_init_inode_cache();
	if (err < 0) {
+29 −4
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
	struct p9_fid *fid;
	struct inode *inode;
	struct v9fs_inode *v9inode;
	unsigned int cached;

	if (flags & LOOKUP_RCU)
		return -ECHILD;
@@ -75,13 +76,22 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
		goto out_valid;

	v9inode = V9FS_I(inode);
	if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);

	cached = v9ses->cache & (CACHE_META | CACHE_LOOSE);

	if (!cached || v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
		int retval;
		struct v9fs_session_info *v9ses;

		fid = v9fs_fid_lookup(dentry);
		if (IS_ERR(fid))
		if (IS_ERR(fid)) {
			p9_debug(
				P9_DEBUG_VFS,
				"v9fs_fid_lookup: dentry = %pd (%p), got error %pe\n",
				dentry, dentry, fid);
			return PTR_ERR(fid);
		}

		v9ses = v9fs_inode2v9ses(inode);
		if (v9fs_proto_dotl(v9ses))
@@ -90,12 +100,25 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
			retval = v9fs_refresh_inode(fid, inode);
		p9_fid_put(fid);

		if (retval == -ENOENT)
		if (retval == -ENOENT) {
			p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) invalidated due to ENOENT\n",
				 dentry, dentry);
			return 0;
		if (retval < 0)
		}
		if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
			p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) invalidated due to type change\n",
				 dentry, dentry);
			return 0;
		}
		if (retval < 0) {
			p9_debug(P9_DEBUG_VFS,
				"refresh inode: dentry = %pd (%p), got error %pe\n",
				dentry, dentry, ERR_PTR(retval));
			return retval;
		}
	}
out_valid:
	p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) is valid\n", dentry, dentry);
	return 1;
}

@@ -127,6 +150,8 @@ const struct dentry_operations v9fs_cached_dentry_operations = {
};

const struct dentry_operations v9fs_dentry_operations = {
	.d_revalidate = v9fs_lookup_revalidate,
	.d_weak_revalidate = __v9fs_lookup_revalidate,
	.d_release = v9fs_dentry_release,
	.d_unalias_trylock = v9fs_dentry_unalias_trylock,
	.d_unalias_unlock = v9fs_dentry_unalias_unlock,
+7 −1
Original line number Diff line number Diff line
@@ -1339,8 +1339,14 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
	 * Don't update inode if the file type is different
	 */
	umode = p9mode2unixmode(v9ses, st, &rdev);
	if (inode_wrong_type(inode, umode))
	if (inode_wrong_type(inode, umode)) {
		/*
		 * Do this as a way of letting the caller know the inode should not
		 * be reused
		 */
		v9fs_invalidate_inode_attr(inode);
		goto out;
	}

	/*
	 * We don't want to refresh inode->i_size,
+7 −1
Original line number Diff line number Diff line
@@ -897,8 +897,14 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
	/*
	 * Don't update inode if the file type is different
	 */
	if (inode_wrong_type(inode, st->st_mode))
	if (inode_wrong_type(inode, st->st_mode)) {
		/*
		 * Do this as a way of letting the caller know the inode should not
		 * be reused
		 */
		v9fs_invalidate_inode_attr(inode);
		goto out;
	}

	/*
	 * We don't want to refresh inode->i_size,
+5 −12
Original line number Diff line number Diff line
@@ -666,7 +666,6 @@ static void p9_poll_mux(struct p9_conn *m)

static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
{
	__poll_t n;
	int err;
	struct p9_trans_fd *ts = client->trans;
	struct p9_conn *m = &ts->conn;
@@ -686,13 +685,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
	list_add_tail(&req->req_list, &m->unsent_req_list);
	spin_unlock(&m->req_lock);

	if (test_and_clear_bit(Wpending, &m->wsched))
		n = EPOLLOUT;
	else
		n = p9_fd_poll(m->client, NULL, NULL);

	if (n & EPOLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
		schedule_work(&m->wq);
	p9_poll_mux(m);

	return 0;
}
@@ -726,10 +719,10 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
	p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);

	spin_lock(&m->req_lock);
	/* Ignore cancelled request if message has been received
	 * before lock.
	/* Ignore cancelled request if status changed since the request was
	 * processed in p9_client_flush()
	*/
	if (req->status == REQ_STATUS_RCVD) {
	if (req->status != REQ_STATUS_SENT) {
		spin_unlock(&m->req_lock);
		return 0;
	}
Loading