From nobody Sun May 24 21:36:39 2026 Received: from e3i421.smtp2go.com (e3i421.smtp2go.com [158.120.85.165]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 529703603D3 for ; Thu, 21 May 2026 10:02:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.120.85.165 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779357772; cv=none; b=Otm9epTVRES/WyCY8FdivwJ2Mf7slvrrKYeWUtxkf1u7k1H8sthMJsHzcB4ba7fD4qEl59RCX43Dk/KFu0F43qzw25AwJfHbxcyfQQYaokVvKJIzb27XLpDvUqXLqZsjVMhR/UuVBnp99LWCUvHFnwfrNb1R7JkChyZ9ayB3W3A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779357772; c=relaxed/simple; bh=K5ODYb+lCZr9CsKAh8f2lBd2ovJulBoqmGCKQwOvMUw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=c0dYzKBAQcoAVFRVvRguNSTF5TAsqWy7w5ryv/4BTrhNSQrRD8FNCsy33F0eF3L1qCFxaKyzgIMPj0Jjued/uiaLosEMs2OOPEixHovkbsG/qvu7qcn1xuqG91Susx0bQNEOnBtnxOmgNCuuxOSN5WyAVspJUqLBYWPslLZYfrg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=triplefau.lt; spf=pass smtp.mailfrom=em510616.triplefau.lt; dkim=pass (2048-bit key) header.d=triplefau.lt header.i=@triplefau.lt header.b=MqT/azJZ; arc=none smtp.client-ip=158.120.85.165 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=triplefau.lt Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=em510616.triplefau.lt Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=triplefau.lt header.i=@triplefau.lt header.b="MqT/azJZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=triplefau.lt; i=@triplefau.lt; q=dns/txt; s=s510616; t=1779357767; h=from : subject : to : message-id : date; bh=gvhlhWo0fj/91Xw4zvBxPEpT76wIaP1E9xbcLqWvsE0=; b=MqT/azJZVlBCY5NSbmXZu36yRCScIkTk/KOwE00wjim4+jVEND24ieiPr4a/79ewHf3Vi 0NnuzX0BpG4JxE4SECN0lKH+wVEw8qkrGfGF0zv23KfMzehXasdE4yQW7dzZZhc9PJHEzD9 bNg75f0d9qDE72PAPsv9E8XOhpaMbp4vM5MENgFxVq+BGkn0e9tBdhxUZns1LcHr/jMzvlO NMr+hDb4+yJdPj6ixUdw8KSfmlmbhHCfqNJbMJ+ejNgrmHBiQkEucE3vvkLi8OTT1GTt76N XX5TSeusHZTDjOP5Sfi4/jUFLrytknnWeb7Kr8QUd3Yhd5xJs9KxOvKAOXEQ== Received: from [10.12.239.196] (helo=localhost) by smtpcorp.com with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.99.2) (envelope-from ) id 1wQ0Em-AIkwcC8nohd-IeXf; Thu, 21 May 2026 10:02:44 +0000 From: Remi Pommarel To: v9fs@lists.linux.dev Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Van Hensbergen , Latchesar Ionkov , Dominique Martinet , Christian Schoenebeck , Remi Pommarel Subject: [PATCH v7 1/4] 9p: Cache negative dentries for lookup performance Date: Thu, 21 May 2026 11:40:29 +0200 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Report-Abuse: Please forward a copy of this message, including all headers, to Feedback-ID: 510616m:510616apGKSTK:510616sVfXmlqY_y X-smtpcorp-track: 4GvCM8Hs64v0.i6u4P_h9qJyl.fZEUZASD7jd Content-Type: text/plain; charset="utf-8" Not caching negative dentries can result in poor performance for workloads that repeatedly look up non-existent paths. Each such lookup triggers a full 9P transaction with the server, adding unnecessary overhead. A typical example is source compilation, where multiple cc1 processes are spawned and repeatedly search for the same missing header files over and over again. This change enables caching of negative dentries, so that lookups for known non-existent paths do not require a full 9P transaction. The cached negative dentries are retained for a configurable duration (expressed in milliseconds), as specified by the ndentry_timeout field in struct v9fs_session_info. If set to -1, negative dentries are cached indefinitely. This optimization reduces lookup overhead and improves performance for workloads involving frequent access to non-existent paths. Signed-off-by: Remi Pommarel --- fs/9p/fid.c | 11 +++-- fs/9p/v9fs.c | 1 + fs/9p/v9fs.h | 5 ++ fs/9p/v9fs_vfs.h | 15 ++++++ fs/9p/vfs_dentry.c | 105 ++++++++++++++++++++++++++++++++++------ fs/9p/vfs_inode.c | 12 +++-- fs/9p/vfs_super.c | 1 + include/net/9p/client.h | 2 + 8 files changed, 128 insertions(+), 24 deletions(-) diff --git a/fs/9p/fid.c b/fs/9p/fid.c index f84412290a30..76242d450aa7 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -20,7 +20,9 @@ =20 static inline void __add_fid(struct dentry *dentry, struct p9_fid *fid) { - hlist_add_head(&fid->dlist, (struct hlist_head *)&dentry->d_fsdata); + struct v9fs_dentry *v9fs_dentry =3D to_v9fs_dentry(dentry); + + hlist_add_head(&fid->dlist, &v9fs_dentry->head); } =20 =20 @@ -112,6 +114,7 @@ void v9fs_open_fid_add(struct inode *inode, struct p9_f= id **pfid) =20 static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int= any) { + struct v9fs_dentry *v9fs_dentry =3D to_v9fs_dentry(dentry); struct p9_fid *fid, *ret; =20 p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p) uid %d any %d\n", @@ -119,11 +122,9 @@ static struct p9_fid *v9fs_fid_find(struct dentry *den= try, kuid_t uid, int any) any); ret =3D NULL; /* we'll recheck under lock if there's anything to look in */ - if (dentry->d_fsdata) { - struct hlist_head *h =3D (struct hlist_head *)&dentry->d_fsdata; - + if (!hlist_empty(&v9fs_dentry->head)) { spin_lock(&dentry->d_lock); - hlist_for_each_entry(fid, h, dlist) { + hlist_for_each_entry(fid, &v9fs_dentry->head, dlist) { if (any || uid_eq(fid->uid, uid)) { ret =3D fid; p9_fid_get(ret); diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index acda42499ca9..be83744b75b2 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -426,6 +426,7 @@ static void v9fs_apply_options(struct v9fs_session_info= *v9ses, v9ses->cache =3D ctx->session_opts.cache; v9ses->uid =3D ctx->session_opts.uid; v9ses->session_lock_timeout =3D ctx->session_opts.session_lock_timeout; + v9ses->ndentry_timeout_ms =3D ctx->session_opts.ndentry_timeout_ms; } =20 /** diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 6a12445d3858..e630c5111d74 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -91,6 +91,7 @@ enum p9_cache_bits { * @debug: debug level * @afid: authentication handle * @cache: cache mode of type &p9_cache_bits + * @ndentry_timeout: Negative dentry lookup cache retention time in ms * @cachetag: the tag of the cache associated with this session * @fscache: session cookie associated with FS-Cache * @uname: string user name to mount hierarchy as @@ -101,6 +102,7 @@ enum p9_cache_bits { * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarc= hy * @clnt: reference to 9P network client instantiated for this session * @slist: reference to list of registered 9p sessions + * @ndentry_timeout_ms: Negative dentry caching retention time * * This structure holds state for each session instance established during * a sys_mount() . @@ -116,6 +118,7 @@ struct v9fs_session_info { unsigned short debug; unsigned int afid; unsigned int cache; + unsigned int ndentry_timeout_ms; #ifdef CONFIG_9P_FSCACHE char *cachetag; struct fscache_volume *fscache; @@ -133,6 +136,8 @@ struct v9fs_session_info { long session_lock_timeout; /* retry interval for blocking locks */ }; =20 +#define NDENTRY_TIMEOUT_NEVER (-1U) + /* cache_validity flags */ #define V9FS_INO_INVALID_ATTR 0x01 =20 diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 34c115d7c250..1856d91f8703 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -28,6 +28,19 @@ /* flags for v9fs_stat2inode() & v9fs_stat2inode_dotl() */ #define V9FS_STAT2INODE_KEEP_ISIZE 1 =20 +/** + * struct v9fs_dentry - v9fs specific dentry data + * @head: List of fid associated with this dentry + * @expire_time: Lookup cache expiration time for negative dentries + * @rcu: used by kfree_rcu to schedule clean up job + */ +struct v9fs_dentry { + struct hlist_head head; + u64 expire_time; + struct rcu_head rcu; +}; +#define to_v9fs_dentry(d) ((struct v9fs_dentry *)((d)->d_fsdata)) + extern struct file_system_type v9fs_fs_type; extern const struct address_space_operations v9fs_addr_operations; extern const struct file_operations v9fs_file_operations; @@ -35,6 +48,8 @@ extern const struct file_operations v9fs_file_operations_= dotl; extern const struct file_operations v9fs_dir_operations; extern const struct file_operations v9fs_dir_operations_dotl; extern const struct dentry_operations v9fs_dentry_operations; +extern void v9fs_ndentry_refresh_timeout(struct dentry *dentry); +extern void v9fs_dentry_fid_remove(struct dentry *dentry); extern const struct dentry_operations v9fs_cached_dentry_operations; extern struct kmem_cache *v9fs_inode_cache; =20 diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index c5bf74d547e8..e549e222602e 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -23,6 +23,46 @@ #include "v9fs_vfs.h" #include "fid.h" =20 +/** + * v9fs_ndentry_is_expired - Check if negative dentry lookup has expired + * + * This should be called to know if a negative dentry should be removed fr= om + * cache. + * + * @dentry: dentry in question + * + */ +static bool v9fs_ndentry_is_expired(struct dentry const *dentry) +{ + struct v9fs_session_info *v9ses =3D v9fs_dentry2v9ses(dentry); + struct v9fs_dentry *v9fs_dentry =3D to_v9fs_dentry(dentry); + + if (v9ses->ndentry_timeout_ms =3D=3D NDENTRY_TIMEOUT_NEVER) + return false; + + return time_before_eq64(v9fs_dentry->expire_time, get_jiffies_64()); +} + +/** + * v9fs_ndentry_refresh_timeout - Refresh negative dentry lookup cache tim= eout + * + * This should be called when a look up yields a negative entry. + * + * @dentry: dentry in question + * + */ +void v9fs_ndentry_refresh_timeout(struct dentry *dentry) +{ + struct v9fs_session_info *v9ses =3D v9fs_dentry2v9ses(dentry); + struct v9fs_dentry *v9fs_dentry =3D to_v9fs_dentry(dentry); + + if (v9ses->ndentry_timeout_ms =3D=3D NDENTRY_TIMEOUT_NEVER) + return; + + v9fs_dentry->expire_time =3D get_jiffies_64() + + msecs_to_jiffies(v9ses->ndentry_timeout_ms); +} + /** * v9fs_cached_dentry_delete - called when dentry refcount equals 0 * @dentry: dentry in question @@ -33,20 +73,15 @@ static int v9fs_cached_dentry_delete(const struct dentr= y *dentry) p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n", dentry, dentry); =20 - /* Don't cache negative dentries */ - if (d_really_is_negative(dentry)) - return 1; - return 0; -} + if (!d_really_is_negative(dentry)) + return 0; =20 -/** - * v9fs_dentry_release - called when dentry is going to be freed - * @dentry: dentry that is being release - * - */ + return v9fs_ndentry_is_expired(dentry); +} =20 -static void v9fs_dentry_release(struct dentry *dentry) +static void __v9fs_dentry_fid_remove(struct dentry *dentry) { + struct v9fs_dentry *v9fs_dentry =3D to_v9fs_dentry(dentry); struct hlist_node *p, *n; struct hlist_head head; =20 @@ -54,13 +89,54 @@ static void v9fs_dentry_release(struct dentry *dentry) dentry, dentry); =20 spin_lock(&dentry->d_lock); - hlist_move_list((struct hlist_head *)&dentry->d_fsdata, &head); + hlist_move_list(&v9fs_dentry->head, &head); spin_unlock(&dentry->d_lock); =20 hlist_for_each_safe(p, n, &head) p9_fid_put(hlist_entry(p, struct p9_fid, dlist)); } =20 +/** + * v9fs_dentry_fid_remove - Release all dentry's fids + * @dentry: dentry in question + * + */ +void v9fs_dentry_fid_remove(struct dentry *dentry) +{ + __v9fs_dentry_fid_remove(dentry); +} + +/** + * v9fs_dentry_init - Initialize v9fs dentry data + * @dentry: dentry in question + * + */ +static int v9fs_dentry_init(struct dentry *dentry) +{ + struct v9fs_dentry *v9fs_dentry =3D kzalloc(sizeof(*v9fs_dentry), + GFP_KERNEL); + + if (!v9fs_dentry) + return -ENOMEM; + + INIT_HLIST_HEAD(&v9fs_dentry->head); + dentry->d_fsdata =3D (void *)v9fs_dentry; + return 0; +} + +/** + * v9fs_dentry_release - called when dentry is going to be freed + * @dentry: dentry that is being released + * + */ +static void v9fs_dentry_release(struct dentry *dentry) +{ + struct v9fs_dentry *v9fs_dentry =3D to_v9fs_dentry(dentry); + + __v9fs_dentry_fid_remove(dentry); + kfree_rcu(v9fs_dentry, rcu); +} + static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int fl= ags) { struct p9_fid *fid; @@ -72,7 +148,7 @@ static int __v9fs_lookup_revalidate(struct dentry *dentr= y, unsigned int flags) =20 inode =3D d_inode(dentry); if (!inode) - goto out_valid; + return !v9fs_ndentry_is_expired(dentry); =20 v9inode =3D V9FS_I(inode); if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { @@ -112,7 +188,6 @@ static int __v9fs_lookup_revalidate(struct dentry *dent= ry, unsigned int flags) return retval; } } -out_valid: p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) is valid\n", dentry, dentry); return 1; } @@ -139,12 +214,14 @@ const struct dentry_operations v9fs_cached_dentry_ope= rations =3D { .d_revalidate =3D v9fs_lookup_revalidate, .d_weak_revalidate =3D __v9fs_lookup_revalidate, .d_delete =3D v9fs_cached_dentry_delete, + .d_init =3D v9fs_dentry_init, .d_release =3D v9fs_dentry_release, .d_unalias_trylock =3D v9fs_dentry_unalias_trylock, .d_unalias_unlock =3D v9fs_dentry_unalias_unlock, }; =20 const struct dentry_operations v9fs_dentry_operations =3D { + .d_init =3D v9fs_dentry_init, .d_release =3D v9fs_dentry_release, .d_unalias_trylock =3D v9fs_dentry_unalias_trylock, .d_unalias_unlock =3D v9fs_dentry_unalias_unlock, diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index f468acb8ee7d..5cbbebafc24e 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -549,7 +549,7 @@ static int v9fs_remove(struct inode *dir, struct dentry= *dentry, int flags) =20 /* invalidate all fids associated with dentry */ /* NOTE: This will not include open fids */ - dentry->d_op->d_release(dentry); + v9fs_dentry_fid_remove(dentry); } return retval; } @@ -732,14 +732,16 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, str= uct dentry *dentry, name =3D dentry->d_name.name; fid =3D p9_client_walk(dfid, 1, &name, 1); p9_fid_put(dfid); - if (fid =3D=3D ERR_PTR(-ENOENT)) + if (fid =3D=3D ERR_PTR(-ENOENT)) { inode =3D NULL; - else if (IS_ERR(fid)) + v9fs_ndentry_refresh_timeout(dentry); + } else if (IS_ERR(fid)) { inode =3D ERR_CAST(fid); - else if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) + } else if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) { inode =3D v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); - else + } else { inode =3D v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); + } /* * If we had a rename on the server and a parallel lookup * for the new name, then make sure we instantiate with diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 431f24938a1d..94d6b02c221b 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -330,6 +330,7 @@ static int v9fs_init_fs_context(struct fs_context *fc) ctx->session_opts.uid =3D INVALID_UID; ctx->session_opts.dfltuid =3D V9FS_DEFUID; ctx->session_opts.dfltgid =3D V9FS_DEFGID; + ctx->session_opts.ndentry_timeout_ms =3D 0; =20 /* initialize client options */ ctx->client_opts.proto_version =3D p9_proto_2000L; diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 838a94218b59..55c6cb54bd25 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -192,6 +192,7 @@ struct p9_rdma_opts { * @dfltgid: default numeric groupid to mount hierarchy as * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarc= hy * @session_lock_timeout: retry interval for blocking locks + * @ndentry_timeout_ms: Negative dentry lookup cache retention time in ms * * This strucure holds options which are parsed and will be transferred * to the v9fs_session_info structure when mounted, and therefore largely @@ -203,6 +204,7 @@ struct p9_session_opts { unsigned short debug; unsigned int afid; unsigned int cache; + unsigned int ndentry_timeout_ms; #ifdef CONFIG_9P_FSCACHE char *cachetag; #endif --=20 2.52.0 From nobody Sun May 24 21:36:39 2026 Received: from e3i421.smtp2go.com (e3i421.smtp2go.com [158.120.85.165]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C38F937F723 for ; Thu, 21 May 2026 10:02:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.120.85.165 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779357777; cv=none; b=dKY93azk61CUS4hFxDC+Uv5qpxEpkp1Y0NEm2LyALMmuR6rEqeaBxUGOkNKPXmfjNYxwWHGOMIH7rpstpojfI6M36+2cToOjfc9FgV+MfXb33CysxRa4fmrnqajQpITS1XdLkSI6pJjD2Pqkl/qLztX8yoMW3+COmN1fvSQclP0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779357777; c=relaxed/simple; bh=AAN255HdM3uZ4+It0uI52zgspk3PlnjRuFJ5Vkbr2uQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YuIw/5lQQkXwrG0ofdvwc+GzMhwp8ccn0NCudyTdY9Rkauivw/s/Ket2kcFCWhk3iWIchw7bYCy3XFP/QqMHbes39FNznAnv44P0W2FbqBADstThF+X6wwIyf1biD5CP+agrWm5VUS/c5w3mt081wivK3tVXMSQXs0oletB8Eo8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=triplefau.lt; spf=pass smtp.mailfrom=em510616.triplefau.lt; dkim=pass (2048-bit key) header.d=triplefau.lt header.i=@triplefau.lt header.b=Drw/s1+G; arc=none smtp.client-ip=158.120.85.165 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=triplefau.lt Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=em510616.triplefau.lt Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=triplefau.lt header.i=@triplefau.lt header.b="Drw/s1+G" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=triplefau.lt; i=@triplefau.lt; q=dns/txt; s=s510616; t=1779357759; h=from : subject : to : message-id : date; bh=Hc1ZS8wBS8cUwmC29S6NYs+RegvTzxi9h3if/SxiDqk=; b=Drw/s1+G0fRiC/sSrVQo4eLllR1T0vLO8fFI7PRz0i2D2MTzjI0zkmjvjzzBZkbYCEfl+ BpKVd7gKIKcQvhx/Ger+eBC8eOtHnbvFLrqHn61KQhnPpJh4M4rFQU+TYwDzxOVH701R1r2 G6Zoo90MxiLdceelSX6z6qta8yUExqT2+5wgzXP/yFAe2cnjjogH19+u5w6Hkl2DrUqc8Vv 0cQGYkisaOqe+hzTWel12q+l8/Qcu2kFIjNUvMfaU9kfWmC1asa7sH4mUBFzYljZ7xiwknv VR3ggzd2Dpb1r9EOwLY4A8YKqyTUZ6hgaatf67o5SEErxL3kDJKjIVjEv5Xg== Received: from [10.12.239.196] (helo=localhost) by smtpcorp.com with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.99.2) (envelope-from ) id 1wQ0Eo-4o5NDgrsjmH-pCbW; Thu, 21 May 2026 10:02:46 +0000 From: Remi Pommarel To: v9fs@lists.linux.dev Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Van Hensbergen , Latchesar Ionkov , Dominique Martinet , Christian Schoenebeck , Remi Pommarel Subject: [PATCH v7 2/4] 9p: Add mount option for negative dentry cache retention Date: Thu, 21 May 2026 11:40:30 +0200 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Report-Abuse: Please forward a copy of this message, including all headers, to Feedback-ID: 510616m:510616apGKSTK:510616s3Pls6ELvV X-smtpcorp-track: ql7Z7eXaHoYc.7pBvTeDJhz0W.lBz_rAbkAlA Content-Type: text/plain; charset="utf-8" Introduce a new mount option, negtimeout, for v9fs that allows users to specify how long negative dentries are retained in the cache. The retention time can be set in milliseconds (e.g. negtimeout=3D10000 for a 10secs retention time) or a negative value (e.g. negtimeout=3D-1) to keep negative entries until the buffer cache management removes them. For consistency reasons, this option should only be used in exclusive or read-only mount scenarios, aligning with the cache=3Dloose usage. Signed-off-by: Remi Pommarel --- Documentation/filesystems/9p.rst | 5 +++++ fs/9p/v9fs.c | 16 +++++++++++++++- fs/9p/v9fs.h | 23 +++++++++++++---------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/Documentation/filesystems/9p.rst b/Documentation/filesystems/9= p.rst index be3504ca034a..b014c7aabba4 100644 --- a/Documentation/filesystems/9p.rst +++ b/Documentation/filesystems/9p.rst @@ -238,6 +238,11 @@ Options cachetag cache tag to use the specified persistent cache. cache tags for existing cache sessions can be listed at /sys/fs/9p/caches. (applies only to cache=3Dfscache) + + negtimeout the duration (in milliseconds) that negative dentries (pat= hs + that do not actually exist) are retained in the cache. If + set to a negative value, those entries are kept indefinite= ly + until evicted by the buffer cache management system =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D =20 Behavior diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index be83744b75b2..3e758b66fefa 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -39,7 +39,7 @@ enum { * source if we rejected it as EINVAL */ Opt_source, /* Options that take integer arguments */ - Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid, + Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid, Opt_negtimeout, /* String options */ Opt_uname, Opt_remotename, Opt_cache, Opt_cachetag, /* Options that take no arguments */ @@ -93,6 +93,7 @@ const struct fs_parameter_spec v9fs_param_spec[] =3D { fsparam_string ("access", Opt_access), fsparam_flag ("posixacl", Opt_posixacl), fsparam_u32 ("locktimeout", Opt_locktimeout), + fsparam_s32 ("negtimeout", Opt_negtimeout), =20 /* client options */ fsparam_u32 ("msize", Opt_msize), @@ -159,6 +160,9 @@ int v9fs_show_options(struct seq_file *m, struct dentry= *root) from_kgid_munged(&init_user_ns, v9ses->dfltgid)); if (v9ses->afid !=3D ~0) seq_printf(m, ",afid=3D%u", v9ses->afid); + if (v9ses->flags & V9FS_NDENTRY_TIMEOUT_SET) + seq_printf(m, ",negtimeout=3D%d", + (int)v9ses->ndentry_timeout_ms); if (strcmp(v9ses->uname, V9FS_DEFUSER) !=3D 0) seq_printf(m, ",uname=3D%s", v9ses->uname); if (strcmp(v9ses->aname, V9FS_DEFANAME) !=3D 0) @@ -337,6 +341,16 @@ int v9fs_parse_param(struct fs_context *fc, struct fs_= parameter *param) session_opts->session_lock_timeout =3D (long)result.uint_32 * HZ; break; =20 + case Opt_negtimeout: + session_opts->flags |=3D V9FS_NDENTRY_TIMEOUT_SET; + if (result.int_32 < 0) { + session_opts->ndentry_timeout_ms =3D + NDENTRY_TIMEOUT_NEVER; + } else { + session_opts->ndentry_timeout_ms =3D result.int_32; + } + break; + /* Options for client */ case Opt_msize: if (result.uint_32 < 4096) { diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index e630c5111d74..a462bcbfc7da 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -24,6 +24,8 @@ * @V9FS_ACCESS_ANY: use a single attach for all users * @V9FS_ACCESS_MASK: bit mask of different ACCESS options * @V9FS_POSIX_ACL: POSIX ACLs are enforced + * @V9FS_NDENTRY_TIMEOUT_SET: Has negative dentry timeout retention time b= een + * overridden by negtimeout mount option * * Session flags reflect options selected by users at mount time */ @@ -34,16 +36,17 @@ #define V9FS_ACL_MASK V9FS_POSIX_ACL =20 enum p9_session_flags { - V9FS_PROTO_2000U =3D 0x01, - V9FS_PROTO_2000L =3D 0x02, - V9FS_ACCESS_SINGLE =3D 0x04, - V9FS_ACCESS_USER =3D 0x08, - V9FS_ACCESS_CLIENT =3D 0x10, - V9FS_POSIX_ACL =3D 0x20, - V9FS_NO_XATTR =3D 0x40, - V9FS_IGNORE_QV =3D 0x80, /* ignore qid.version for cache hints */ - V9FS_DIRECT_IO =3D 0x100, - V9FS_SYNC =3D 0x200 + V9FS_PROTO_2000U =3D 0x01, + V9FS_PROTO_2000L =3D 0x02, + V9FS_ACCESS_SINGLE =3D 0x04, + V9FS_ACCESS_USER =3D 0x08, + V9FS_ACCESS_CLIENT =3D 0x10, + V9FS_POSIX_ACL =3D 0x20, + V9FS_NO_XATTR =3D 0x40, + V9FS_IGNORE_QV =3D 0x80, /* ignore qid.version for cache hints = */ + V9FS_DIRECT_IO =3D 0x100, + V9FS_SYNC =3D 0x200, + V9FS_NDENTRY_TIMEOUT_SET =3D 0x400, }; =20 /** --=20 2.52.0 From nobody Sun May 24 21:36:39 2026 Received: from e3i421.smtp2go.com (e3i421.smtp2go.com [158.120.85.165]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F2DA737FF45 for ; Thu, 21 May 2026 10:02:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.120.85.165 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779357781; cv=none; b=GpUwlIgqnuH7Mx+wFw0Ld9wwG/OTqJOuigH9egBSWnAcsBdp8Sgu9avBv60jje9S/uoCBfWIfcLConool4a3jsGXzV5G2pvWm96EuBiHcjjQhCHvcvZ1tqbJtRJ+lPOY5EwId64U/qKOfO6HyAeigAhi/0eQspy2Wmo62no8/Po= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779357781; c=relaxed/simple; bh=vodvvcswZRlbDFXfFUiY4r5AdgWfA3xto6hrwuObiOo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JarmOe5beNcvkQnv/jlbDson08zpt/6APdPVU1dOIHLjvtj3FuK1JleJqezubY9taY0dudi1icXrzx4DzxXtj/kmFIj5SBGul6ngNDga8ihdiroLUFoyoDl9JFzjwrwto2UX6p2/nJQKOk62Fu7zftZ5pS6kHP7OxZAeFctq+3I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=triplefau.lt; spf=pass smtp.mailfrom=em510616.triplefau.lt; dkim=pass (2048-bit key) header.d=triplefau.lt header.i=@triplefau.lt header.b=UHwLN+Ew; arc=none smtp.client-ip=158.120.85.165 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=triplefau.lt Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=em510616.triplefau.lt Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=triplefau.lt header.i=@triplefau.lt header.b="UHwLN+Ew" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=triplefau.lt; i=@triplefau.lt; q=dns/txt; s=s510616; t=1779357778; h=from : subject : to : message-id : date; bh=uCNwpibAseSDNQ68UeAV3DI4drw37VIBam9jpljEa7M=; b=UHwLN+Ewik/A1YMdBdSjUYWdhkVtyaUyXIpY7oj0e+bmNeirOzz3p3zSnDc1kPQbKqa6G eFPyAO1uOR/65NysQR0tMbFhsdRiegbw8+J/JMON55KCjan45j7rnvL08RNunBNP4qiwEGk UlG6aemcIzoC4cPc2+k6NCxAGs1ib4i6zYodZRQ70kkIv/h7o9QhkyJNlqUFhcWR/Uf0ZBR xd/74sKMFsPunN2rIXuoN4/pKv3D5JJ8QkD/KFTxO1ubO3sm5ayEEj5Mks1csTXPFu8zWYF QEUIgUJ1LBhEqwcZpzyosKSw/2XRy/ecDDB2M5gmIsMooBeDfa6xCQZKJhPg== Received: from [10.12.239.196] (helo=localhost) by smtpcorp.com with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.99.2-S2G) (envelope-from ) id 1wQ0Eq-FnQW0hPzify-nxIq; Thu, 21 May 2026 10:02:49 +0000 From: Remi Pommarel To: v9fs@lists.linux.dev Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Van Hensbergen , Latchesar Ionkov , Dominique Martinet , Christian Schoenebeck , Remi Pommarel Subject: [PATCH v7 3/4] 9p: Set default negative dentry retention time for cache=loose Date: Thu, 21 May 2026 11:40:31 +0200 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Report-Abuse: Please forward a copy of this message, including all headers, to Feedback-ID: 510616m:510616apGKSTK:510616skA0ZlBRBB X-smtpcorp-track: OZDl9zx4SxsB.ZKKdnJpDJ65-.MWYsfQN7iJ8 Content-Type: text/plain; charset="utf-8" For cache=3Dloose mounts, set the default negative dentry cache retention time to 24 hours. Signed-off-by: Remi Pommarel --- fs/9p/v9fs.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 3e758b66fefa..274c5157135d 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -24,6 +24,9 @@ #include "v9fs_vfs.h" #include "cache.h" =20 +/* cache=3Dloose default negative dentry retention time is 24hours */ +#define CACHE_LOOSE_NDENTRY_TIMEOUT_DEFAULT (24 * 60 * 60 * 1000) + static DEFINE_SPINLOCK(v9fs_sessionlist_lock); static LIST_HEAD(v9fs_sessionlist); struct kmem_cache *v9fs_inode_cache; @@ -441,6 +444,13 @@ static void v9fs_apply_options(struct v9fs_session_inf= o *v9ses, v9ses->uid =3D ctx->session_opts.uid; v9ses->session_lock_timeout =3D ctx->session_opts.session_lock_timeout; v9ses->ndentry_timeout_ms =3D ctx->session_opts.ndentry_timeout_ms; + + /* If negative dentry timeout has not been overridden set default for + * cache=3Dloose + */ + if (!(v9ses->flags & V9FS_NDENTRY_TIMEOUT_SET) && + (v9ses->cache & CACHE_LOOSE)) + v9ses->ndentry_timeout_ms =3D CACHE_LOOSE_NDENTRY_TIMEOUT_DEFAULT; } =20 /** --=20 2.52.0 From nobody Sun May 24 21:36:39 2026 Received: from e3i421.smtp2go.com (e3i421.smtp2go.com [158.120.85.165]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C3B5E3803CB for ; Thu, 21 May 2026 10:03:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=158.120.85.165 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779357783; cv=none; b=CRpkHnTnmycjuk/2s2UeT5ADsofHMML/w2HV2ZgMZfx0JQY77uhsX4MbMGXzA660WldwIslXeZukyWCdk+C3Rv3V/SAcrJGbyON5W9hUCyXVx5wsBGhORgULkuIjUzxgqbyGn/+et+BW0xs5mDr/VKeLc+ITucVMnJiu8O0abjk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779357783; c=relaxed/simple; bh=I1588I/1fYv3RU4qRZ8PpNJ1gtZ11AAIoQ3cZ95uqcg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NLeJgc0p8DO0cb5mgwM0RKGoHjJYA6TEUgVjFjtTWLvgtQ6S9TLdbbQWUe2sf0xV7Vd112m+1DEqbASsha9bQ20wVCEjXzMqmv5qaeQInnEVU7WUJtDY+P/44R/OcN0sKVV3p+h/zzzuM7I6T7ANjhKNSzUTOqsGfg3Is/lOUoo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=triplefau.lt; spf=pass smtp.mailfrom=em510616.triplefau.lt; dkim=pass (2048-bit key) header.d=triplefau.lt header.i=@triplefau.lt header.b=mtdF9eVF; arc=none smtp.client-ip=158.120.85.165 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=triplefau.lt Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=em510616.triplefau.lt Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=triplefau.lt header.i=@triplefau.lt header.b="mtdF9eVF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=triplefau.lt; i=@triplefau.lt; q=dns/txt; s=s510616; t=1779357777; h=from : subject : to : message-id : date; bh=T72YYyUlEQJZdzLS62UItGU7H4qC2PfTWsccTrhKodE=; b=mtdF9eVF5UkRDZZyZRcvxmbDBXTO0mYFWmZT285qPozUJV9Bd/maRUi9P2ZPCVhyjbXvx pW0gb8yEkSUN502mk/IMxC/mFVIPzbWTy3sP+0V9PR22BlBsyseEXH90n4AGsUMX9YqsKQF zjDff04yt8IxEgpEV0+2BKEGAeWoi3xPQ3RIwjeTOwaZ/UbpCOV1G1321B42BSw2cYAzjo9 T8Ilz7L0rImTZ1ZLCx9lEGkE/BjvHvF15n7oVKtoP27DyDIrzi/5u3IWmXqwqojv78w0pcA H5pz4/i3n/AtngWo0+BiqdypxMu2TW1Q479XDrNxmiynjiJhfIobhOTaP66g== Received: from [10.12.239.196] (helo=localhost) by smtpcorp.com with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.99.2) (envelope-from ) id 1wQ0Et-4o5NDgrlHTS-n0aL; Thu, 21 May 2026 10:02:51 +0000 From: Remi Pommarel To: v9fs@lists.linux.dev Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Van Hensbergen , Latchesar Ionkov , Dominique Martinet , Christian Schoenebeck , Remi Pommarel Subject: [PATCH v7 4/4] 9p: Enable symlink caching in page cache Date: Thu, 21 May 2026 11:40:32 +0200 Message-ID: <982462d17c0c0d2856763266a25eb04d080c1dbb.1779355927.git.repk@triplefau.lt> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Report-Abuse: Please forward a copy of this message, including all headers, to Feedback-ID: 510616m:510616apGKSTK:510616swVnw_WQeF X-smtpcorp-track: kbaKCSOsOwOD.BSe1G_Py7TJ4.tJKo2Q6WKqI Content-Type: text/plain; charset="utf-8" Currently, when cache=3Dloose is enabled, file reads are cached in the page cache, but symlink reads are not. This patch allows the results of p9_client_readlink() to be stored in the page cache, eliminating the need for repeated 9P transactions on subsequent symlink accesses. This change improves performance for workloads that involve frequent symlink resolution. Signed-off-by: Remi Pommarel --- fs/9p/vfs_addr.c | 38 ++++++++++++++++++++++++++--- fs/9p/vfs_inode.c | 6 +++-- fs/9p/vfs_inode_dotl.c | 54 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 88 insertions(+), 10 deletions(-) diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index c21d33830f5f..1ac0b3dcc077 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -70,11 +70,34 @@ static void v9fs_issue_read(struct netfs_io_subrequest = *subreq) { struct netfs_io_request *rreq =3D subreq->rreq; struct p9_fid *fid =3D rreq->netfs_priv; + char *target; unsigned long long pos =3D subreq->start + subreq->transferred; - int total, err; - - total =3D p9_client_read(fid, pos, &subreq->io_iter, &err); + int total =3D 0, err, len, n; + + if (S_ISLNK(rreq->inode->i_mode)) { + /* p9_client_readlink() must not be called for legacy protocols + * 9p2000 or 9p2000.u. + */ + BUG_ON(!p9_is_proto_dotl(fid->clnt)); + if (WARN_ON_ONCE(pos)) { + /* reading a link at a non null offset should + * not happen + */ + err =3D -EIO; + goto fill_subreq; + } + err =3D p9_client_readlink(fid, &target); + if (err !=3D 0) + goto fill_subreq; + len =3D strlen(target); + n =3D copy_to_iter(target, len, &subreq->io_iter); + kfree(target); + total =3D n; + } else { + total =3D p9_client_read(fid, pos, &subreq->io_iter, &err); + } =20 +fill_subreq: /* if we just extended the file size, any portion not in * cache won't be on server and is zeroes */ if (subreq->rreq->origin !=3D NETFS_UNBUFFERED_READ && @@ -99,6 +122,7 @@ static void v9fs_issue_read(struct netfs_io_subrequest *= subreq) static int v9fs_init_request(struct netfs_io_request *rreq, struct file *f= ile) { struct p9_fid *fid; + struct dentry *dentry; bool writing =3D (rreq->origin =3D=3D NETFS_READ_FOR_WRITE || rreq->origin =3D=3D NETFS_WRITETHROUGH || rreq->origin =3D=3D NETFS_UNBUFFERED_WRITE || @@ -115,6 +139,14 @@ static int v9fs_init_request(struct netfs_io_request *= rreq, struct file *file) if (!fid) goto no_fid; p9_fid_get(fid); + } else if (S_ISLNK(rreq->inode->i_mode)) { + dentry =3D d_find_any_alias(rreq->inode); + if (!dentry) + goto no_fid; + fid =3D v9fs_fid_lookup(dentry); + dput(dentry); + if (IS_ERR(fid)) + goto no_fid; } else { fid =3D v9fs_fid_find_inode(rreq->inode, writing, INVALID_UID, true); if (!fid) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 5cbbebafc24e..d29df0b2e89c 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -302,10 +302,12 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses, goto error; } =20 - if (v9fs_proto_dotl(v9ses)) + if (v9fs_proto_dotl(v9ses)) { inode->i_op =3D &v9fs_symlink_inode_operations_dotl; - else + inode_nohighmem(inode); + } else { inode->i_op =3D &v9fs_symlink_inode_operations; + } =20 break; case S_IFDIR: diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 141fb54db65d..3ca79f225709 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -690,9 +690,11 @@ v9fs_vfs_symlink_dotl(struct mnt_idmap *idmap, struct = inode *dir, int err; kgid_t gid; const unsigned char *name; + struct v9fs_session_info *v9ses; struct p9_qid qid; struct p9_fid *dfid; struct p9_fid *fid =3D NULL; + struct inode *inode; =20 name =3D dentry->d_name.name; p9_debug(P9_DEBUG_VFS, "%llu,%s,%s\n", dir->i_ino, name, symname); @@ -716,6 +718,26 @@ v9fs_vfs_symlink_dotl(struct mnt_idmap *idmap, struct = inode *dir, =20 v9fs_invalidate_inode_attr(dir); =20 + /* instantiate inode and assign the unopened fid to the dentry */ + fid =3D p9_client_walk(dfid, 1, &name, 1); + if (IS_ERR(fid)) { + err =3D PTR_ERR(fid); + p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", + err); + goto error; + } + + v9ses =3D v9fs_inode2v9ses(dir); + inode =3D v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); + if (IS_ERR(inode)) { + err =3D PTR_ERR(inode); + p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", + err); + goto error; + } + v9fs_fid_add(dentry, &fid); + d_instantiate(dentry, inode); + err =3D 0; error: p9_fid_put(fid); p9_fid_put(dfid); @@ -857,16 +879,18 @@ v9fs_vfs_mknod_dotl(struct mnt_idmap *idmap, struct i= node *dir, } =20 /** - * v9fs_vfs_get_link_dotl - follow a symlink path + * v9fs_vfs_get_link_nocache_dotl - Resolve a symlink directly. + * + * To be used when symlink caching is not enabled. + * * @dentry: dentry for symlink * @inode: inode for symlink * @done: destructor for return value */ - static const char * -v9fs_vfs_get_link_dotl(struct dentry *dentry, - struct inode *inode, - struct delayed_call *done) +v9fs_vfs_get_link_nocache_dotl(struct dentry *dentry, + struct inode *inode, + struct delayed_call *done) { struct p9_fid *fid; char *target; @@ -888,6 +912,26 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry, return target; } =20 +/** + * v9fs_vfs_get_link_dotl - follow a symlink path + * @dentry: dentry for symlink + * @inode: inode for symlink + * @done: destructor for return value + */ +static const char * +v9fs_vfs_get_link_dotl(struct dentry *dentry, + struct inode *inode, + struct delayed_call *done) +{ + struct v9fs_session_info *v9ses; + + v9ses =3D v9fs_inode2v9ses(inode); + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) + return page_get_link(dentry, inode, done); + + return v9fs_vfs_get_link_nocache_dotl(dentry, inode, done); +} + int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) { struct p9_stat_dotl *st; --=20 2.52.0