Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2218335/?format=api
{ "id": 2218335, "url": "http://patchwork.ozlabs.org/api/patches/2218335/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260401011153.1757515-1-pc@manguebit.org/", "project": { "id": 12, "url": "http://patchwork.ozlabs.org/api/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": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260401011153.1757515-1-pc@manguebit.org>", "list_archive_url": null, "date": "2026-04-01T01:11:53", "name": "[RFC] smb: client: add support for O_TMPFILE", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "843d6a361eb180427e097e665280bec0c2e1965a", "submitter": { "id": 91025, "url": "http://patchwork.ozlabs.org/api/people/91025/?format=api", "name": "Paulo Alcantara", "email": "pc@manguebit.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260401011153.1757515-1-pc@manguebit.org/mbox/", "series": [ { "id": 498266, "url": "http://patchwork.ozlabs.org/api/series/498266/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/list/?series=498266", "date": "2026-04-01T01:11:53", "name": "[RFC] smb: client: add support for O_TMPFILE", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/498266/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2218335/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2218335/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-cifs+bounces-10602-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 secure) header.d=manguebit.org header.i=@manguebit.org header.a=rsa-sha256\n header.s=dkim header.b=p/IPXlqT;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-cifs+bounces-10602-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=manguebit.org header.i=@manguebit.org\n header.b=\"p/IPXlqT\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=143.255.12.172", "smtp.subspace.kernel.org;\n dmarc=pass (p=quarantine dis=none) header.from=manguebit.org", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=manguebit.org" ], "Received": [ "from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::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 4fln5f0MYRz1yCp\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 01 Apr 2026 12:12:21 +1100 (AEDT)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id E53A430036CD\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 1 Apr 2026 01:12:07 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 601142773F0;\n\tWed, 1 Apr 2026 01:12:07 +0000 (UTC)", "from mx1.manguebit.org (mx1.manguebit.org [143.255.12.172])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E4731D0DEE;\n\tWed, 1 Apr 2026 01:12:04 +0000 (UTC)", "from pc by mx1.manguebit.org with local (Exim 4.99.1)\n\tid 1w7k7d-00000001znP-1k1m;\n\tTue, 31 Mar 2026 22:11:53 -0300" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775005927; cv=none;\n b=D1C6DIpLSxzqiJ8oXyc2lMZdz66SJt8NrCgISsotjdFIRLroGcr3UGEy7aUpKNgoW7re7BWPboldgafAZM9Rha5y4dmUOFmsihttbLh07Iwhq39bova0tzWtnRHNHajla7qPLGdsEYuf+6JWwo85yCEoknE2medntgtk/YLHgkU=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775005927; c=relaxed/simple;\n\tbh=tVZVPRF4eIEP9VTAsc44bolm2U8RiKKG6o9yMgI8m7E=;\n\th=From:To:Cc:Subject:Date:Message-ID:MIME-Version;\n b=AstBfYBFeXWlopaR1jBUKMzJ5ZcRKRXKXQXJuPlrdX1KL4b2uTLQTyCYlVy3jKPNuik8ssZR+F+NnjpgKtqFE3ZwjlZpOp7lPQkak9jT7HPQCM7fX0aKKZKrVUdDMdOeuHUJoITlAgsYdTvSvUBNkUYdI6CMVP3K8fOvSuUD9xw=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=quarantine dis=none) header.from=manguebit.org;\n spf=pass smtp.mailfrom=manguebit.org;\n dkim=pass (2048-bit key) header.d=manguebit.org header.i=@manguebit.org\n header.b=p/IPXlqT; arc=none smtp.client-ip=143.255.12.172", "DKIM-Signature": "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=manguebit.org; s=dkim; h=Content-Transfer-Encoding:MIME-Version:Message-ID:\n\tDate:Subject:Cc:To:From:Sender:Content-Type:Reply-To:Content-ID:\n\tContent-Description:In-Reply-To:References;\n\tbh=vLoXCGS1LwabYnwR/YTGODiGbpj4Fpgd0wr0/yeEgRI=; b=p/IPXlqTqk6IHVn5o9QAiH+ak7\n\tIVp3N9XResih6cW34C7GvX/gZUPDB8/OHbqyLtp+F9sYjVetODPKP0OCRbofznzZof/rt2FBkFil9\n\tDEZsEc2mORdA4ky5pLwpg/dZmd6SvBtCrCyF8XtVCSnPVpxN2W+I5W0PZUY39UPsDXCD1kvYFK/2w\n\tGuFvs3rJPq0/Ms5CWvcbDXU8o5Gk+y0S/IBGIRbAAkfuNXTB7mB1D6Mr6QkvWXNWNuX+y2DcXhSM3\n\tGsHmjG/eZIryvoqGd+rcQu8bHTj2QkbaWpgMvd0/VHDxy3evfwBE+iXVpWxGYIVUolLh+/LiXFpxd\n\tlO++kvVg==;", "From": "Paulo Alcantara <pc@manguebit.org>", "To": "viro@zeniv.linux.org.uk,\n\tbrauner@kernel.org,\n\tsmfrench@gmail.com", "Cc": "\"Paulo Alcantara (Red Hat)\" <pc@manguebit.org>,\n\tDavid Howells <dhowells@redhat.com>,\n\tlinux-fsdevel@vger.kernel.org,\n\tlinux-cifs@vger.kernel.org", "Subject": "[RFC PATCH] smb: client: add support for O_TMPFILE", "Date": "Tue, 31 Mar 2026 22:11:53 -0300", "Message-ID": "<20260401011153.1757515-1-pc@manguebit.org>", "X-Mailer": "git-send-email 2.53.0", "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": "Implement O_TMPFILE support for SMB2+ in the CIFS client.\n\nSigned-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>\nCc: David Howells <dhowells@redhat.com>\nCc: linux-fsdevel@vger.kernel.org\nCc: linux-cifs@vger.kernel.org\n---\nAl, Christian,\n\nCould you please have a look at cifs_d_mark_tmpfile() in this patch?\nThis is just an open-coded version of d_mark_tmpfile() but with the\nability of setting ->d_shortname with CIFS generated tmpfile names\ninstead.\n\nI do know we're not supposed to change ->d_shortname or ->__dname\ndirectly outside fs/dcache.c, so I've added cifs_d_mark_tmpfile() just\nto show you how simple it would be supporting O_TMPFILE in CIFS by\nhaving a function like that.\n\nCIFS relies heavily on\n\n\tpage = alloc_dentry_path();\n\tfull_path = build_path_from_dentry(dentry, page);\n\t...\n\nin order to build full paths all the way from current dentry up to the\nroot; including share name and prefix paths, in some cases.\n\nMost of the CIFS functions are path-based, hence not instantiating\nO_TMPFILE dentries with CIFS-specific tmpfile names will require a lot\nof changes on how we build those full paths. In the worst case having\nto increase inode by storing those tmpfile names, having to kmalloc()\nand then append the names with ->d_parent when CIFS_INO_TMPFILE bit is\nset, etc.\n\nWould it be OK to have a helper or extend d_mark_tmpfile() in a way\nthat we can _optionally_ pass down @name and @namelen (<=\nDNAME_INLINE_LEN - 1) and then set it in O_TMPFILE dentry?\n\nIf there is another way to solve that, then please let me know.\n\nThanks.\n\n fs/smb/client/cifsfs.c | 4 +\n fs/smb/client/cifsfs.h | 19 ++\n fs/smb/client/cifsglob.h | 23 ++-\n fs/smb/client/cifsproto.h | 3 +-\n fs/smb/client/dir.c | 232 ++++++++++++++++++++--\n fs/smb/client/file.c | 23 ++-\n fs/smb/client/inode.c | 3 +-\n fs/smb/client/link.c | 1 +\n fs/smb/client/smb2inode.c | 403 ++++++++++++++------------------------\n 9 files changed, 426 insertions(+), 285 deletions(-)", "diff": "diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c\nindex 32d0305a1239..f4bed8d4a072 100644\n--- a/fs/smb/client/cifsfs.c\n+++ b/fs/smb/client/cifsfs.c\n@@ -124,6 +124,9 @@ MODULE_PARM_DESC(dir_cache_timeout, \"Number of seconds to cache directory conten\n /* Module-wide total cached dirents (in bytes) across all tcons */\n atomic64_t cifs_dircache_bytes_used = ATOMIC64_INIT(0);\n \n+atomic_t cifs_sillycounter;\n+atomic_t cifs_tmpcounter;\n+\n /*\n * Write-only module parameter to drop all cached directory entries across\n * all CIFS mounts. Echo a non-zero value to trigger.\n@@ -1199,6 +1202,7 @@ MODULE_ALIAS(\"smb3\");\n const struct inode_operations cifs_dir_inode_ops = {\n \t.create = cifs_create,\n \t.atomic_open = cifs_atomic_open,\n+\t.tmpfile = cifs_tmpfile,\n \t.lookup = cifs_lookup,\n \t.getattr = cifs_getattr,\n \t.unlink = cifs_unlink,\ndiff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h\nindex e320d39b01f5..64c7a4c6ac83 100644\n--- a/fs/smb/client/cifsfs.h\n+++ b/fs/smb/client/cifsfs.h\n@@ -13,6 +13,9 @@\n \n #define ROOT_I 2\n \n+extern atomic_t cifs_sillycounter;\n+extern atomic_t cifs_tmpcounter;\n+\n /*\n * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down\n * so that it will fit. We use hash_64 to convert the value to 31 bits, and\n@@ -53,6 +56,8 @@ int cifs_create(struct mnt_idmap *idmap, struct inode *inode,\n \t\tstruct dentry *direntry, umode_t mode, bool excl);\n int cifs_atomic_open(struct inode *inode, struct dentry *direntry,\n \t\t struct file *file, unsigned int oflags, umode_t mode);\n+int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,\n+\t\t struct file *file, umode_t mode);\n struct dentry *cifs_lookup(struct inode *parent_dir_inode,\n \t\t\t struct dentry *direntry, unsigned int flags);\n int cifs_unlink(struct inode *dir, struct dentry *dentry);\n@@ -142,6 +147,20 @@ struct smb3_fs_context;\n struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type, int flags,\n \t\t\t\t struct smb3_fs_context *old_ctx);\n \n+char *cifs_silly_fullpath(struct dentry *dentry);\n+\n+#define CIFS_TMPNAME_PREFIX \".__smbfile_tmp\"\n+#define CIFS_TMPNAME_PREFIX_LEN ((int)sizeof(CIFS_TMPNAME_PREFIX) - 1)\n+#define CIFS_TMPNAME_COUNTER_LEN ((int)sizeof(cifs_tmpcounter) * 2)\n+#define CIFS_TMPNAME_LEN \\\n+\t(CIFS_TMPNAME_PREFIX_LEN + CIFS_TMPNAME_COUNTER_LEN)\n+\n+#define CIFS_SILLYNAME_PREFIX\t \".__smbfile_silly\"\n+#define CIFS_SILLYNAME_PREFIX_LEN ((int)sizeof(CIFS_SILLYNAME_PREFIX) - 1)\n+#define CIFS_SILLYNAME_COUNTER_LEN ((int)sizeof(cifs_sillycounter) * 2)\n+#define CIFS_SILLYNAME_LEN \\\n+\t(CIFS_SILLYNAME_PREFIX_LEN + CIFS_SILLYNAME_COUNTER_LEN)\n+\n #ifdef CONFIG_CIFS_NFSD_EXPORT\n extern const struct export_operations cifs_export_ops;\n #endif /* CONFIG_CIFS_NFSD_EXPORT */\ndiff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h\nindex 709e96e07791..8f35bbc3db6b 100644\n--- a/fs/smb/client/cifsglob.h\n+++ b/fs/smb/client/cifsglob.h\n@@ -1534,9 +1534,16 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,\n #define CIFS_CACHE_RW_FLG\t(CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG)\n #define CIFS_CACHE_RHW_FLG\t(CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG)\n \n-/*\n- * One of these for each file inode\n- */\n+enum cifs_inode_flags {\n+\tCIFS_INODE_PENDING_OPLOCK_BREAK,\t/* oplock break in progress */\n+\tCIFS_INODE_PENDING_WRITERS,\t\t/* Writes in progress */\n+\tCIFS_INODE_FLAG_UNUSED,\t\t\t/* Unused flag */\n+\tCIFS_INO_DELETE_PENDING,\t\t/* delete pending on server */\n+\tCIFS_INO_INVALID_MAPPING,\t\t/* pagecache is invalid */\n+\tCIFS_INO_LOCK,\t\t\t\t/* lock bit for synchronization */\n+\tCIFS_INO_CLOSE_ON_LOCK,\t\t\t/* Not to defer the close when lock is set */\n+\tCIFS_INO_TMPFILE,\t\t\t/* for O_TMPFILE inodes */\n+};\n \n struct cifsInodeInfo {\n \tstruct netfs_inode netfs; /* Netfslib context and vfs inode */\n@@ -1554,13 +1561,6 @@ struct cifsInodeInfo {\n \t__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */\n \tunsigned int oplock;\t\t/* oplock/lease level we have */\n \t__u16 epoch;\t\t/* used to track lease state changes */\n-#define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */\n-#define CIFS_INODE_PENDING_WRITERS\t (1) /* Writes in progress */\n-#define CIFS_INODE_FLAG_UNUSED\t\t (2) /* Unused flag */\n-#define CIFS_INO_DELETE_PENDING\t\t (3) /* delete pending on server */\n-#define CIFS_INO_INVALID_MAPPING\t (4) /* pagecache is invalid */\n-#define CIFS_INO_LOCK\t\t\t (5) /* lock bit for synchronization */\n-#define CIFS_INO_CLOSE_ON_LOCK (7) /* Not to defer the close when lock is set */\n \tunsigned long flags;\n \tspinlock_t writers_lock;\n \tunsigned int writers;\t\t/* Number of writers on this inode */\n@@ -2259,6 +2259,7 @@ struct smb2_compound_vars {\n \tstruct kvec qi_iov;\n \tstruct kvec io_iov[SMB2_IOCTL_IOV_SIZE];\n \tstruct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];\n+\tstruct kvec hl_iov[SMB2_SET_INFO_IOV_SIZE];\n \tstruct kvec unlink_iov[SMB2_SET_INFO_IOV_SIZE];\n \tstruct kvec rename_iov[SMB2_SET_INFO_IOV_SIZE];\n \tstruct kvec close_iov;\n@@ -2383,6 +2384,8 @@ static inline int cifs_open_create_options(unsigned int oflags, int opts)\n \t\topts |= CREATE_WRITE_THROUGH;\n \tif (oflags & O_DIRECT)\n \t\topts |= CREATE_NO_BUFFER;\n+\tif (oflags & O_TMPFILE)\n+\t\topts |= CREATE_DELETE_ON_CLOSE;\n \treturn opts;\n }\n \ndiff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h\nindex 884bfa1cf0b4..c24c50d732e6 100644\n--- a/fs/smb/client/cifsproto.h\n+++ b/fs/smb/client/cifsproto.h\n@@ -141,7 +141,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,\n int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,\n \t\t\t unsigned int find_flags, unsigned int open_flags,\n \t\t\t struct cifsFileInfo **ret_file);\n-int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, int flags,\n+int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,\n+\t\t\t struct inode *inode, int flags,\n \t\t\t struct cifsFileInfo **ret_file);\n struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode,\n \t\t\t\t\t unsigned int find_flags,\ndiff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c\nindex 6d2378eeb7f6..f485259c9ed3 100644\n--- a/fs/smb/client/dir.c\n+++ b/fs/smb/client/dir.c\n@@ -287,16 +287,22 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \t\tdesired_access |= GENERIC_WRITE;\n \tif (rdwr_for_fscache == 1)\n \t\tdesired_access |= GENERIC_READ;\n+\tif (oflags & O_TMPFILE)\n+\t\tdesired_access |= DELETE;\n \n \tdisposition = FILE_OVERWRITE_IF;\n-\tif ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))\n+\tif (oflags & O_CREAT) {\n+\t\tif (oflags & O_EXCL)\n+\t\t\tdisposition = FILE_CREATE;\n+\t\telse if (oflags & O_TRUNC)\n+\t\t\tdisposition = FILE_OVERWRITE_IF;\n+\t\telse\n+\t\t\tdisposition = FILE_OPEN_IF;\n+\t} else if (oflags & O_TMPFILE) {\n \t\tdisposition = FILE_CREATE;\n-\telse if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))\n-\t\tdisposition = FILE_OVERWRITE_IF;\n-\telse if ((oflags & O_CREAT) == O_CREAT)\n-\t\tdisposition = FILE_OPEN_IF;\n-\telse\n+\t} else {\n \t\tcifs_dbg(FYI, \"Create flag not set in create function\\n\");\n+\t}\n \n \t/*\n \t * BB add processing to set equivalent of mode - e.g. via CreateX with\n@@ -436,15 +442,20 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \t\tgoto out_err;\n \t}\n \n-\tif (newinode)\n-\t\tif (S_ISDIR(newinode->i_mode)) {\n-\t\t\trc = -EISDIR;\n-\t\t\tgoto out_err;\n-\t\t}\n+\tif (newinode && S_ISDIR(newinode->i_mode)) {\n+\t\trc = -EISDIR;\n+\t\tgoto out_err;\n+\t}\n \n \td_drop(direntry);\n-\td_add(direntry, newinode);\n-\n+\tinode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));\n+\tif (oflags & O_TMPFILE) {\n+\t\tset_nlink(newinode, 0);\n+\t\tmark_inode_dirty(newinode);\n+\t\td_instantiate(direntry, newinode);\n+\t} else {\n+\t\td_add(direntry, newinode);\n+\t}\n out:\n \tfree_dentry_path(page);\n \treturn rc;\n@@ -959,6 +970,201 @@ static int cifs_ci_compare(const struct dentry *dentry,\n \treturn 0;\n }\n \n+static int set_hidden_attr(const unsigned int xid,\n+\t\t\t struct TCP_Server_Info *server,\n+\t\t\t struct file *file)\n+{\n+\tstruct dentry *dentry = file->f_path.dentry;\n+\tstruct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry));\n+\tFILE_BASIC_INFO fi = {\n+\t\t.Attributes = cpu_to_le32(cinode->cifsAttrs |\n+\t\t\t\t\t ATTR_HIDDEN),\n+\t};\n+\tvoid *page = alloc_dentry_path();\n+\tconst char *full_path;\n+\tint rc;\n+\n+\tfull_path = build_path_from_dentry(dentry, page);\n+\tif (IS_ERR(full_path))\n+\t\trc = PTR_ERR(full_path);\n+\telse\n+\t\trc = server->ops->set_file_info(d_inode(dentry),\n+\t\t\t\t\t\t full_path, &fi, xid);\n+\tfree_dentry_path(page);\n+\treturn rc;\n+}\n+\n+static void cifs_d_mark_tmpfile(struct file *file,\n+\t\t\t\tconst unsigned char *name,\n+\t\t\t\tsize_t namelen)\n+{\n+\tstruct dentry *dentry = file->f_path.dentry;\n+\n+\tBUG_ON(dentry->d_name.name != dentry->d_shortname.string ||\n+\t !hlist_unhashed(&dentry->d_u.d_alias) ||\n+\t !d_unlinked(dentry) ||\n+\t namelen > DNAME_INLINE_LEN - 1);\n+\tspin_lock(&dentry->d_parent->d_lock);\n+\tspin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);\n+\tdentry->__d_name.len = sprintf(dentry->d_shortname.string, \"%.*s\",\n+\t\t\t\t (int)namelen, name);\n+\tspin_unlock(&dentry->d_lock);\n+\tspin_unlock(&dentry->d_parent->d_lock);\n+}\n+\n+static int set_tmpfile_name(struct file *file)\n+{\n+\tstruct dentry *dentry = file->f_path.dentry;\n+\tunsigned char name[CIFS_TMPNAME_LEN + 1];\n+\tstruct dentry *sdentry = NULL;\n+\n+\tdo {\n+\t\tdput(sdentry);\n+\t\tscnprintf(name, sizeof(name),\n+\t\t\t CIFS_TMPNAME_PREFIX \"%0*x\",\n+\t\t\t CIFS_TMPNAME_COUNTER_LEN,\n+\t\t\t atomic_inc_return(&cifs_tmpcounter));\n+\t\tsdentry = lookup_noperm_unlocked(&QSTR(name), dentry->d_parent);\n+\t\tif (IS_ERR(sdentry))\n+\t\t\treturn -EBUSY;\n+\t} while (!d_is_negative(sdentry));\n+\tdput(sdentry);\n+\tcifs_d_mark_tmpfile(file, name, sizeof(name) - 1);\n+\treturn 0;\n+}\n+\n+int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,\n+\t\t struct file *file, umode_t mode)\n+{\n+\tstruct dentry *dentry = file->f_path.dentry;\n+\tstruct cifs_sb_info *cifs_sb = CIFS_SB(dir);\n+\tstruct TCP_Server_Info *server;\n+\tstruct cifs_pending_open open;\n+\tstruct cifsFileInfo *cfile;\n+\tstruct cifs_fid fid = {};\n+\tstruct tcon_link *tlink;\n+\tstruct cifs_tcon *tcon;\n+\tunsigned int sbflags;\n+\tunsigned int xid;\n+\t__u32 oplock;\n+\tint rc;\n+\n+\tif (unlikely(cifs_forced_shutdown(cifs_sb)))\n+\t\treturn smb_EIO(smb_eio_trace_forced_shutdown);\n+\n+\ttlink = cifs_sb_tlink(cifs_sb);\n+\tif (IS_ERR(tlink))\n+\t\treturn PTR_ERR(tlink);\n+\ttcon = tlink_tcon(tlink);\n+\tserver = tcon->ses->server;\n+\n+\txid = get_xid();\n+\n+\tif (server->vals->protocol_id < SMB20_PROT_ID) {\n+\t\tcifs_dbg(VFS | ONCE, \"O_TMPFILE is supported only in SMB2+\\n\");\n+\t\trc = -EOPNOTSUPP;\n+\t\tgoto out;\n+\t}\n+\n+\trc = set_tmpfile_name(file);\n+\tif (rc)\n+\t\tgoto out;\n+\n+\tif (server->ops->new_lease_key)\n+\t\tserver->ops->new_lease_key(&fid);\n+\tcifs_add_pending_open(&fid, tlink, &open);\n+\n+\trc = cifs_do_create(dir, dentry, xid, tlink, file->f_flags,\n+\t\t\t mode, &oplock, &fid, NULL);\n+\tif (rc) {\n+\t\tcifs_del_pending_open(&open);\n+\t\tgoto out;\n+\t}\n+\n+\trc = finish_open(file, dentry, generic_file_open);\n+\tif (rc)\n+\t\tgoto err_open;\n+\n+\tsbflags = cifs_sb_flags(cifs_sb);\n+\tif ((file->f_flags & O_DIRECT) && (sbflags & CIFS_MOUNT_STRICT_IO)) {\n+\t\tif (sbflags & CIFS_MOUNT_NO_BRL)\n+\t\t\tfile->f_op = &cifs_file_direct_nobrl_ops;\n+\t\telse\n+\t\t\tfile->f_op = &cifs_file_direct_ops;\n+\t}\n+\n+\tcfile = cifs_new_fileinfo(&fid, file, tlink, oplock, NULL);\n+\tif (!cfile) {\n+\t\trc = -ENOMEM;\n+\t\tgoto err_open;\n+\t}\n+\n+\trc = set_hidden_attr(xid, server, file);\n+\tif (rc)\n+\t\tgoto out;\n+\n+\tfscache_use_cookie(cifs_inode_cookie(file_inode(file)),\n+\t\t\t file->f_mode & FMODE_WRITE);\n+out:\n+\tcifs_put_tlink(tlink);\n+\tfree_xid(xid);\n+\treturn rc;\n+err_open:\n+\tcifs_del_pending_open(&open);\n+\tif (server->ops->close)\n+\t\tserver->ops->close(xid, tcon, &fid);\n+\tgoto out;\n+}\n+\n+static char *__cifs_silly_fullpath(struct dentry *dentry,\n+\t\t\t\t const unsigned char *name,\n+\t\t\t\t size_t namelen)\n+{\n+\tstruct cifs_sb_info *cifs_sb = CIFS_SB(dentry);\n+\tchar *page = alloc_dentry_path();\n+\tconst char *path;\n+\tchar *npath;\n+\tsize_t len;\n+\n+\tpath = build_path_from_dentry(dentry->d_parent, page);\n+\tif (IS_ERR(path)) {\n+\t\tnpath = ERR_CAST(path);\n+\t\tgoto out;\n+\t}\n+\n+\tlen = strlen(path) + namelen + 2;\n+\tnpath = kmalloc(len, GFP_KERNEL);\n+\tif (npath) {\n+\t\tscnprintf(npath, len, \"%s%c%s\", path,\n+\t\t\t CIFS_DIR_SEP(cifs_sb), name);\n+\t} else {\n+\t\tnpath = ERR_PTR(-ENOMEM);\n+\t}\n+out:\n+\tfree_dentry_path(page);\n+\treturn npath;\n+}\n+\n+char *cifs_silly_fullpath(struct dentry *dentry)\n+{\n+\tunsigned char name[CIFS_SILLYNAME_LEN + 1];\n+\tsize_t namesize = sizeof(name);\n+\tstruct dentry *sdentry = NULL;\n+\n+\tdo {\n+\t\tdput(sdentry);\n+\t\tscnprintf(name, namesize,\n+\t\t\t CIFS_SILLYNAME_PREFIX \"%0*x\",\n+\t\t\t CIFS_SILLYNAME_COUNTER_LEN,\n+\t\t\t atomic_inc_return(&cifs_sillycounter));\n+\t\tsdentry = lookup_noperm(&QSTR(name), dentry->d_parent);\n+\t\tif (IS_ERR(sdentry))\n+\t\t\treturn ERR_PTR(-EBUSY);\n+\t} while (!d_is_negative(sdentry));\n+\tdput(sdentry);\n+\treturn __cifs_silly_fullpath(dentry, name, namesize - 1);\n+}\n+\n const struct dentry_operations cifs_ci_dentry_ops = {\n \t.d_revalidate = cifs_d_revalidate,\n \t.d_hash = cifs_ci_hash,\ndiff --git a/fs/smb/client/file.c b/fs/smb/client/file.c\nindex a69e05f86d7e..31805414a02c 100644\n--- a/fs/smb/client/file.c\n+++ b/fs/smb/client/file.c\n@@ -696,6 +696,7 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,\n \tcfile->f_flags = file->f_flags;\n \tcfile->invalidHandle = false;\n \tcfile->deferred_close_scheduled = false;\n+\tcfile->status_file_deleted = file->f_flags & O_TMPFILE;\n \tcfile->tlink = cifs_get_tlink(tlink);\n \tINIT_WORK(&cfile->oplock_break, cifs_oplock_break);\n \tINIT_WORK(&cfile->put, cifsFileInfo_put_work);\n@@ -727,6 +728,8 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,\n \n \t/* if readable file instance put first in list*/\n \tspin_lock(&cinode->open_file_lock);\n+\tif (file->f_flags & O_TMPFILE)\n+\t\tset_bit(CIFS_INO_TMPFILE, &cinode->flags);\n \tfid->purge_cache = false;\n \tserver->ops->set_fid(cfile, fid, oplock);\n \n@@ -2578,13 +2581,12 @@ int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,\n \t\t\t struct cifsFileInfo **ret_file)\n {\n \tstruct cifsFileInfo *open_file, *inv_file = NULL;\n+\tbool fsuid_only, with_delete;\n \tstruct cifs_sb_info *cifs_sb;\n \tbool any_available = false;\n-\tint rc = -EBADF;\n \tunsigned int refind = 0;\n-\tbool fsuid_only = find_flags & FIND_FSUID_ONLY;\n-\tbool with_delete = find_flags & FIND_WITH_DELETE;\n \t*ret_file = NULL;\n+\tint rc = -EBADF;\n \n \t/*\n \t * Having a null inode here (because mapping->host was set to zero by\n@@ -2600,11 +2602,15 @@ int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,\n \n \tcifs_sb = CIFS_SB(cifs_inode);\n \n+\tspin_lock(&cifs_inode->open_file_lock);\n+\tif (test_bit(CIFS_INO_TMPFILE, &cifs_inode->flags))\n+\t\tfind_flags = FIND_ANY;\n+\n+\twith_delete = find_flags & FIND_WITH_DELETE;\n+\tfsuid_only = find_flags & FIND_FSUID_ONLY;\n \t/* only filter by fsuid on multiuser mounts */\n \tif (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MULTIUSER))\n \t\tfsuid_only = false;\n-\n-\tspin_lock(&cifs_inode->open_file_lock);\n refind_writable:\n \tif (refind > MAX_REOPEN_ATT) {\n \t\tspin_unlock(&cifs_inode->open_file_lock);\n@@ -2683,10 +2689,9 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, int flags)\n \treturn cfile;\n }\n \n-int\n-cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,\n-\t\t int flags,\n-\t\t struct cifsFileInfo **ret_file)\n+int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,\n+\t\t\t struct inode *inode, int flags,\n+\t\t\t struct cifsFileInfo **ret_file)\n {\n \tstruct cifsFileInfo *cfile;\n \tvoid *page = alloc_dentry_path();\ndiff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c\nindex 888f9e35f14b..24040909d184 100644\n--- a/fs/smb/client/inode.c\n+++ b/fs/smb/client/inode.c\n@@ -2690,7 +2690,8 @@ cifs_dentry_needs_reval(struct dentry *dentry)\n \tstruct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);\n \tstruct cached_fid *cfid = NULL;\n \n-\tif (test_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags))\n+\tif (test_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags) ||\n+\t test_bit(CIFS_INO_TMPFILE, &cifs_i->flags))\n \t\treturn false;\n \tif (cifs_i->time == 0)\n \t\treturn true;\ndiff --git a/fs/smb/client/link.c b/fs/smb/client/link.c\nindex 434e8fe74080..dd127917a340 100644\n--- a/fs/smb/client/link.c\n+++ b/fs/smb/client/link.c\n@@ -503,6 +503,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,\n \tif (d_really_is_positive(old_file)) {\n \t\tcifsInode = CIFS_I(d_inode(old_file));\n \t\tif (rc == 0) {\n+\t\t\tclear_bit(CIFS_INO_TMPFILE, &cifsInode->flags);\n \t\t\tspin_lock(&d_inode(old_file)->i_lock);\n \t\t\tinc_nlink(d_inode(old_file));\n \t\t\tspin_unlock(&d_inode(old_file)->i_lock);\ndiff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c\nindex 364bdcff9c9d..6a302beee043 100644\n--- a/fs/smb/client/smb2inode.c\n+++ b/fs/smb/client/smb2inode.c\n@@ -164,6 +164,27 @@ static int check_wsl_eas(struct kvec *rsp_iov)\n \treturn 0;\n }\n \n+/*\n+ * If @cfile is NULL, then need to account for extra open and close requests in\n+ * the compound chain.\n+ */\n+static void set_next_compound(struct cifs_tcon *tcon,\n+\t\t\t struct cifsFileInfo *cfile,\n+\t\t\t int i, int num_cmds,\n+\t\t\t struct smb_rqst *rqst, int *num_rqst)\n+{\n+\tint k = !cfile ? 1 : 0;\n+\n+\tif (i + 1 < num_cmds + k)\n+\t\tsmb2_set_next_command(tcon, &rqst[*num_rqst]);\n+\tif (i + k > 0)\n+\t\tsmb2_set_related(&rqst[*num_rqst]);\n+\t(*num_rqst)++;\n+}\n+\n+#define COMP_PID(cfile) ((cfile) ? (cfile)->fid.persistent_fid : COMPOUND_FID)\n+#define COMP_VID(cfile) ((cfile) ? (cfile)->fid.volatile_fid : COMPOUND_FID)\n+\n /*\n * note: If cfile is passed, the reference to it is dropped here.\n * So make sure that you do not reuse cfile after return from this func.\n@@ -284,32 +305,16 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t\trqst[num_rqst].rq_iov = &vars->qi_iov;\n \t\t\trqst[num_rqst].rq_nvec = 1;\n \n-\t\t\tif (cfile) {\n-\t\t\t\trc = SMB2_query_info_init(tcon, server,\n-\t\t\t\t\t\t\t &rqst[num_rqst],\n-\t\t\t\t\t\t\t cfile->fid.persistent_fid,\n-\t\t\t\t\t\t\t cfile->fid.volatile_fid,\n-\t\t\t\t\t\t\t FILE_ALL_INFORMATION,\n-\t\t\t\t\t\t\t SMB2_O_INFO_FILE, 0,\n-\t\t\t\t\t\t\t sizeof(struct smb2_file_all_info) +\n-\t\t\t\t\t\t\t PATH_MAX * 2, 0, NULL);\n-\t\t\t} else {\n-\t\t\t\trc = SMB2_query_info_init(tcon, server,\n-\t\t\t\t\t\t\t &rqst[num_rqst],\n-\t\t\t\t\t\t\t COMPOUND_FID,\n-\t\t\t\t\t\t\t COMPOUND_FID,\n-\t\t\t\t\t\t\t FILE_ALL_INFORMATION,\n-\t\t\t\t\t\t\t SMB2_O_INFO_FILE, 0,\n-\t\t\t\t\t\t\t sizeof(struct smb2_file_all_info) +\n-\t\t\t\t\t\t\t PATH_MAX * 2, 0, NULL);\n-\t\t\t}\n-\t\t\tif (!rc && (!cfile || num_rqst > 1)) {\n-\t\t\t\tsmb2_set_next_command(tcon, &rqst[num_rqst]);\n-\t\t\t\tsmb2_set_related(&rqst[num_rqst]);\n-\t\t\t} else if (rc) {\n+\t\t\trc = SMB2_query_info_init(tcon, server,\n+\t\t\t\t\t\t &rqst[num_rqst],\n+\t\t\t\t\t\t COMP_PID(cfile), COMP_VID(cfile),\n+\t\t\t\t\t\t FILE_ALL_INFORMATION,\n+\t\t\t\t\t\t SMB2_O_INFO_FILE, 0,\n+\t\t\t\t\t\t sizeof(struct smb2_file_all_info) +\n+\t\t\t\t\t\t PATH_MAX * 2, 0, NULL);\n+\t\t\tif (rc)\n \t\t\t\tgoto finished;\n-\t\t\t}\n-\t\t\tnum_rqst++;\n+\t\t\tset_next_compound(tcon, cfile, i, num_cmds, rqst, &num_rqst);\n \t\t\ttrace_smb3_query_info_compound_enter(xid, tcon->tid,\n \t\t\t\t\t\t\t ses->Suid, full_path);\n \t\t\tbreak;\n@@ -317,35 +322,18 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t\trqst[num_rqst].rq_iov = &vars->qi_iov;\n \t\t\trqst[num_rqst].rq_nvec = 1;\n \n-\t\t\tif (cfile) {\n-\t\t\t\t/* TBD: fix following to allow for longer SIDs */\n-\t\t\t\trc = SMB2_query_info_init(tcon, server,\n-\t\t\t\t\t\t\t &rqst[num_rqst],\n-\t\t\t\t\t\t\t cfile->fid.persistent_fid,\n-\t\t\t\t\t\t\t cfile->fid.volatile_fid,\n-\t\t\t\t\t\t\t SMB_FIND_FILE_POSIX_INFO,\n-\t\t\t\t\t\t\t SMB2_O_INFO_FILE, 0,\n-\t\t\t\t\t\t\t sizeof(struct smb311_posix_qinfo) +\n-\t\t\t\t\t\t\t (PATH_MAX * 2) +\n-\t\t\t\t\t\t\t (sizeof(struct smb_sid) * 2), 0, NULL);\n-\t\t\t} else {\n-\t\t\t\trc = SMB2_query_info_init(tcon, server,\n-\t\t\t\t\t\t\t &rqst[num_rqst],\n-\t\t\t\t\t\t\t COMPOUND_FID,\n-\t\t\t\t\t\t\t COMPOUND_FID,\n-\t\t\t\t\t\t\t SMB_FIND_FILE_POSIX_INFO,\n-\t\t\t\t\t\t\t SMB2_O_INFO_FILE, 0,\n-\t\t\t\t\t\t\t sizeof(struct smb311_posix_qinfo) +\n-\t\t\t\t\t\t\t (PATH_MAX * 2) +\n-\t\t\t\t\t\t\t (sizeof(struct smb_sid) * 2), 0, NULL);\n-\t\t\t}\n-\t\t\tif (!rc && (!cfile || num_rqst > 1)) {\n-\t\t\t\tsmb2_set_next_command(tcon, &rqst[num_rqst]);\n-\t\t\t\tsmb2_set_related(&rqst[num_rqst]);\n-\t\t\t} else if (rc) {\n+\t\t\t/* TBD: fix following to allow for longer SIDs */\n+\t\t\trc = SMB2_query_info_init(tcon, server,\n+\t\t\t\t\t\t &rqst[num_rqst],\n+\t\t\t\t\t\t COMP_PID(cfile), COMP_VID(cfile),\n+\t\t\t\t\t\t SMB_FIND_FILE_POSIX_INFO,\n+\t\t\t\t\t\t SMB2_O_INFO_FILE, 0,\n+\t\t\t\t\t\t sizeof(struct smb311_posix_qinfo) +\n+\t\t\t\t\t\t (PATH_MAX * 2) +\n+\t\t\t\t\t\t (sizeof(struct smb_sid) * 2), 0, NULL);\n+\t\t\tif (rc)\n \t\t\t\tgoto finished;\n-\t\t\t}\n-\t\t\tnum_rqst++;\n+\t\t\tset_next_compound(tcon, cfile, i, num_cmds, rqst, &num_rqst);\n \t\t\ttrace_smb3_posix_query_info_compound_enter(xid, tcon->tid,\n \t\t\t\t\t\t\t\t ses->Suid, full_path);\n \t\t\tbreak;\n@@ -363,32 +351,15 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t\tsize[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */\n \t\t\tdata[0] = &delete_pending[0];\n \n-\t\t\tif (cfile) {\n-\t\t\t\trc = SMB2_set_info_init(tcon, server,\n-\t\t\t\t\t\t\t&rqst[num_rqst],\n-\t\t\t\t\t\t\tcfile->fid.persistent_fid,\n-\t\t\t\t\t\t\tcfile->fid.volatile_fid,\n-\t\t\t\t\t\t\tcurrent->tgid,\n-\t\t\t\t\t\t\tFILE_DISPOSITION_INFORMATION,\n-\t\t\t\t\t\t\tSMB2_O_INFO_FILE, 0,\n-\t\t\t\t\t\t\tdata, size);\n-\t\t\t} else {\n-\t\t\t\trc = SMB2_set_info_init(tcon, server,\n-\t\t\t\t\t\t\t&rqst[num_rqst],\n-\t\t\t\t\t\t\tCOMPOUND_FID,\n-\t\t\t\t\t\t\tCOMPOUND_FID,\n-\t\t\t\t\t\t\tcurrent->tgid,\n-\t\t\t\t\t\t\tFILE_DISPOSITION_INFORMATION,\n-\t\t\t\t\t\t\tSMB2_O_INFO_FILE, 0,\n-\t\t\t\t\t\t\tdata, size);\n-\t\t\t}\n-\t\t\tif (!rc && (!cfile || num_rqst > 1)) {\n-\t\t\t\tsmb2_set_next_command(tcon, &rqst[num_rqst]);\n-\t\t\t\tsmb2_set_related(&rqst[num_rqst]);\n-\t\t\t} else if (rc) {\n+\t\t\trc = SMB2_set_info_init(tcon, server,\n+\t\t\t\t\t\t&rqst[num_rqst],\n+\t\t\t\t\t\tCOMP_PID(cfile), COMP_VID(cfile),\n+\t\t\t\t\t\tcurrent->tgid, FILE_DISPOSITION_INFORMATION,\n+\t\t\t\t\t\tSMB2_O_INFO_FILE, 0,\n+\t\t\t\t\t\tdata, size);\n+\t\t\tif (rc)\n \t\t\t\tgoto finished;\n-\t\t\t}\n-\t\t\tnum_rqst++;\n+\t\t\tset_next_compound(tcon, cfile, i, num_cmds, rqst, &num_rqst);\n \t\t\ttrace_smb3_unlink_enter(xid, tcon->tid, ses->Suid, full_path);\n \t\t\tbreak;\n \t\tcase SMB2_OP_SET_EOF:\n@@ -398,32 +369,15 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t\tsize[0] = in_iov[i].iov_len;\n \t\t\tdata[0] = in_iov[i].iov_base;\n \n-\t\t\tif (cfile) {\n-\t\t\t\trc = SMB2_set_info_init(tcon, server,\n-\t\t\t\t\t\t\t&rqst[num_rqst],\n-\t\t\t\t\t\t\tcfile->fid.persistent_fid,\n-\t\t\t\t\t\t\tcfile->fid.volatile_fid,\n-\t\t\t\t\t\t\tcurrent->tgid,\n-\t\t\t\t\t\t\tFILE_END_OF_FILE_INFORMATION,\n-\t\t\t\t\t\t\tSMB2_O_INFO_FILE, 0,\n-\t\t\t\t\t\t\tdata, size);\n-\t\t\t} else {\n-\t\t\t\trc = SMB2_set_info_init(tcon, server,\n-\t\t\t\t\t\t\t&rqst[num_rqst],\n-\t\t\t\t\t\t\tCOMPOUND_FID,\n-\t\t\t\t\t\t\tCOMPOUND_FID,\n-\t\t\t\t\t\t\tcurrent->tgid,\n-\t\t\t\t\t\t\tFILE_END_OF_FILE_INFORMATION,\n-\t\t\t\t\t\t\tSMB2_O_INFO_FILE, 0,\n-\t\t\t\t\t\t\tdata, size);\n-\t\t\t}\n-\t\t\tif (!rc && (!cfile || num_rqst > 1)) {\n-\t\t\t\tsmb2_set_next_command(tcon, &rqst[num_rqst]);\n-\t\t\t\tsmb2_set_related(&rqst[num_rqst]);\n-\t\t\t} else if (rc) {\n+\t\t\trc = SMB2_set_info_init(tcon, server,\n+\t\t\t\t\t\t&rqst[num_rqst],\n+\t\t\t\t\t\tCOMP_PID(cfile), COMP_VID(cfile),\n+\t\t\t\t\t\tcurrent->tgid, FILE_END_OF_FILE_INFORMATION,\n+\t\t\t\t\t\tSMB2_O_INFO_FILE, 0,\n+\t\t\t\t\t\tdata, size);\n+\t\t\tif (rc)\n \t\t\t\tgoto finished;\n-\t\t\t}\n-\t\t\tnum_rqst++;\n+\t\t\tset_next_compound(tcon, cfile, i, num_cmds, rqst, &num_rqst);\n \t\t\ttrace_smb3_set_eof_enter(xid, tcon->tid, ses->Suid, full_path);\n \t\t\tbreak;\n \t\tcase SMB2_OP_SET_INFO:\n@@ -433,28 +387,14 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t\tsize[0] = in_iov[i].iov_len;\n \t\t\tdata[0] = in_iov[i].iov_base;\n \n-\t\t\tif (cfile) {\n-\t\t\t\trc = SMB2_set_info_init(tcon, server,\n-\t\t\t\t\t\t\t&rqst[num_rqst],\n-\t\t\t\t\t\t\tcfile->fid.persistent_fid,\n-\t\t\t\t\t\t\tcfile->fid.volatile_fid, current->tgid,\n-\t\t\t\t\t\t\tFILE_BASIC_INFORMATION,\n-\t\t\t\t\t\t\tSMB2_O_INFO_FILE, 0, data, size);\n-\t\t\t} else {\n-\t\t\t\trc = SMB2_set_info_init(tcon, server,\n-\t\t\t\t\t\t\t&rqst[num_rqst],\n-\t\t\t\t\t\t\tCOMPOUND_FID,\n-\t\t\t\t\t\t\tCOMPOUND_FID, current->tgid,\n-\t\t\t\t\t\t\tFILE_BASIC_INFORMATION,\n-\t\t\t\t\t\t\tSMB2_O_INFO_FILE, 0, data, size);\n-\t\t\t}\n-\t\t\tif (!rc && (!cfile || num_rqst > 1)) {\n-\t\t\t\tsmb2_set_next_command(tcon, &rqst[num_rqst]);\n-\t\t\t\tsmb2_set_related(&rqst[num_rqst]);\n-\t\t\t} else if (rc) {\n+\t\t\trc = SMB2_set_info_init(tcon, server,\n+\t\t\t\t\t\t&rqst[num_rqst],\n+\t\t\t\t\t\tCOMP_PID(cfile), COMP_VID(cfile),\n+\t\t\t\t\t\tcurrent->tgid, FILE_BASIC_INFORMATION,\n+\t\t\t\t\t\tSMB2_O_INFO_FILE, 0, data, size);\n+\t\t\tif (rc)\n \t\t\t\tgoto finished;\n-\t\t\t}\n-\t\t\tnum_rqst++;\n+\t\t\tset_next_compound(tcon, cfile, i, num_cmds, rqst, &num_rqst);\n \t\t\ttrace_smb3_set_info_compound_enter(xid, tcon->tid,\n \t\t\t\t\t\t\t ses->Suid, full_path);\n \t\t\tbreak;\n@@ -474,31 +414,19 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t\tsize[1] = len + 2 /* null */;\n \t\t\tdata[1] = in_iov[i].iov_base;\n \n-\t\t\tif (cfile) {\n-\t\t\t\trc = SMB2_set_info_init(tcon, server,\n-\t\t\t\t\t\t\t&rqst[num_rqst],\n-\t\t\t\t\t\t\tcfile->fid.persistent_fid,\n-\t\t\t\t\t\t\tcfile->fid.volatile_fid,\n-\t\t\t\t\t\t\tcurrent->tgid, FILE_RENAME_INFORMATION,\n-\t\t\t\t\t\t\tSMB2_O_INFO_FILE, 0, data, size);\n-\t\t\t} else {\n-\t\t\t\trc = SMB2_set_info_init(tcon, server,\n-\t\t\t\t\t\t\t&rqst[num_rqst],\n-\t\t\t\t\t\t\tCOMPOUND_FID, COMPOUND_FID,\n-\t\t\t\t\t\t\tcurrent->tgid, FILE_RENAME_INFORMATION,\n-\t\t\t\t\t\t\tSMB2_O_INFO_FILE, 0, data, size);\n-\t\t\t}\n-\t\t\tif (!rc && (!cfile || num_rqst > 1)) {\n-\t\t\t\tsmb2_set_next_command(tcon, &rqst[num_rqst]);\n-\t\t\t\tsmb2_set_related(&rqst[num_rqst]);\n-\t\t\t} else if (rc) {\n+\t\t\trc = SMB2_set_info_init(tcon, server,\n+\t\t\t\t\t\t&rqst[num_rqst],\n+\t\t\t\t\t\tCOMP_PID(cfile), COMP_VID(cfile),\n+\t\t\t\t\t\tcurrent->tgid, FILE_RENAME_INFORMATION,\n+\t\t\t\t\t\tSMB2_O_INFO_FILE, 0, data, size);\n+\n+\t\t\tif (rc)\n \t\t\t\tgoto finished;\n-\t\t\t}\n-\t\t\tnum_rqst++;\n+\t\t\tset_next_compound(tcon, cfile, i, num_cmds, rqst, &num_rqst);\n \t\t\ttrace_smb3_rename_enter(xid, tcon->tid, ses->Suid, full_path);\n \t\t\tbreak;\n \t\tcase SMB2_OP_HARDLINK:\n-\t\t\trqst[num_rqst].rq_iov = &vars->si_iov[0];\n+\t\t\trqst[num_rqst].rq_iov = vars->hl_iov;\n \t\t\trqst[num_rqst].rq_nvec = 2;\n \n \t\t\tlen = in_iov[i].iov_len;\n@@ -514,41 +442,27 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t\tdata[1] = in_iov[i].iov_base;\n \n \t\t\trc = SMB2_set_info_init(tcon, server,\n-\t\t\t\t\t\t&rqst[num_rqst], COMPOUND_FID,\n-\t\t\t\t\t\tCOMPOUND_FID, current->tgid,\n-\t\t\t\t\t\tFILE_LINK_INFORMATION,\n+\t\t\t\t\t\t&rqst[num_rqst],\n+\t\t\t\t\t\tCOMP_PID(cfile), COMP_VID(cfile),\n+\t\t\t\t\t\tcurrent->tgid, FILE_LINK_INFORMATION,\n \t\t\t\t\t\tSMB2_O_INFO_FILE, 0, data, size);\n \t\t\tif (rc)\n \t\t\t\tgoto finished;\n-\t\t\tsmb2_set_next_command(tcon, &rqst[num_rqst]);\n-\t\t\tsmb2_set_related(&rqst[num_rqst++]);\n+\t\t\tset_next_compound(tcon, cfile, i, num_cmds, rqst, &num_rqst);\n \t\t\ttrace_smb3_hardlink_enter(xid, tcon->tid, ses->Suid, full_path);\n \t\t\tbreak;\n \t\tcase SMB2_OP_SET_REPARSE:\n \t\t\trqst[num_rqst].rq_iov = vars->io_iov;\n \t\t\trqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);\n \n-\t\t\tif (cfile) {\n-\t\t\t\trc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],\n-\t\t\t\t\t\t cfile->fid.persistent_fid,\n-\t\t\t\t\t\t cfile->fid.volatile_fid,\n-\t\t\t\t\t\t FSCTL_SET_REPARSE_POINT,\n-\t\t\t\t\t\t in_iov[i].iov_base,\n-\t\t\t\t\t\t in_iov[i].iov_len, 0);\n-\t\t\t} else {\n-\t\t\t\trc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],\n-\t\t\t\t\t\t COMPOUND_FID, COMPOUND_FID,\n-\t\t\t\t\t\t FSCTL_SET_REPARSE_POINT,\n-\t\t\t\t\t\t in_iov[i].iov_base,\n-\t\t\t\t\t\t in_iov[i].iov_len, 0);\n-\t\t\t}\n-\t\t\tif (!rc && (!cfile || num_rqst > 1)) {\n-\t\t\t\tsmb2_set_next_command(tcon, &rqst[num_rqst]);\n-\t\t\t\tsmb2_set_related(&rqst[num_rqst]);\n-\t\t\t} else if (rc) {\n+\t\t\trc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],\n+\t\t\t\t\t COMP_PID(cfile), COMP_VID(cfile),\n+\t\t\t\t\t FSCTL_SET_REPARSE_POINT,\n+\t\t\t\t\t in_iov[i].iov_base,\n+\t\t\t\t\t in_iov[i].iov_len, 0);\n+\t\t\tif (rc)\n \t\t\t\tgoto finished;\n-\t\t\t}\n-\t\t\tnum_rqst++;\n+\t\t\tset_next_compound(tcon, cfile, i, num_cmds, rqst, &num_rqst);\n \t\t\ttrace_smb3_set_reparse_compound_enter(xid, tcon->tid,\n \t\t\t\t\t\t\t ses->Suid, full_path);\n \t\t\tbreak;\n@@ -556,25 +470,13 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t\trqst[num_rqst].rq_iov = vars->io_iov;\n \t\t\trqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov);\n \n-\t\t\tif (cfile) {\n-\t\t\t\trc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],\n-\t\t\t\t\t\t cfile->fid.persistent_fid,\n-\t\t\t\t\t\t cfile->fid.volatile_fid,\n-\t\t\t\t\t\t FSCTL_GET_REPARSE_POINT,\n-\t\t\t\t\t\t NULL, 0, CIFSMaxBufSize);\n-\t\t\t} else {\n-\t\t\t\trc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],\n-\t\t\t\t\t\t COMPOUND_FID, COMPOUND_FID,\n-\t\t\t\t\t\t FSCTL_GET_REPARSE_POINT,\n-\t\t\t\t\t\t NULL, 0, CIFSMaxBufSize);\n-\t\t\t}\n-\t\t\tif (!rc && (!cfile || num_rqst > 1)) {\n-\t\t\t\tsmb2_set_next_command(tcon, &rqst[num_rqst]);\n-\t\t\t\tsmb2_set_related(&rqst[num_rqst]);\n-\t\t\t} else if (rc) {\n+\t\t\trc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst],\n+\t\t\t\t\t COMP_PID(cfile), COMP_VID(cfile),\n+\t\t\t\t\t FSCTL_GET_REPARSE_POINT,\n+\t\t\t\t\t NULL, 0, CIFSMaxBufSize);\n+\t\t\tif (rc)\n \t\t\t\tgoto finished;\n-\t\t\t}\n-\t\t\tnum_rqst++;\n+\t\t\tset_next_compound(tcon, cfile, i, num_cmds, rqst, &num_rqst);\n \t\t\ttrace_smb3_get_reparse_compound_enter(xid, tcon->tid,\n \t\t\t\t\t\t\t ses->Suid, full_path);\n \t\t\tbreak;\n@@ -582,34 +484,17 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t\trqst[num_rqst].rq_iov = &vars->ea_iov;\n \t\t\trqst[num_rqst].rq_nvec = 1;\n \n-\t\t\tif (cfile) {\n-\t\t\t\trc = SMB2_query_info_init(tcon, server,\n-\t\t\t\t\t\t\t &rqst[num_rqst],\n-\t\t\t\t\t\t\t cfile->fid.persistent_fid,\n-\t\t\t\t\t\t\t cfile->fid.volatile_fid,\n-\t\t\t\t\t\t\t FILE_FULL_EA_INFORMATION,\n-\t\t\t\t\t\t\t SMB2_O_INFO_FILE, 0,\n-\t\t\t\t\t\t\t SMB2_WSL_MAX_QUERY_EA_RESP_SIZE,\n-\t\t\t\t\t\t\t sizeof(wsl_query_eas),\n-\t\t\t\t\t\t\t (void *)wsl_query_eas);\n-\t\t\t} else {\n-\t\t\t\trc = SMB2_query_info_init(tcon, server,\n-\t\t\t\t\t\t\t &rqst[num_rqst],\n-\t\t\t\t\t\t\t COMPOUND_FID,\n-\t\t\t\t\t\t\t COMPOUND_FID,\n-\t\t\t\t\t\t\t FILE_FULL_EA_INFORMATION,\n-\t\t\t\t\t\t\t SMB2_O_INFO_FILE, 0,\n-\t\t\t\t\t\t\t SMB2_WSL_MAX_QUERY_EA_RESP_SIZE,\n-\t\t\t\t\t\t\t sizeof(wsl_query_eas),\n-\t\t\t\t\t\t\t (void *)wsl_query_eas);\n-\t\t\t}\n-\t\t\tif (!rc && (!cfile || num_rqst > 1)) {\n-\t\t\t\tsmb2_set_next_command(tcon, &rqst[num_rqst]);\n-\t\t\t\tsmb2_set_related(&rqst[num_rqst]);\n-\t\t\t} else if (rc) {\n+\t\t\trc = SMB2_query_info_init(tcon, server,\n+\t\t\t\t\t\t &rqst[num_rqst],\n+\t\t\t\t\t\t COMP_PID(cfile), COMP_VID(cfile),\n+\t\t\t\t\t\t FILE_FULL_EA_INFORMATION,\n+\t\t\t\t\t\t SMB2_O_INFO_FILE, 0,\n+\t\t\t\t\t\t SMB2_WSL_MAX_QUERY_EA_RESP_SIZE,\n+\t\t\t\t\t\t sizeof(wsl_query_eas),\n+\t\t\t\t\t\t (void *)wsl_query_eas);\n+\t\t\tif (rc)\n \t\t\t\tgoto finished;\n-\t\t\t}\n-\t\t\tnum_rqst++;\n+\t\t\tset_next_compound(tcon, cfile, i, num_cmds, rqst, &num_rqst);\n \t\t\ttrace_smb3_query_wsl_ea_compound_enter(xid, tcon->tid,\n \t\t\t\t\t\t\t ses->Suid, full_path);\n \t\t\tbreak;\n@@ -1156,7 +1041,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,\n \tcifs_i = CIFS_I(inode);\n \tdosattrs = cifs_i->cifsAttrs | ATTR_READONLY;\n \tdata.Attributes = cpu_to_le32(dosattrs);\n-\tcifs_get_writable_path(tcon, name, FIND_ANY, &cfile);\n+\tcifs_get_writable_path(tcon, name, inode, FIND_ANY, &cfile);\n \toparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,\n \t\t\t FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE);\n \ttmprc = smb2_compound_op(xid, tcon, cifs_sb, name,\n@@ -1332,17 +1217,20 @@ int smb2_rename_path(const unsigned int xid,\n \t\t const char *from_name, const char *to_name,\n \t\t struct cifs_sb_info *cifs_sb)\n {\n+\tstruct inode *inode = source_dentry ? d_inode(source_dentry) : NULL;\n \tstruct cifsFileInfo *cfile;\n \t__u32 co = file_create_options(source_dentry);\n \n \tdrop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);\n-\tcifs_get_writable_path(tcon, from_name, FIND_WITH_DELETE, &cfile);\n+\tcifs_get_writable_path(tcon, from_name, inode,\n+\t\t\t FIND_WITH_DELETE, &cfile);\n \n \tint rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,\n \t\t\t\t co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);\n \tif (rc == -EINVAL) {\n \t\tcifs_dbg(FYI, \"invalid lease key, resending request without lease\");\n-\t\tcifs_get_writable_path(tcon, from_name, FIND_WITH_DELETE, &cfile);\n+\t\tcifs_get_writable_path(tcon, from_name, inode,\n+\t\t\t\t FIND_WITH_DELETE, &cfile);\n \t\trc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,\n \t\t\t\t co, DELETE, SMB2_OP_RENAME, cfile, NULL);\n \t}\n@@ -1355,11 +1243,35 @@ int smb2_create_hardlink(const unsigned int xid,\n \t\t\t const char *from_name, const char *to_name,\n \t\t\t struct cifs_sb_info *cifs_sb)\n {\n+\tstruct inode *inode = source_dentry ? d_inode(source_dentry) : NULL;\n \t__u32 co = file_create_options(source_dentry);\n+\tstruct cifsFileInfo *cfile;\n \n+\tif (inode) {\n+\t\tstruct cifsInodeInfo *cinode = CIFS_I(inode);\n+\t\tFILE_BASIC_INFO fi;\n+\t\t__u32 attrs;\n+\t\tint rc;\n+\n+\t\tscoped_guard(spinlock, &cinode->open_file_lock) {\n+\t\t\tif (!test_bit(CIFS_INO_TMPFILE, &CIFS_I(inode)->flags))\n+\t\t\t\tgoto no_tmpfile;\n+\t\t\tattrs = cinode->cifsAttrs;\n+\t\t}\n+\t\tfi = (FILE_BASIC_INFO) {\n+\t\t\t.Attributes = cpu_to_le32(attrs & ~ATTR_HIDDEN),\n+\t\t};\n+\t\trc = smb2_set_file_info(inode, from_name, &fi, xid);\n+\t\tif (rc)\n+\t\t\treturn rc;\n+\t}\n+\n+no_tmpfile:\n+\tcifs_get_writable_path(tcon, from_name, inode,\n+\t\t\t FIND_WITH_DELETE, &cfile);\n \treturn smb2_set_path_attr(xid, tcon, from_name, to_name,\n \t\t\t\t cifs_sb, co, FILE_READ_ATTRIBUTES,\n-\t\t\t\t SMB2_OP_HARDLINK, NULL, NULL);\n+\t\t\t\t SMB2_OP_HARDLINK, cfile, NULL);\n }\n \n int\n@@ -1368,15 +1280,16 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t struct cifs_sb_info *cifs_sb, bool set_alloc,\n \t\t struct dentry *dentry)\n {\n-\tstruct cifs_open_parms oparms;\n-\tstruct cifsFileInfo *cfile;\n-\tstruct kvec in_iov;\n+\tstruct inode *inode = dentry ? d_inode(dentry) : NULL;\n \t__le64 eof = cpu_to_le64(size);\n+\tstruct cifs_open_parms oparms;\n+\tstruct cifsFileInfo *cfile;\n+\tstruct kvec in_iov;\n \tint rc;\n \n \tin_iov.iov_base = &eof;\n \tin_iov.iov_len = sizeof(eof);\n-\tcifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);\n+\tcifs_get_writable_path(tcon, full_path, inode, FIND_ANY, &cfile);\n \n \toparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA,\n \t\t\t FILE_OPEN, 0, ACL_NO_MODE);\n@@ -1386,7 +1299,8 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,\n \t\t\t cfile, NULL, NULL, dentry);\n \tif (rc == -EINVAL) {\n \t\tcifs_dbg(FYI, \"invalid lease key, resending request without lease\");\n-\t\tcifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);\n+\t\tcifs_get_writable_path(tcon, full_path,\n+\t\t\t\t inode, FIND_ANY, &cfile);\n \t\trc = smb2_compound_op(xid, tcon, cifs_sb,\n \t\t\t\t full_path, &oparms, &in_iov,\n \t\t\t\t &(int){SMB2_OP_SET_EOF}, 1,\n@@ -1416,7 +1330,8 @@ smb2_set_file_info(struct inode *inode, const char *full_path,\n \t (buf->LastWriteTime == 0) && (buf->ChangeTime == 0)) {\n \t\tif (buf->Attributes == 0)\n \t\t\tgoto out; /* would be a no op, no sense sending this */\n-\t\tcifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);\n+\t\tcifs_get_writable_path(tcon, full_path,\n+\t\t\t\t inode, FIND_ANY, &cfile);\n \t}\n \n \toparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES,\n@@ -1475,7 +1390,7 @@ struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,\n \n \tif (tcon->posix_extensions) {\n \t\tcmds[1] = SMB2_OP_POSIX_QUERY_INFO;\n-\t\tcifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);\n+\t\tcifs_get_writable_path(tcon, full_path, NULL, FIND_ANY, &cfile);\n \t\trc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,\n \t\t\t\t in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);\n \t\tif (!rc) {\n@@ -1484,7 +1399,7 @@ struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,\n \t\t}\n \t} else {\n \t\tcmds[1] = SMB2_OP_QUERY_INFO;\n-\t\tcifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);\n+\t\tcifs_get_writable_path(tcon, full_path, NULL, FIND_ANY, &cfile);\n \t\trc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,\n \t\t\t\t in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);\n \t\tif (!rc) {\n@@ -1566,8 +1481,8 @@ int smb2_rename_pending_delete(const char *full_path,\n \t\t\t struct dentry *dentry,\n \t\t\t const unsigned int xid)\n {\n-\tstruct cifs_sb_info *cifs_sb = CIFS_SB(d_inode(dentry)->i_sb);\n \tstruct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry));\n+\tstruct cifs_sb_info *cifs_sb = CIFS_SB(dentry);\n \t__le16 *utf16_path __free(kfree) = NULL;\n \t__u32 co = file_create_options(dentry);\n \tint cmds[] = {\n@@ -1579,14 +1494,10 @@ int smb2_rename_pending_delete(const char *full_path,\n \tchar *to_name __free(kfree) = NULL;\n \t__u32 attrs = cinode->cifsAttrs;\n \tstruct cifs_open_parms oparms;\n-\tstatic atomic_t sillycounter;\n \tstruct cifsFileInfo *cfile;\n \tstruct tcon_link *tlink;\n \tstruct cifs_tcon *tcon;\n \tstruct kvec iov[2];\n-\tconst char *ppath;\n-\tvoid *page;\n-\tsize_t len;\n \tint rc;\n \n \ttlink = cifs_sb_tlink(cifs_sb);\n@@ -1594,25 +1505,14 @@ int smb2_rename_pending_delete(const char *full_path,\n \t\treturn PTR_ERR(tlink);\n \ttcon = tlink_tcon(tlink);\n \n-\tpage = alloc_dentry_path();\n-\n-\tppath = build_path_from_dentry(dentry->d_parent, page);\n-\tif (IS_ERR(ppath)) {\n-\t\trc = PTR_ERR(ppath);\n+\tto_name = cifs_silly_fullpath(dentry);\n+\tif (IS_ERR(to_name)) {\n+\t\trc = PTR_ERR(to_name);\n+\t\tto_name = NULL;\n \t\tgoto out;\n \t}\n \n-\tlen = strlen(ppath) + strlen(\"/.__smb1234\") + 1;\n-\tto_name = kmalloc(len, GFP_KERNEL);\n-\tif (!to_name) {\n-\t\trc = -ENOMEM;\n-\t\tgoto out;\n-\t}\n-\n-\tscnprintf(to_name, len, \"%s%c.__smb%04X\", ppath, CIFS_DIR_SEP(cifs_sb),\n-\t\t atomic_inc_return(&sillycounter) & 0xffff);\n-\n-\tutf16_path = utf16_smb2_path(cifs_sb, to_name, len);\n+\tutf16_path = utf16_smb2_path(cifs_sb, to_name, strlen(to_name));\n \tif (!utf16_path) {\n \t\trc = -ENOMEM;\n \t\tgoto out;\n@@ -1635,12 +1535,14 @@ int smb2_rename_pending_delete(const char *full_path,\n \tiov[1].iov_base = utf16_path;\n \tiov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path);\n \n-\tcifs_get_writable_path(tcon, full_path, FIND_WITH_DELETE, &cfile);\n+\tcifs_get_writable_path(tcon, full_path, d_inode(dentry),\n+\t\t\t FIND_WITH_DELETE, &cfile);\n \trc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov,\n \t\t\t cmds, num_cmds, cfile, NULL, NULL, dentry);\n \tif (rc == -EINVAL) {\n \t\tcifs_dbg(FYI, \"invalid lease key, resending request without lease\\n\");\n-\t\tcifs_get_writable_path(tcon, full_path, FIND_WITH_DELETE, &cfile);\n+\t\tcifs_get_writable_path(tcon, full_path, d_inode(dentry),\n+\t\t\t\t FIND_WITH_DELETE, &cfile);\n \t\trc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov,\n \t\t\t\t cmds, num_cmds, cfile, NULL, NULL, NULL);\n \t}\n@@ -1653,6 +1555,5 @@ int smb2_rename_pending_delete(const char *full_path,\n \t}\n out:\n \tcifs_put_tlink(tlink);\n-\tfree_dentry_path(page);\n \treturn rc;\n }\n", "prefixes": [ "RFC" ] }