Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2229731/?format=api
{ "id": 2229731, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2229731/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260428160804.281745-11-sprasad@microsoft.com/", "project": { "id": 12, "url": "http://patchwork.ozlabs.org/api/1.1/projects/12/?format=api", "name": "Linux CIFS Client", "link_name": "linux-cifs-client", "list_id": "linux-cifs.vger.kernel.org", "list_email": "linux-cifs@vger.kernel.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260428160804.281745-11-sprasad@microsoft.com>", "date": "2026-04-28T16:07:56", "name": "[v3,11/19] cifs: in place changes to cached_dirents when dir lease is held", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "6ff9088d525e4debcc3c481937bd0e27ee5cd46f", "submitter": { "id": 79368, "url": "http://patchwork.ozlabs.org/api/1.1/people/79368/?format=api", "name": "Shyam Prasad N", "email": "nspmangalore@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260428160804.281745-11-sprasad@microsoft.com/mbox/", "series": [ { "id": 501896, "url": "http://patchwork.ozlabs.org/api/1.1/series/501896/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/list/?series=501896", "date": "2026-04-28T16:07:57", "name": "[v3,01/19] cifs: change_conf needs to be called for session setup", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/501896/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2229731/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2229731/checks/", "tags": {}, "headers": { "Return-Path": "\n <linux-cifs+bounces-11247-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-cifs@vger.kernel.org" ], "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=Ln/BoTA4;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-cifs+bounces-11247-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=\"Ln/BoTA4\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.214.170", "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=gmail.com" ], "Received": [ "from tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g4mNf1rPVz1xrS\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 02:39:14 +1000 (AEST)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id 1B5813195117\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 16:14:39 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id B3C1544D022;\n\tTue, 28 Apr 2026 16:08:32 +0000 (UTC)", "from mail-pl1-f170.google.com (mail-pl1-f170.google.com\n [209.85.214.170])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 9999544BCB6\n\tfor <linux-cifs@vger.kernel.org>; Tue, 28 Apr 2026 16:08:30 +0000 (UTC)", "by mail-pl1-f170.google.com with SMTP id\n d9443c01a7336-2b23fcf90b2so110901735ad.3\n for <linux-cifs@vger.kernel.org>;\n Tue, 28 Apr 2026 09:08:30 -0700 (PDT)", "from sprasad-dev1.corp.microsoft.com ([167.220.110.216])\n by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2b97ac7894csm30864465ad.50.2026.04.28.09.08.28\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 28 Apr 2026 09:08:29 -0700 (PDT)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1777392512; cv=none;\n b=RvxZFe0vtS94WL+qcWpv2tPdzFb2SkW9eSNen5/vb0a11yBijwKD76OEjvVVBEQ4469WYpBLipBOOLJDTGFqAaO6V+ZO2Ffnr3TnAmSR5eFZyAZ8WFG3TQH2Oni99RHR6YtTgJXc5QixqgDLLmGfwsUbUWIpbIAMqbaGwIjWKkY=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1777392512; c=relaxed/simple;\n\tbh=laxYPRxQNROn/mCB1U8uJ/z9GQXx1ybMlhRi45bFu9w=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=MhS6OXluhS+0Lw1pSks9dpqmtkVnBMi91Hn7UEfaYJhjDPrscJhAMDkMGJA/AoEanD1RgJd+bAGqSjWWo5J9RUG3ZeXAewcuSwH5dkMg0dzpif8oLr8xn2FB1xWk/Vym4HClIaLmWqKze9bdWYy0zJBFjgMkjigpc2BNdEkWF28=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com;\n spf=pass smtp.mailfrom=gmail.com;\n dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=Ln/BoTA4; arc=none smtp.client-ip=209.85.214.170", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1777392509; x=1777997309;\n darn=vger.kernel.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=UhpjoDjQGZevd2W9AU4bA1KVcZ73s6bijGKBV20qyws=;\n b=Ln/BoTA4OpepPSTCn0hS7FAe1CcWBSWBiO+jGTTq0AtdvGv/3v2/hcXGsxCS+skhdD\n WNsJKLDtbPXFQVbkT/hqrB1sRv5oGcx0rrQjRuTpeKwiYEE2claiWqKYU3WTRAmd3H1u\n G2hxAXalE2Re2+xBqE+JbVZMZX4I+He8KghiwbGUqA0RLCN2tA+2lloh+cpHi7+QVO2n\n 8BleHQc8RDoXQRsQHEJfJ1rywQKPsV8ofR3QOX0biL+NUA1QnBdTQA1eTNLS6+qJCdO7\n OnpZtsPfe6LjTxLvKHFnVw2N2i9OatwlL7CKwUClME4UPq6zcFvu1jLfhgt7QgoxwIgD\n 3eDA==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777392509; x=1777997309;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=UhpjoDjQGZevd2W9AU4bA1KVcZ73s6bijGKBV20qyws=;\n b=Fhsr/DsLjxU21bllLwFbWMQ5OEIm8c1vercAeH9gcqTZJqLc4lTcw92hcJRbHWr8qx\n 3UtmEmqBOoWLrZ2PdxgkbLRSKeo/khSfDG8kfnGhe3KSseBt7OI+fIUAjMW5Z7f5dWP7\n wboWsDdvNll3dBPwBHGeuMOHOcctxoWZkQO5qBG8Y6+1xBpcex+sQ5prxaWCvKtgCHGm\n FYBy/5LE45aLnDR6yv8d3w1QDQvzwLhJnUOrlbUVMyJFAmiNiH2uL1JB9bG1rifcQHZh\n bNPMSZuBqg/f2tQ95jTax1/LvMU9/9ZTpU+HFiou3Ox/7+ASFpiSoDZG1gZ23dSn5WMI\n XQgw==", "X-Gm-Message-State": "AOJu0YyHiqoDIQ9UR3ygU4SZzWe5nuMS8Kn6XjIRWrK2wp+XiwTlwO4u\n\tPAbaPerrZjT1HY23nIDYmJp2Y3nzdVd/jll7xo0+FcmRNF/00gnzSemZOAqWPMDB5GE=", "X-Gm-Gg": "AeBDiesWbrUtdCs6mSeYJLJcDvQJkc31Wnw61ZEUuq5OXbDO8QZT+DMTVqgCvpaD/uL\n\tJEY9sfYzTlm1LOeWxZ+lIEFpiLBCJM34kYc2N8T+teCWOUDgT05kpOs3DUr16hkRfODp+66d5ro\n\t0mEjD/CgmI/Y/ocqHFZ49KQMYfU8JHflM2x22jy26iKVgw5P9+w5m6VlyV39AlqaNl9gbw+OeYp\n\taazfLLGC2T9N6okDfVh3VEft3ZEOfvasRGqy0WRWhq+VEO1A/lmvtSTfFzY7jcXEY2qbSH0TSMd\n\tcNsD3pDePWVUgWxBcs13Q4yLrbAKW5bnirWjqIr3gwr5tH5nRkPgjO57K/ykwiYcUAqTdIKcEbg\n\tbCuzTFzguju/Y2nHuzYZMgwbIVE8E4jJaHo2Mw+L7v8RwJCNcaG98YpcULCvc2Lw+ndXZDVlnpZ\n\tjab5wnpODx/XzL/wCIYdeCaFiMEO3u2xklqKD19f8ZOLXENFlfr+GpS6qz2eqY2n7lDiteAxDFr\n\t0w=", "X-Received": "by 2002:a17:903:1103:b0:2b2:4029:d781 with SMTP id\n d9443c01a7336-2b97c46201bmr40245435ad.20.1777392509493;\n Tue, 28 Apr 2026 09:08:29 -0700 (PDT)", "From": "nspmangalore@gmail.com", "X-Google-Original-From": "sprasad@microsoft.com", "To": "linux-cifs@vger.kernel.org,\n\tsmfrench@gmail.com,\n\tpc@manguebit.org,\n\tbharathsm@microsoft.com,\n\tdhowells@redhat.com,\n\thenrique.carvalho@suse.com,\n\tematsumiya@suse.de", "Cc": "Shyam Prasad N <sprasad@microsoft.com>", "Subject": "[PATCH v3 11/19] cifs: in place changes to cached_dirents when dir\n lease is held", "Date": "Tue, 28 Apr 2026 21:37:56 +0530", "Message-ID": "<20260428160804.281745-11-sprasad@microsoft.com>", "X-Mailer": "git-send-email 2.43.0", "In-Reply-To": "<20260428160804.281745-1-sprasad@microsoft.com>", "References": "<20260428160804.281745-1-sprasad@microsoft.com>", "Precedence": "bulk", "X-Mailing-List": "linux-cifs@vger.kernel.org", "List-Id": "<linux-cifs.vger.kernel.org>", "List-Subscribe": "<mailto:linux-cifs+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-cifs+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit" }, "content": "From: Shyam Prasad N <sprasad@microsoft.com>\n\nWhen a directory lease is held, we do not need to invalidate the\ndirent cache on the cfid when new dentries are added.\n\nThis change allows local adds to directory contents to be made\nin the cached_dirents so that we don't need to fetch again from server.\n\nSigned-off-by: Shyam Prasad N <sprasad@microsoft.com>\n---\n fs/smb/client/dir.c | 95 ++++++++++---------\n fs/smb/client/inode.c | 207 +++++++++++++++++++++++++++++++++++++-----\n 2 files changed, 234 insertions(+), 68 deletions(-)", "diff": "diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c\nindex 4e5c580e4de0a..092fff1ad02a2 100644\n--- a/fs/smb/client/dir.c\n+++ b/fs/smb/client/dir.c\n@@ -194,7 +194,6 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \tstruct cached_fid *parent_cfid = NULL;\n \tint rdwr_for_fscache = 0;\n \t__le32 lease_flags = 0;\n-\tbool found_parent_cfid;\n \n \t*oplock = 0;\n \tif (tcon->ses->server->oplocks)\n@@ -320,33 +319,14 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \n retry_open:\n \tif (tcon->cfids && direntry->d_parent && server->dialect >= SMB30_PROT_ID) {\n-\t\tfound_parent_cfid = false;\n \t\tparent_cfid = NULL;\n-\t\tspin_lock(&tcon->cfids->cfid_list_lock);\n-\t\tlist_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) {\n-\t\t\tspin_lock(&parent_cfid->cfid_lock);\n-\t\t\tif (parent_cfid->dentry == direntry->d_parent) {\n-\t\t\t\tkref_get(&parent_cfid->refcount);\n-\t\t\t\tspin_unlock(&parent_cfid->cfid_lock);\n-\t\t\t\tspin_unlock(&tcon->cfids->cfid_list_lock);\n-\t\t\t\tfound_parent_cfid = true;\n-\t\t\t\tcifs_dbg(FYI, \"found a parent cached file handle\\n\");\n-\t\t\t\tif (cached_dir_copy_lease_key(parent_cfid,\n-\t\t\t\t\t\t fid->parent_lease_key)) {\n-\t\t\t\t\tlease_flags\n-\t\t\t\t\t\t|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;\n-\t\t\t\t\tmutex_lock(&parent_cfid->dirents.de_mutex);\n-\t\t\t\t\tparent_cfid->dirents.is_valid = false;\n-\t\t\t\t\tparent_cfid->dirents.is_failed = true;\n-\t\t\t\t\tmutex_unlock(&parent_cfid->dirents.de_mutex);\n-\t\t\t\t}\n-\t\t\t\tclose_cached_dir(parent_cfid);\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tspin_unlock(&parent_cfid->cfid_lock);\n+\t\tif (!open_cached_dir_by_dentry(tcon, direntry->d_parent,\n+\t\t\t\t\t &parent_cfid)) {\n+\t\t\tcifs_dbg(FYI, \"found a parent cached file handle\\n\");\n+\t\t\tif (cached_dir_copy_lease_key(parent_cfid,\n+\t\t\t\t\t fid->parent_lease_key))\n+\t\t\t\tlease_flags |= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;\n \t\t}\n-\t\tif (!found_parent_cfid)\n-\t\t\tspin_unlock(&tcon->cfids->cfid_list_lock);\n \t}\n \n \toparms = (struct cifs_open_parms) {\n@@ -364,6 +344,10 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \tif (rc) {\n \t\tcifs_dbg(FYI, \"cifs_create returned 0x%x\\n\", rc);\n \t\tif (rc == -EACCES && rdwr_for_fscache == 1) {\n+\t\t\tif (parent_cfid) {\n+\t\t\t\tclose_cached_dir(parent_cfid);\n+\t\t\t\tparent_cfid = NULL;\n+\t\t\t}\n \t\t\tdesired_access &= ~GENERIC_READ;\n \t\t\trdwr_for_fscache = 2;\n \t\t\tgoto retry_open;\n@@ -452,10 +436,25 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \t\t\tgoto out_err;\n \t\t}\n \n+\tif (newinode && parent_cfid) {\n+\t\tstruct cifs_fattr fattr;\n+\t\tbool cache_updated;\n+\n+\t\tcifs_inode_to_fattr(newinode, &fattr);\n+\t\tcache_updated = update_dirent_in_cached_dir(parent_cfid,\n+\t\t\t\t\t\t direntry->d_name.name,\n+\t\t\t\t\t\t direntry->d_name.len,\n+\t\t\t\t\t\t &fattr);\n+\t\tif (!cache_updated)\n+\t\t\tinvalidate_cached_dir_contents(parent_cfid);\n+\t}\n+\n \td_drop(direntry);\n \td_add(direntry, newinode);\n \n out:\n+\tif (parent_cfid)\n+\t\tclose_cached_dir(parent_cfid);\n \tfree_dentry_path(page);\n \treturn rc;\n \n@@ -732,27 +731,35 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,\n \n \t\tcifs_dbg(FYI, \"NULL inode in lookup\\n\");\n \n-\t\t/*\n-\t\t * We can only rely on negative dentries having the same\n-\t\t * spelling as the cached dirent if case insensitivity is\n-\t\t * forced on mount.\n-\t\t *\n-\t\t * XXX: if servers correctly announce Case Sensitivity Search\n-\t\t * on GetInfo of FileFSAttributeInformation, then we can take\n-\t\t * correct action even if case insensitive is not forced on\n-\t\t * mount.\n-\t\t */\n-\t\tif (pTcon->nocase && !open_cached_dir_by_dentry(pTcon, direntry->d_parent, &cfid)) {\n+\t\tif (!open_cached_dir_by_dentry(pTcon, direntry->d_parent, &cfid)) {\n+\t\t\tstruct qstr qname = QSTR_INIT(direntry->d_name.name, direntry->d_name.len);\n+\t\t\tstruct cached_dirent_lookup_result lookup = {};\n+\t\t\tint rc_lookup;\n+\t\t\tint rc_wait;\n+\n+\t\t\trc_wait = cifs_wait_for_pending_dcache(cfid, qname.name, qname.len);\n+\t\t\tif (rc_wait == -ETIMEDOUT)\n+\t\t\t\tcifs_dbg(FYI, \"Wait for pending dcache entry timed out\\n\");\n+\n+\t\t\trc_lookup = lookup_cached_dir(cfid, qname.name,\n+\t\t\t\t\t\t\t qname.len, &lookup);\n+\t\t\tif (!rc_lookup && lookup.found && lookup.under_active_lease) {\n+\t\t\t\tnewInode = cifs_iget(parent_dir_inode->i_sb, &lookup.fattr);\n+\t\t\t\tclose_cached_dir(cfid);\n+\t\t\t\tif (!newInode) {\n+\t\t\t\t\tde = ERR_PTR(-ENOMEM);\n+\t\t\t\t\tgoto free_dentry_path;\n+\t\t\t\t}\n+\t\t\t\trc = 0;\n+\t\t\t\trenew_parental_timestamps(direntry);\n+\t\t\t\tgoto out;\n+\t\t\t}\n+\n \t\t\t/*\n \t\t\t * dentry is negative and parent is fully cached:\n-\t\t\t * we can assume file does not exist\n+\t\t\t * we can assume file does not exist if case sensitive\n \t\t\t */\n-\t\t\tbool dirents_valid;\n-\n-\t\t\tmutex_lock(&cfid->dirents.de_mutex);\n-\t\t\tdirents_valid = cfid->dirents.is_valid;\n-\t\t\tmutex_unlock(&cfid->dirents.de_mutex);\n-\t\t\tif (dirents_valid) {\n+\t\t\tif (pTcon->nocase && cfid->dirents.is_valid) {\n \t\t\t\tclose_cached_dir(cfid);\n \t\t\t\tgoto out;\n \t\t\t}\ndiff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c\nindex e077df844c819..f03371abcfef9 100644\n--- a/fs/smb/client/inode.c\n+++ b/fs/smb/client/inode.c\n@@ -28,19 +28,18 @@\n #include \"cached_dir.h\"\n #include \"reparse.h\"\n \n-static void cifs_invalidate_cached_dir(struct cifs_tcon *tcon,\n-\t\t\t\t struct dentry *parent)\n+static void cifs_invalidate_cached_dirent(struct cifs_tcon *tcon,\n+\t\t\t\t\t\t struct dentry *parent,\n+\t\t\t\t\t\t const char *name,\n+\t\t\t\t\t\t unsigned int namelen)\n {\n \tstruct cached_fid *parent_cfid = NULL;\n \n-\tif (!tcon || !parent)\n+\tif (!tcon || !parent || !name || !namelen)\n \t\treturn;\n \n \tif (!open_cached_dir_by_dentry(tcon, parent, &parent_cfid)) {\n-\t\tmutex_lock(&parent_cfid->dirents.de_mutex);\n-\t\tparent_cfid->dirents.is_valid = false;\n-\t\tparent_cfid->dirents.is_failed = true;\n-\t\tmutex_unlock(&parent_cfid->dirents.de_mutex);\n+\t\tinvalidate_dirent_in_cached_dir(parent_cfid, name, namelen);\n \t\tclose_cached_dir(parent_cfid);\n \t}\n }\n@@ -177,6 +176,28 @@ cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)\n \tset_nlink(inode, fattr->cf_nlink);\n }\n \n+void cifs_inode_to_fattr(struct inode *inode, struct cifs_fattr *fattr)\n+{\n+\tstruct cifsInodeInfo *cifs_i = CIFS_I(inode);\n+\n+\tmemset(fattr, 0, sizeof(*fattr));\n+\tfattr->cf_cifsattrs = cifs_i->cifsAttrs;\n+\tfattr->cf_uniqueid = cifs_i->uniqueid;\n+\tfattr->cf_eof = cifs_i->netfs.remote_i_size;\n+\tfattr->cf_bytes = (u64)inode->i_blocks << 9;\n+\tfattr->cf_createtime = cifs_i->createtime;\n+\tfattr->cf_uid = inode->i_uid;\n+\tfattr->cf_gid = inode->i_gid;\n+\tfattr->cf_mode = inode->i_mode;\n+\tfattr->cf_rdev = inode->i_rdev;\n+\tfattr->cf_nlink = inode->i_nlink;\n+\tfattr->cf_dtype = S_DT(inode->i_mode);\n+\tfattr->cf_atime = inode_get_atime(inode);\n+\tfattr->cf_mtime = inode_get_mtime(inode);\n+\tfattr->cf_ctime = inode_get_ctime(inode);\n+\tfattr->cf_cifstag = cifs_i->reparse_tag;\n+}\n+\n /* populate an inode with info from a cifs_fattr struct */\n int\n cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,\n@@ -1169,6 +1190,24 @@ static inline bool is_inode_cache_good(struct inode *ino)\n \treturn ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;\n }\n \n+static bool cifs_inode_has_writable_handle(struct inode *inode)\n+{\n+\tstruct cifsInodeInfo *cifs_inode = CIFS_I(inode);\n+\tstruct cifsFileInfo *open_file;\n+\tbool writable = false;\n+\n+\tspin_lock(&cifs_inode->open_file_lock);\n+\tlist_for_each_entry(open_file, &cifs_inode->openFileList, flist) {\n+\t\tif (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {\n+\t\t\twritable = true;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tspin_unlock(&cifs_inode->open_file_lock);\n+\n+\treturn writable;\n+}\n+\n static int reparse_info_to_fattr(struct cifs_open_info_data *data,\n \t\t\t\t struct super_block *sb,\n \t\t\t\t const unsigned int xid,\n@@ -2085,7 +2124,9 @@ static int __cifs_unlink(struct inode *dir, struct dentry *dentry, bool sillyren\n \n out_reval:\n \tif (!rc && dentry->d_parent)\n-\t\tcifs_invalidate_cached_dir(tcon, dentry->d_parent);\n+\t\tcifs_invalidate_cached_dirent(tcon, dentry->d_parent,\n+\t\t\t\t\t\t\t dentry->d_name.name,\n+\t\t\t\t\t\t\t dentry->d_name.len);\n \n \tif (inode) {\n \t\tcifs_inode = CIFS_I(inode);\n@@ -2276,6 +2317,7 @@ struct dentry *cifs_mkdir(struct mnt_idmap *idmap, struct inode *inode,\n \tint rc = 0;\n \tunsigned int xid;\n \tstruct cifs_sb_info *cifs_sb;\n+\tstruct cached_fid *parent_cfid = NULL;\n \tstruct tcon_link *tlink;\n \tstruct cifs_tcon *tcon;\n \tstruct TCP_Server_Info *server;\n@@ -2337,12 +2379,26 @@ struct dentry *cifs_mkdir(struct mnt_idmap *idmap, struct inode *inode,\n \t/* TODO: skip this for smb2/smb3 */\n \trc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,\n \t\t\t xid);\n+\tif (!rc && d_inode(direntry) && direntry->d_parent &&\n+\t server->dialect >= SMB30_PROT_ID &&\n+\t !open_cached_dir_by_dentry(tcon, direntry->d_parent, &parent_cfid)) {\n+\t\tstruct cifs_fattr fattr;\n+\n+\t\tcifs_inode_to_fattr(d_inode(direntry), &fattr);\n+\t\tif (!update_dirent_in_cached_dir(parent_cfid,\n+\t\t\t\t\t\t direntry->d_name.name,\n+\t\t\t\t\t\t direntry->d_name.len,\n+\t\t\t\t\t\t &fattr))\n+\t\t\tinvalidate_cached_dir_contents(parent_cfid);\n+\t}\n mkdir_out:\n \t/*\n \t * Force revalidate to get parent dir info when needed since cached\n \t * attributes are invalid now.\n \t */\n \tCIFS_I(inode)->time = 0;\n+\tif (parent_cfid)\n+\t\tclose_cached_dir(parent_cfid);\n \tfree_dentry_path(page);\n \tfree_xid(xid);\n \tcifs_put_tlink(tlink);\n@@ -2408,7 +2464,9 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)\n \t\tclear_nlink(d_inode(direntry));\n \t\tspin_unlock(&d_inode(direntry)->i_lock);\n \t\tif (direntry->d_parent)\n-\t\t\tcifs_invalidate_cached_dir(tcon, direntry->d_parent);\n+\t\t\tcifs_invalidate_cached_dirent(tcon, direntry->d_parent,\n+\t\t\t\t\t\t\t direntry->d_name.name,\n+\t\t\t\t\t\t\t direntry->d_name.len);\n \t}\n \n \t/* force revalidate to go get info when needed */\n@@ -2518,6 +2576,7 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,\n \t struct dentry *target_dentry, unsigned int flags)\n {\n \tconst char *from_name, *to_name;\n+\tconst char *source_name, *target_name;\n \tstruct TCP_Server_Info *server;\n \tvoid *page1, *page2;\n \tstruct cifs_sb_info *cifs_sb;\n@@ -2525,10 +2584,12 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,\n \tstruct cifs_tcon *tcon;\n \tstruct dentry *source_parent;\n \tstruct dentry *target_parent;\n+\tstruct inode *source_inode;\n \tbool rehash = false;\n \tunsigned int xid;\n \tint rc, tmprc;\n \tint retry_count = 0;\n+\tunsigned int source_namelen, target_namelen;\n \tFILE_UNIX_BASIC_INFO *info_buf_source = NULL;\n #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY\n \tFILE_UNIX_BASIC_INFO *info_buf_target;\n@@ -2556,6 +2617,11 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,\n \tif (IS_ERR(tlink))\n \t\treturn PTR_ERR(tlink);\n \ttcon = tlink_tcon(tlink);\n+\tsource_inode = d_inode(source_dentry);\n+\tsource_name = source_dentry->d_name.name;\n+\tsource_namelen = source_dentry->d_name.len;\n+\ttarget_name = target_dentry->d_name.name;\n+\ttarget_namelen = target_dentry->d_name.len;\n \tsource_parent = source_dentry->d_parent ? dget(source_dentry->d_parent) : NULL;\n \ttarget_parent = target_dentry->d_parent ? dget(target_dentry->d_parent) : NULL;\n \tserver = tcon->ses->server;\n@@ -2598,6 +2664,31 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,\n \n \tif (!rc)\n \t\trehash = false;\n+\n+\t/* Update cached dirents after successful rename (before exit checks) */\n+\tif (!rc) {\n+\t\tstruct cifs_fattr fattr;\n+\t\tstruct cached_fid *target_cfid = NULL;\n+\n+\t\t/* Invalidate source entry (no longer exists at old name) */\n+\t\tcifs_invalidate_cached_dirent(tcon, source_parent,\n+\t\t\t\t\t source_name,\n+\t\t\t\t\t source_namelen);\n+\n+\t\t/* Upsert target entry with the renamed inode's attributes */\n+\t\tif (source_inode && target_parent) {\n+\t\t\tcifs_inode_to_fattr(source_inode, &fattr);\n+\t\t\tif (!open_cached_dir_by_dentry(tcon, target_parent, &target_cfid)) {\n+\t\t\t\tif (!update_dirent_in_cached_dir(target_cfid,\n+\t\t\t\t\t\t\t\t target_name,\n+\t\t\t\t\t\t\t\t target_namelen,\n+\t\t\t\t\t\t\t\t &fattr))\n+\t\t\t\t\tinvalidate_cached_dir_contents(target_cfid);\n+\t\t\t\tclose_cached_dir(target_cfid);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n \t/*\n \t * No-replace is the natural behavior for CIFS, so skip unlink hacks.\n \t */\n@@ -2693,13 +2784,6 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,\n \t\t}\n \t}\n \n-\t/* force revalidate to go get info when needed */\n-\tif (!rc) {\n-\t\tcifs_invalidate_cached_dir(tcon, source_parent);\n-\t\tif (target_parent != source_parent)\n-\t\t\tcifs_invalidate_cached_dir(tcon, target_parent);\n-\t}\n-\n \tCIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;\n \n cifs_rename_exit:\n@@ -2723,13 +2807,14 @@ cifs_dentry_needs_reval(struct dentry *dentry)\n \tstruct inode *inode = d_inode(dentry);\n \tstruct cifsInodeInfo *cifs_i = CIFS_I(inode);\n \tstruct cifs_sb_info *cifs_sb = CIFS_SB(inode);\n-\tstruct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);\n+\tstruct tcon_link *tlink;\n+\tstruct cifs_tcon *tcon;\n \tstruct cached_fid *cfid = NULL;\n+\tbool retried_pending = false;\n+\tbool force_reval = cifs_i->time == 0;\n \n \tif (test_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags))\n \t\treturn false;\n-\tif (cifs_i->time == 0)\n-\t\treturn true;\n \n \tif (CIFS_CACHE_READ(cifs_i))\n \t\treturn false;\n@@ -2737,36 +2822,110 @@ cifs_dentry_needs_reval(struct dentry *dentry)\n \tif (!lookupCacheEnabled)\n \t\treturn true;\n \n+\ttlink = cifs_sb_tlink(cifs_sb);\n+\tif (IS_ERR(tlink))\n+\t\treturn true;\n+\ttcon = tlink_tcon(tlink);\n+\n \tif (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {\n \t\tif (cifs_i->time > cfid->time) {\n \t\t\tclose_cached_dir(cfid);\n+\t\t\tcifs_put_tlink(tlink);\n \t\t\treturn false;\n \t\t}\n \t\tclose_cached_dir(cfid);\n \t}\n+\n+\tif (dentry->d_parent) {\n+\t\tstruct cached_dirent_lookup_result lookup = {};\n+\t\tint rc;\n+\t\tint rc_wait;\n+\n+\tretry_lookup:\n+\t\tcfid = NULL;\n+\t\tif (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {\n+\t\t\trc = lookup_cached_dir(cfid, dentry->d_name.name,\n+\t\t\t\t\t\t\t dentry->d_name.len,\n+\t\t\t\t\t\t\t &lookup);\n+\t\t\tif (rc == -ENOENT && !retried_pending) {\n+\t\t\t\trc_wait = cifs_wait_for_pending_dcache(cfid,\n+\t\t\t\t\t\t\t dentry->d_name.name,\n+\t\t\t\t\t\t\t dentry->d_name.len);\n+\t\t\t\tif (rc_wait == -ETIMEDOUT)\n+\t\t\t\t\tcifs_dbg(FYI,\n+\t\t\t\t\t\t \"Timed out waiting for async dcache population of %pd\\n\",\n+\t\t\t\t\t\t dentry);\n+\t\t\t\telse if (!rc_wait) {\n+\t\t\t\t\tclose_cached_dir(cfid);\n+\t\t\t\t\tretried_pending = true;\n+\t\t\t\t\tgoto retry_lookup;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tclose_cached_dir(cfid);\n+\t\t\tif (!rc && lookup.found && lookup.under_active_lease) {\n+\t\t\t\tif (cifs_inode_has_writable_handle(inode)) {\n+\t\t\t\t\tcifs_set_time(dentry, jiffies);\n+\t\t\t\t\tcifs_put_tlink(tlink);\n+\t\t\t\t\treturn false;\n+\t\t\t\t}\n+\t\t\t\trc = cifs_fattr_to_inode(inode, &lookup.fattr, false);\n+\t\t\t\tif (!rc) {\n+\t\t\t\t\tcifs_set_time(dentry, jiffies);\n+\t\t\t\t\tcifs_put_tlink(tlink);\n+\t\t\t\t\treturn false;\n+\t\t\t\t}\n+\t\t\t\tif (rc != -ESTALE) {\n+\t\t\t\t\tcifs_put_tlink(tlink);\n+\t\t\t\t\treturn true;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Even when metadata is marked stale (time == 0), attempt the\n+\t * cached-dir fast path above first; only force wire revalidation if\n+\t * cache lookup/update did not satisfy this dentry.\n+\t */\n+\tif (force_reval) {\n+\t\tcifs_put_tlink(tlink);\n+\t\treturn true;\n+\t}\n+\n \t/*\n \t * depending on inode type, check if attribute caching disabled for\n \t * files or directories\n \t */\n \tif (S_ISDIR(inode->i_mode)) {\n-\t\tif (!cifs_sb->ctx->acdirmax)\n+\t\tif (!cifs_sb->ctx->acdirmax) {\n+\t\t\tcifs_put_tlink(tlink);\n \t\t\treturn true;\n+\t\t}\n \t\tif (!time_in_range(jiffies, cifs_i->time,\n-\t\t\t\t cifs_i->time + cifs_sb->ctx->acdirmax))\n+\t\t\t\t cifs_i->time + cifs_sb->ctx->acdirmax)) {\n+\t\t\tcifs_put_tlink(tlink);\n \t\t\treturn true;\n+\t\t}\n \t} else { /* file */\n-\t\tif (!cifs_sb->ctx->acregmax)\n+\t\tif (!cifs_sb->ctx->acregmax) {\n+\t\t\tcifs_put_tlink(tlink);\n \t\t\treturn true;\n+\t\t}\n \t\tif (!time_in_range(jiffies, cifs_i->time,\n-\t\t\t\t cifs_i->time + cifs_sb->ctx->acregmax))\n+\t\t\t\t cifs_i->time + cifs_sb->ctx->acregmax)) {\n+\t\t\tcifs_put_tlink(tlink);\n \t\t\treturn true;\n+\t\t}\n \t}\n \n \t/* hardlinked files w/ noserverino get \"special\" treatment */\n \tif (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM) &&\n-\t S_ISREG(inode->i_mode) && inode->i_nlink != 1)\n+\t S_ISREG(inode->i_mode) && inode->i_nlink != 1) {\n+\t\tcifs_put_tlink(tlink);\n \t\treturn true;\n+\t}\n \n+\tcifs_put_tlink(tlink);\n \treturn false;\n }\n \n", "prefixes": [ "v3", "11/19" ] }