Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2217924/?format=api
{ "id": 2217924, "url": "http://patchwork.ozlabs.org/api/patches/2217924/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/patch/20260331010836.1397616-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": "<20260331010836.1397616-1-pc@manguebit.org>", "list_archive_url": null, "date": "2026-03-31T01:08:36", "name": "smb: client: add support for O_TMPFILE", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "c3b456e56af23fbe7c7ecfcee245beae8f6cd8d6", "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/20260331010836.1397616-1-pc@manguebit.org/mbox/", "series": [ { "id": 498115, "url": "http://patchwork.ozlabs.org/api/series/498115/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-cifs-client/list/?series=498115", "date": "2026-03-31T01:08:36", "name": "smb: client: add support for O_TMPFILE", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/498115/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2217924/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2217924/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-cifs+bounces-10587-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=lE/G1Asl;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.234.253.10; helo=sea.lore.kernel.org;\n envelope-from=linux-cifs+bounces-10587-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=\"lE/G1Asl\"", "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 [172.234.253.10])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fl97C48CLz1yGH\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 12:11:35 +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 A17C030048C9\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 01:08:50 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 6DA6940DFC6;\n\tTue, 31 Mar 2026 01:08:49 +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 320C740DFB9;\n\tTue, 31 Mar 2026 01:08:45 +0000 (UTC)", "from pc by mx1.manguebit.org with local (Exim 4.99.1)\n\tid 1w7Nau-00000001vQ1-3RZS;\n\tMon, 30 Mar 2026 22:08:36 -0300" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774919329; cv=none;\n b=cN+rd645OYJpHr2DAZYZ2hP1X1/px0TlzTMHRJNktL2pxAV+Aru1tJg9amFcH0WZ+9mg8y6bkbeTEQMbEVQJLiohfNdCDuZD1hQAqa7YFvm4jTLl7DFFqCYbnq7W8tQQ21drNHTxz8ZIVGpDjM3hlFsZAMUdQfDNz73BGTcQoow=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774919329; c=relaxed/simple;\n\tbh=1+rliyUDsoLF2Y7E6JRPapneCTxo+HzPePpwuqmD/CE=;\n\th=From:To:Cc:Subject:Date:Message-ID:MIME-Version;\n b=KYMmgQocJEBHRtw3vCKgCbxKfvjfIWH19r5Wp3mqPJ0rVQAZocw2jb+2mG2iLsbvaie3zw8RdEycrd1hTlRd+ktNztBisd4irxpoeoSQbdvQ5PvkpRzGW5GeGgJ5YRakdXFDJjsctbrdcJO6dz1txYJLq0DWAtXI1MRYpeLaz48=", "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=lE/G1Asl; 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=6t0am4ulTFKjcvXWFOBnNOkHwLBIpUEmxwdYhRPBL9w=; b=lE/G1Aslvc8VwrJc8DcoyFijNx\n\t+zOR/EMNWgzJWw/GA1c5y9my8umhzKuROA7EF2R3KLTNPqVekA3YxIrjbZcydIS/Vf3eKGWx6KkXg\n\tyuM7xC+sii7gh2IJKOwJLRv/kSUhqdvTfpzBgprI7kMrM9l/baCMiKFo8pLFjmFzaPFH/8QeAbi8A\n\tlF68YnpmTldB1+xxp6sEe6RH+Bi5H3ijRT0xO5L3nNwgobwNRWh/P0eN2hcGSlyJo7/sVEecyeX/B\n\trgjYbo2X4n5OUMZY2P0BTFcOywAj7tNTtoVlRJhY4BbkN1b5oX3v8SNl2/usl0cYLJUC3hO4f5/vM\n\tqbQEYnFA==;", "From": "Paulo Alcantara <pc@manguebit.org>", "To": "smfrench@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": "[PATCH] smb: client: add support for O_TMPFILE", "Date": "Mon, 30 Mar 2026 22:08:36 -0300", "Message-ID": "<20260331010836.1397616-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---\n fs/smb/client/cached_dir.c | 3 +\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/cifssmb.c | 3 +\n fs/smb/client/dir.c | 279 +++++++++++++++++++++----\n fs/smb/client/file.c | 29 ++-\n fs/smb/client/inode.c | 3 +-\n fs/smb/client/link.c | 18 +-\n fs/smb/client/smb2inode.c | 404 ++++++++++++++-----------------------\n 11 files changed, 480 insertions(+), 308 deletions(-)", "diff": "diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c\nindex 04bb95091f49..fee16d50e996 100644\n--- a/fs/smb/client/cached_dir.c\n+++ b/fs/smb/client/cached_dir.c\n@@ -477,6 +477,9 @@ void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon,\n \tstruct cached_fid *cfid = NULL;\n \tint rc;\n \n+\tif (!name)\n+\t\treturn;\n+\n \trc = open_cached_dir(xid, tcon, name, cifs_sb, true, &cfid);\n \tif (rc) {\n \t\tcifs_dbg(FYI, \"no cached dir found for rmdir(%s)\\n\", name);\ndiff --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..d82ab7ce1064 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_filename(struct dentry *dentry);\n+char *cifs_tmpfile_name(struct dentry *dentry);\n+\n+#define CIFS_TMPFILE_PREFIX\t\t\"%c.smb%04X__\"\n+#define CIFS_TMPFILE_PREFIX_LEN\tsizeof(\".smb1234__\")\n+\n+#define CIFS_SILLY_FILENAME_SUFFIX\t\"silly\"\n+#define CIFS_SILLY_FILENAME_SIZE \\\n+\t(CIFS_TMPFILE_PREFIX_LEN + sizeof(CIFS_SILLY_FILENAME_SUFFIX))\n+\n+#define CIFS_TMP_FILENAME_SUFFIX\t\"tmp\"\n+#define CIFS_TMP_FILENAME_SIZE \\\n+\t(CIFS_TMPFILE_PREFIX_LEN + sizeof(CIFS_TMP_FILENAME_SUFFIX))\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..2a6af454095c 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 = 0,\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/cifssmb.c b/fs/smb/client/cifssmb.c\nindex 3990a9012264..0bffb6b9dce8 100644\n--- a/fs/smb/client/cifssmb.c\n+++ b/fs/smb/client/cifssmb.c\n@@ -2715,6 +2715,9 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,\n \n \tcifs_dbg(FYI, \"In Create Hard link Unix style\\n\");\n createHardLinkRetry:\n+\tif (!fromName)\n+\t\treturn -EBADF;\n+\n \trc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,\n \t\t (void **) &pSMBr);\n \tif (rc < 0)\ndiff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c\nindex 6d2378eeb7f6..c107c25d0709 100644\n--- a/fs/smb/client/dir.c\n+++ b/fs/smb/client/dir.c\n@@ -175,17 +175,17 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon)\n \n /* Inode operations in similar order to how they appear in Linux file fs.h */\n \n-static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,\n-\t\t\t struct tcon_link *tlink, unsigned int oflags, umode_t mode, __u32 *oplock,\n-\t\t\t struct cifs_fid *fid, struct cifs_open_info_data *buf)\n+static int __cifs_do_create(struct file *file, struct inode *inode,\n+\t\t\t struct dentry *direntry, const char *full_path,\n+\t\t\t unsigned int xid, struct tcon_link *tlink,\n+\t\t\t unsigned int oflags, umode_t mode, __u32 *oplock,\n+\t\t\t struct cifs_fid *fid, struct cifs_open_info_data *buf)\n {\n \tint rc = -ENOENT;\n \tint create_options = CREATE_NOT_DIR;\n \tint desired_access;\n \tstruct cifs_sb_info *cifs_sb = CIFS_SB(inode);\n \tstruct cifs_tcon *tcon = tlink_tcon(tlink);\n-\tconst char *full_path;\n-\tvoid *page = alloc_dentry_path();\n \tstruct inode *newinode = NULL;\n \tunsigned int sbflags = cifs_sb_flags(cifs_sb);\n \tint disposition;\n@@ -199,11 +199,6 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \tif (tcon->ses->server->oplocks)\n \t\t*oplock = REQ_OPLOCK;\n \n-\tfull_path = build_path_from_dentry(direntry, page);\n-\tif (IS_ERR(full_path)) {\n-\t\trc = PTR_ERR(full_path);\n-\t\tgoto out;\n-\t}\n \n \t/* If we're caching, we need to be able to fill in around partial writes. */\n \tif (cifs_fscache_enabled(inode) && (oflags & O_ACCMODE) == O_WRONLY)\n@@ -225,8 +220,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \t\t\tif (S_ISDIR(newinode->i_mode)) {\n \t\t\t\tCIFSSMBClose(xid, tcon, fid->netfid);\n \t\t\t\tiput(newinode);\n-\t\t\t\trc = -EISDIR;\n-\t\t\t\tgoto out;\n+\t\t\t\treturn -EISDIR;\n \t\t\t}\n \n \t\t\tif (!S_ISREG(newinode->i_mode)) {\n@@ -269,7 +263,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \t\t\tbreak;\n \n \t\tdefault:\n-\t\t\tgoto out;\n+\t\t\treturn rc;\n \t\t}\n \t\t/*\n \t\t * fallthrough to retry, using older open call, this is case\n@@ -287,26 +281,30 @@ 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 \t * ACLs\n \t */\n \n-\tif (!server->ops->open) {\n-\t\trc = -ENOSYS;\n-\t\tgoto out;\n-\t}\n+\tif (!server->ops->open)\n+\t\treturn -EOPNOTSUPP;\n \n \tcreate_options |= cifs_open_create_options(oflags, create_options);\n \t/*\n@@ -358,7 +356,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \t\t\trdwr_for_fscache = 2;\n \t\t\tgoto retry_open;\n \t\t}\n-\t\tgoto out;\n+\t\treturn rc;\n \t}\n \tif (rdwr_for_fscache == 2)\n \t\tcifs_invalidate_cache(inode, FSCACHE_INVAL_DIO_WRITE);\n@@ -436,17 +434,19 @@ 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-out:\n-\tfree_dentry_path(page);\n+\tinode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));\n+\tif (oflags & O_TMPFILE) {\n+\t\tset_nlink(newinode, 1);\n+\t\td_tmpfile(file, newinode);\n+\t} else {\n+\t\td_add(direntry, newinode);\n+\t}\n \treturn rc;\n \n out_err:\n@@ -454,7 +454,49 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned\n \t\tserver->ops->close(xid, tcon, fid);\n \tif (newinode)\n \t\tiput(newinode);\n-\tgoto out;\n+\treturn rc;\n+}\n+\n+static int create_tmpfile(struct inode *inode, struct file *file,\n+\t\t\t unsigned int xid, struct tcon_link *tlink,\n+\t\t\t umode_t mode, __u32 *oplock, struct cifs_fid *fid)\n+{\n+\tstruct dentry *dentry = file->f_path.dentry;\n+\tchar *path __free(kfree) = NULL;\n+\tint rc;\n+\n+\tpath = cifs_tmpfile_name(dentry);\n+\tif (IS_ERR(path)) {\n+\t\trc = PTR_ERR(path);\n+\t\tpath = NULL;\n+\t\treturn rc;\n+\t}\n+\n+\treturn __cifs_do_create(file, inode, dentry, path, xid, tlink,\n+\t\t\t\tfile->f_flags, mode, oplock, fid, NULL);\n+}\n+\n+static int create_file(struct inode *inode, struct dentry *direntry,\n+\t\t unsigned int xid, struct tcon_link *tlink,\n+\t\t unsigned int oflags, umode_t mode,\n+\t\t __u32 *oplock, struct cifs_fid *fid,\n+\t\t struct cifs_open_info_data *buf)\n+{\n+\tvoid *page = alloc_dentry_path();\n+\tconst char *path;\n+\tint rc;\n+\n+\tpath = build_path_from_dentry(direntry, page);\n+\tif (IS_ERR(path)) {\n+\t\trc = PTR_ERR(path);\n+\t\tgoto out_free_path;\n+\t}\n+\n+\trc = __cifs_do_create(NULL, inode, direntry, path, xid,\n+\t\t\t tlink, oflags, mode, oplock, fid, buf);\n+out_free_path:\n+\tfree_dentry_path(page);\n+\treturn rc;\n }\n \n int\n@@ -523,8 +565,8 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,\n \n \tcifs_add_pending_open(&fid, tlink, &open);\n \n-\trc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,\n-\t\t\t &oplock, &fid, &buf);\n+\trc = create_file(inode, direntry, xid, tlink,\n+\t\t\t oflags, mode, &oplock, &fid, &buf);\n \tif (rc) {\n \t\tcifs_del_pending_open(&open);\n \t\tgoto out;\n@@ -608,7 +650,8 @@ int cifs_create(struct mnt_idmap *idmap, struct inode *inode,\n \tif (server->ops->new_lease_key)\n \t\tserver->ops->new_lease_key(&fid);\n \n-\trc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, &oplock, &fid, &buf);\n+\trc = create_file(inode, direntry, xid, tlink,\n+\t\t\t oflags, mode, &oplock, &fid, &buf);\n \tif (!rc && server->ops->close)\n \t\tserver->ops->close(xid, tcon, &fid);\n \n@@ -959,6 +1002,168 @@ 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 cifsInodeInfo *cinode = CIFS_I(file_inode(file));\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+\n+\treturn server->ops->set_file_info(file_inode(file), NULL, &fi, xid);\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+\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 = create_tmpfile(dir, file, xid, tlink, mode, &oplock, &fid);\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 err_close;\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+err_close:\n+\tif (server->ops->close)\n+\t\tserver->ops->close(xid, tcon, &fid);\n+\tgoto out;\n+}\n+\n+static char *tmp_fullpath(struct dentry *dentry,\n+\t\t\t const unsigned char *name, size_t namesize)\n+{\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) + namesize;\n+\tnpath = kmalloc(len, GFP_KERNEL);\n+\tif (npath)\n+\t\tscnprintf(npath, len, \"%s%s\", path, name);\n+\telse\n+\t\tnpath = ERR_PTR(-ENOMEM);\n+out:\n+\tfree_dentry_path(page);\n+\treturn npath;\n+}\n+\n+char *cifs_silly_filename(struct dentry *dentry)\n+{\n+\tstruct cifs_sb_info *cifs_sb = CIFS_SB(dentry);\n+\tunsigned char name[CIFS_SILLY_FILENAME_SIZE];\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_TMPFILE_PREFIX \"%s\",\n+\t\t\t CIFS_DIR_SEP(cifs_sb),\n+\t\t\t atomic_inc_return(&cifs_sillycounter) & 0xffff,\n+\t\t\t CIFS_SILLY_FILENAME_SUFFIX);\n+\t\tsdentry = lookup_noperm(&QSTR(name + 1), 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 tmp_fullpath(dentry, name, namesize);\n+}\n+\n+char *cifs_tmpfile_name(struct dentry *dentry)\n+{\n+\tstruct cifs_sb_info *cifs_sb = CIFS_SB(dentry);\n+\tunsigned char name[CIFS_TMP_FILENAME_SIZE];\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_TMPFILE_PREFIX \"%s\",\n+\t\t\t CIFS_DIR_SEP(cifs_sb),\n+\t\t\t atomic_inc_return(&cifs_tmpcounter) & 0xffff,\n+\t\t\t CIFS_TMP_FILENAME_SUFFIX);\n+\t\tsdentry = lookup_noperm_unlocked(&QSTR(name + 1),\n+\t\t\t\t\t\t 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 tmp_fullpath(dentry, name, namesize);\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..0d1fda84a89e 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@@ -715,6 +716,8 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,\n \n \tcifs_down_write(&cinode->lock_sem);\n \tlist_add(&fdlocks->llist, &cinode->llist);\n+\tif (file->f_flags & O_TMPFILE)\n+\t\tset_bit(CIFS_INO_TMPFILE, &cinode->flags);\n \tup_write(&cinode->lock_sem);\n \n \tspin_lock(&tcon->open_file_lock);\n@@ -2605,6 +2608,15 @@ int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,\n \t\tfsuid_only = false;\n \n \tspin_lock(&cifs_inode->open_file_lock);\n+\tif (test_bit(CIFS_INO_TMPFILE, &cifs_inode->flags)) {\n+\t\t*ret_file = list_first_entry_or_null(&cifs_inode->openFileList,\n+\t\t\t\t\t\t struct cifsFileInfo,\n+\t\t\t\t\t\t flist);\n+\t\tif (*ret_file)\n+\t\t\tcifsFileInfo_get(*ret_file);\n+\t\tspin_unlock(&cifs_inode->open_file_lock);\n+\t\treturn *ret_file ? 0 : -EBADF;\n+\t}\n refind_writable:\n \tif (refind > MAX_REOPEN_ATT) {\n \t\tspin_unlock(&cifs_inode->open_file_lock);\n@@ -2683,16 +2695,23 @@ 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+\n \tstruct cifsFileInfo *cfile;\n-\tvoid *page = alloc_dentry_path();\n+\tvoid *page;\n \n \t*ret_file = NULL;\n \n+\tif (!name) {\n+\t\tif (WARN_ON_ONCE(!inode))\n+\t\t\treturn -EBADF;\n+\t\treturn cifs_get_writable_file(CIFS_I(inode), flags, ret_file);\n+\t}\n+\n+\tpage = alloc_dentry_path();\n \tspin_lock(&tcon->open_file_lock);\n \tlist_for_each_entry(cfile, &tcon->openFileList, tlist) {\n \t\tstruct cifsInodeInfo *cinode;\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..50daf6bb0551 100644\n--- a/fs/smb/client/link.c\n+++ b/fs/smb/client/link.c\n@@ -444,7 +444,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,\n \tint rc = -EACCES;\n \tunsigned int xid;\n \tconst char *from_name, *to_name;\n-\tvoid *page1, *page2;\n+\tvoid *page1 = NULL, *page2 = NULL;\n \tstruct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);\n \tstruct tcon_link *tlink;\n \tstruct cifs_tcon *tcon;\n@@ -460,14 +460,25 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,\n \ttcon = tlink_tcon(tlink);\n \n \txid = get_xid();\n+\n+\tif (d_really_is_positive(old_file)) {\n+\t\tcifsInode = CIFS_I(d_inode(old_file));\n+\t\tguard(spinlock)(&cifsInode->open_file_lock);\n+\t\tif (test_bit(CIFS_INO_TMPFILE, &cifsInode->flags)) {\n+\t\t\tfrom_name = NULL;\n+\t\t\tgoto tmpfile;\n+\t\t}\n+\t}\n+\n \tpage1 = alloc_dentry_path();\n-\tpage2 = alloc_dentry_path();\n-\n \tfrom_name = build_path_from_dentry(old_file, page1);\n \tif (IS_ERR(from_name)) {\n \t\trc = PTR_ERR(from_name);\n \t\tgoto cifs_hl_exit;\n \t}\n+\n+tmpfile:\n+\tpage2 = alloc_dentry_path();\n \tto_name = build_path_from_dentry(direntry, page2);\n \tif (IS_ERR(to_name)) {\n \t\trc = PTR_ERR(to_name);\n@@ -503,6 +514,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..44d660a9c67e 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@@ -226,6 +247,10 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,\n \t/* We already have a handle so we can skip the open */\n \tif (cfile)\n \t\tgoto after_open;\n+\tif (WARN_ON_ONCE(!full_path)) {\n+\t\trc = -EINVAL;\n+\t\tgoto finished;\n+\t}\n \n \t/* Open */\n \tutf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);\n@@ -284,32 +309,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 +326,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 +355,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 +373,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 +391,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 +418,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 +446,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 +474,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 +488,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 +1045,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 +1221,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 +1247,32 @@ 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 && !from_name) {\n+\t\tstruct cifsInodeInfo *cinode = CIFS_I(inode);\n+\t\tFILE_BASIC_INFO fi;\n+\t\t__u32 attrs;\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\tsmb2_set_file_info(inode, NULL, &fi, xid);\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 +1281,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 +1300,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 +1331,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 +1391,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 +1400,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 +1482,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 +1495,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 +1506,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_filename(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 +1536,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 +1556,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": [] }