blob: 728ff45b6667d3a1ac4aadf06f849a65876e0e0b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/inode.c
3 *
Steve Frenchf19159d2010-04-21 04:12:10 +00004 * Copyright (C) International Business Machines Corp., 2002,2010
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/stat.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/pagemap.h>
Jeff Layton4f73c7d2014-04-30 09:31:47 -040025#include <linux/freezer.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010026#include <linux/sched/signal.h>
Ingo Molnar5dd43ce2017-06-20 12:19:09 +020027#include <linux/wait_bit.h>
Christoph Hellwig10c5db22020-05-23 09:30:11 +020028#include <linux/fiemap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <asm/div64.h>
30#include "cifsfs.h"
31#include "cifspdu.h"
32#include "cifsglob.h"
33#include "cifsproto.h"
Steve French6a5f6592020-06-11 19:25:47 -050034#include "smb2proto.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include "cifs_debug.h"
36#include "cifs_fs_sb.h"
Steve French2baa2682014-09-27 02:19:01 -050037#include "cifs_unicode.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053038#include "fscache.h"
Ronnie Sahlberg8401e932020-12-12 13:40:50 -060039#include "fs_context.h"
Steve French087f7572021-04-29 00:18:43 -050040#include "cifs_ioctl.h"
Christoph Hellwig70eff552008-02-15 20:55:05 +000041
David Howells01c64fe2011-01-14 18:45:47 +000042static void cifs_set_ops(struct inode *inode)
Christoph Hellwig70eff552008-02-15 20:55:05 +000043{
44 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
45
46 switch (inode->i_mode & S_IFMT) {
47 case S_IFREG:
48 inode->i_op = &cifs_file_inode_ops;
49 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
50 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
51 inode->i_fop = &cifs_file_direct_nobrl_ops;
52 else
53 inode->i_fop = &cifs_file_direct_ops;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +030054 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
55 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
56 inode->i_fop = &cifs_file_strict_nobrl_ops;
57 else
58 inode->i_fop = &cifs_file_strict_ops;
Christoph Hellwig70eff552008-02-15 20:55:05 +000059 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
60 inode->i_fop = &cifs_file_nobrl_ops;
61 else { /* not direct, send byte range locks */
62 inode->i_fop = &cifs_file_ops;
63 }
64
Christoph Hellwig70eff552008-02-15 20:55:05 +000065 /* check if server can support readpages */
Jones Syue1f641d92020-04-13 09:37:23 +080066 if (cifs_sb_master_tcon(cifs_sb)->ses->server->max_read <
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +030067 PAGE_SIZE + MAX_CIFS_HDR_SIZE)
Christoph Hellwig70eff552008-02-15 20:55:05 +000068 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
69 else
70 inode->i_data.a_ops = &cifs_addr_ops;
71 break;
72 case S_IFDIR:
Steve Frenchbc5b6e22008-03-11 21:07:48 +000073#ifdef CONFIG_CIFS_DFS_UPCALL
David Howells01c64fe2011-01-14 18:45:47 +000074 if (IS_AUTOMOUNT(inode)) {
Igor Mammedov79626702008-03-09 03:44:18 +000075 inode->i_op = &cifs_dfs_referral_inode_operations;
76 } else {
Steve Frenchbc5b6e22008-03-11 21:07:48 +000077#else /* NO DFS support, treat as a directory */
78 {
79#endif
Igor Mammedov79626702008-03-09 03:44:18 +000080 inode->i_op = &cifs_dir_inode_ops;
81 inode->i_fop = &cifs_dir_ops;
82 }
Christoph Hellwig70eff552008-02-15 20:55:05 +000083 break;
84 case S_IFLNK:
85 inode->i_op = &cifs_symlink_inode_ops;
86 break;
87 default:
88 init_special_inode(inode, inode->i_mode, inode->i_rdev);
89 break;
90 }
91}
92
Jeff Laytondf2cf172010-02-12 07:44:16 -050093/* check inode attributes against fattr. If they don't match, tag the
94 * inode for cache invalidation
95 */
96static void
97cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
98{
99 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
100
Joe Perchesf96637b2013-05-04 22:12:25 -0500101 cifs_dbg(FYI, "%s: revalidating inode %llu\n",
102 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500103
104 if (inode->i_state & I_NEW) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500105 cifs_dbg(FYI, "%s: inode %llu is new\n",
106 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500107 return;
108 }
109
110 /* don't bother with revalidation if we have an oplock */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400111 if (CIFS_CACHE_READ(cifs_i)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500112 cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
113 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500114 return;
115 }
116
117 /* revalidate if mtime or size have changed */
Deepa Dinamani918c9002019-12-02 21:19:41 -0800118 fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
Arnd Bergmann95390202018-06-19 17:27:58 +0200119 if (timespec64_equal(&inode->i_mtime, &fattr->cf_mtime) &&
Jeff Laytondf2cf172010-02-12 07:44:16 -0500120 cifs_i->server_eof == fattr->cf_eof) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500121 cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
122 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500123 return;
124 }
125
Joe Perchesf96637b2013-05-04 22:12:25 -0500126 cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
127 __func__, cifs_i->uniqueid);
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400128 set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500129}
130
Jim McDonough74d290d2013-09-21 10:36:10 -0500131/*
132 * copy nlink to the inode, unless it wasn't provided. Provide
133 * sane values if we don't have an existing one and none was provided
134 */
135static void
136cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
137{
138 /*
139 * if we're in a situation where we can't trust what we
140 * got from the server (readdir, some non-unix cases)
141 * fake reasonable values
142 */
143 if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
144 /* only provide fake values on a new inode */
145 if (inode->i_state & I_NEW) {
146 if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
147 set_nlink(inode, 2);
148 else
149 set_nlink(inode, 1);
150 }
151 return;
152 }
153
154 /* we trust the server, so update it */
155 set_nlink(inode, fattr->cf_nlink);
156}
157
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400158/* populate an inode with info from a cifs_fattr struct */
159void
160cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
Christoph Hellwig75f12982008-02-25 20:25:21 +0000161{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400162 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400163 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000164
Jeff Laytondf2cf172010-02-12 07:44:16 -0500165 cifs_revalidate_cache(inode, fattr);
166
Steve Frenchb7ca6922012-08-03 08:43:01 -0500167 spin_lock(&inode->i_lock);
Deepa Dinamani918c9002019-12-02 21:19:41 -0800168 fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
169 fattr->cf_atime = timestamp_truncate(fattr->cf_atime, inode);
170 fattr->cf_ctime = timestamp_truncate(fattr->cf_ctime, inode);
Steve French9b9c5be2018-09-22 12:07:06 -0500171 /* we do not want atime to be less than mtime, it broke some apps */
Deepa Dinamani69738cf2019-11-29 21:30:25 -0800172 if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime) < 0)
Steve French9b9c5be2018-09-22 12:07:06 -0500173 inode->i_atime = fattr->cf_mtime;
174 else
175 inode->i_atime = fattr->cf_atime;
Arnd Bergmann95390202018-06-19 17:27:58 +0200176 inode->i_mtime = fattr->cf_mtime;
177 inode->i_ctime = fattr->cf_ctime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400178 inode->i_rdev = fattr->cf_rdev;
Jim McDonough74d290d2013-09-21 10:36:10 -0500179 cifs_nlink_fattr_to_inode(inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400180 inode->i_uid = fattr->cf_uid;
181 inode->i_gid = fattr->cf_gid;
182
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400183 /* if dynperm is set, don't clobber existing mode */
184 if (inode->i_state & I_NEW ||
185 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
186 inode->i_mode = fattr->cf_mode;
187
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400188 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400189
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400190 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
191 cifs_i->time = 0;
192 else
193 cifs_i->time = jiffies;
194
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400195 if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
196 set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
197 else
198 clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000199
Jeff Layton835a36c2010-02-10 16:21:33 -0500200 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000201 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400202 * Can't safely change the file size here if the client is writing to
203 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000204 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400205 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
206 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000207
208 /*
209 * i_blocks is not related to (i_size / i_blksize),
210 * but instead 512 byte (2**9) size is required for
211 * calculating num blocks.
212 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400213 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000214 }
215 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400216
David Howells01c64fe2011-01-14 18:45:47 +0000217 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
218 inode->i_flags |= S_AUTOMOUNT;
Jeff Laytonc2b93e02013-05-07 11:28:31 -0400219 if (inode->i_state & I_NEW)
220 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000221}
222
Jeff Layton4065c802010-05-17 07:18:58 -0400223void
224cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
225{
226 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
227
228 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
229 return;
230
231 fattr->cf_uniqueid = iunique(sb, ROOT_I);
232}
233
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400234/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
235void
236cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
237 struct cifs_sb_info *cifs_sb)
238{
239 memset(fattr, 0, sizeof(*fattr));
240 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
241 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
242 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
243
244 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
245 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
246 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
Steve French6e70e262017-09-21 21:32:29 -0500247 /* old POSIX extensions don't get create time */
248
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400249 fattr->cf_mode = le64_to_cpu(info->Permissions);
250
251 /*
252 * Since we set the inode type below we need to mask off
253 * to avoid strange results if bits set above.
254 */
255 fattr->cf_mode &= ~S_IFMT;
256 switch (le32_to_cpu(info->Type)) {
257 case UNIX_FILE:
258 fattr->cf_mode |= S_IFREG;
259 fattr->cf_dtype = DT_REG;
260 break;
261 case UNIX_SYMLINK:
262 fattr->cf_mode |= S_IFLNK;
263 fattr->cf_dtype = DT_LNK;
264 break;
265 case UNIX_DIR:
266 fattr->cf_mode |= S_IFDIR;
267 fattr->cf_dtype = DT_DIR;
268 break;
269 case UNIX_CHARDEV:
270 fattr->cf_mode |= S_IFCHR;
271 fattr->cf_dtype = DT_CHR;
272 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
273 le64_to_cpu(info->DevMinor) & MINORMASK);
274 break;
275 case UNIX_BLOCKDEV:
276 fattr->cf_mode |= S_IFBLK;
277 fattr->cf_dtype = DT_BLK;
278 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
279 le64_to_cpu(info->DevMinor) & MINORMASK);
280 break;
281 case UNIX_FIFO:
282 fattr->cf_mode |= S_IFIFO;
283 fattr->cf_dtype = DT_FIFO;
284 break;
285 case UNIX_SOCKET:
286 fattr->cf_mode |= S_IFSOCK;
287 fattr->cf_dtype = DT_SOCK;
288 break;
289 default:
290 /* safest to call it a file if we do not know */
291 fattr->cf_mode |= S_IFREG;
292 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500293 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400294 break;
295 }
296
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600297 fattr->cf_uid = cifs_sb->ctx->linux_uid;
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800298 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
299 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800300 if (id < ((uid_t)-1)) {
301 kuid_t uid = make_kuid(&init_user_ns, id);
302 if (uid_valid(uid))
303 fattr->cf_uid = uid;
304 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800305 }
306
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600307 fattr->cf_gid = cifs_sb->ctx->linux_gid;
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800308 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
309 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800310 if (id < ((gid_t)-1)) {
311 kgid_t gid = make_kgid(&init_user_ns, id);
312 if (gid_valid(gid))
313 fattr->cf_gid = gid;
314 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800315 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400316
317 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
318}
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000319
320/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400321 * Fill a cifs_fattr struct with fake inode info.
322 *
323 * Needed to setup cifs_fattr data for the directory which is the
324 * junction to the new submount (ie to setup the fake directory
325 * which represents a DFS referral).
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000326 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000327static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400328cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000329{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400330 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000331
Joe Perchesf96637b2013-05-04 22:12:25 -0500332 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000333
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400334 memset(fattr, 0, sizeof(*fattr));
335 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600336 fattr->cf_uid = cifs_sb->ctx->linux_uid;
337 fattr->cf_gid = cifs_sb->ctx->linux_gid;
Deepa Dinamani918c9002019-12-02 21:19:41 -0800338 ktime_get_coarse_real_ts64(&fattr->cf_mtime);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700339 fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400340 fattr->cf_nlink = 2;
Steve French97aa4952018-11-15 00:33:05 -0600341 fattr->cf_flags = CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000342}
343
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700344static int
345cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500346{
347 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400348 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500349 FILE_UNIX_BASIC_INFO find_data;
350 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500351 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500352 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700353 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000354 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500355
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400356 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700357 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500358 if (!rc) {
359 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
360 } else if (rc == -EREMOTE) {
361 cifs_create_dfs_fattr(&fattr, inode->i_sb);
362 rc = 0;
363 }
364
365 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400366 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500367 return rc;
368}
369
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400371 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400372 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400374 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000375 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400376 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000377 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400378 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Joe Perchesf96637b2013-05-04 22:12:25 -0500381 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000382
Jeff Layton7ffec372010-09-29 19:51:11 -0400383 tlink = cifs_sb_tlink(cifs_sb);
384 if (IS_ERR(tlink))
385 return PTR_ERR(tlink);
386 tcon = tlink_tcon(tlink);
387
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400389 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +0900390 cifs_sb->local_nls, cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -0400391 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400392
393 if (!rc) {
394 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
395 } else if (rc == -EREMOTE) {
396 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700397 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400398 } else {
399 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000400 }
401
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200402 /* check for Minshall+French symlinks */
403 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000404 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
405 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200406 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000407 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200408 }
409
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400410 if (*pinode == NULL) {
411 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400412 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400413 *pinode = cifs_iget(sb, &fattr);
414 if (!*pinode)
415 rc = -ENOMEM;
416 } else {
417 /* we already have inode, update it */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900418
419 /* if uniqueid is different, return error */
420 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
421 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -0700422 CIFS_I(*pinode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900423 rc = -ESTALE;
424 goto cgiiu_exit;
425 }
426
427 /* if filetype is different, return error */
428 if (unlikely(((*pinode)->i_mode & S_IFMT) !=
429 (fattr.cf_mode & S_IFMT))) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -0700430 CIFS_I(*pinode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900431 rc = -ESTALE;
432 goto cgiiu_exit;
433 }
434
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400435 cifs_fattr_to_inode(*pinode, &fattr);
436 }
Steve French0e4bbde2008-05-20 19:50:46 +0000437
Nakajima Akira7196ac12015-04-22 15:24:44 +0900438cgiiu_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 return rc;
440}
441
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400442static int
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400443cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400444 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800445{
446 int rc;
Steve Frenchdb8b6312014-09-22 05:13:55 -0500447 __u32 oplock;
Jeff Layton7ffec372010-09-29 19:51:11 -0400448 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000449 struct cifs_tcon *tcon;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400450 struct cifs_fid fid;
451 struct cifs_open_parms oparms;
Aurelien Aptel7c065142020-06-04 17:23:55 +0200452 struct cifs_io_parms io_parms = {0};
Steve French86c96b42005-11-18 20:25:31 -0800453 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800454 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000455 char *pbuf;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400456 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800457
458 pbuf = buf;
459
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400460 fattr->cf_mode &= ~S_IFMT;
461
462 if (fattr->cf_eof == 0) {
463 fattr->cf_mode |= S_IFIFO;
464 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800465 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400466 } else if (fattr->cf_eof < 8) {
467 fattr->cf_mode |= S_IFREG;
468 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800469 return -EINVAL; /* EOPNOTSUPP? */
470 }
Steve French50c2f752007-07-13 00:33:32 +0000471
Jeff Layton7ffec372010-09-29 19:51:11 -0400472 tlink = cifs_sb_tlink(cifs_sb);
473 if (IS_ERR(tlink))
474 return PTR_ERR(tlink);
475 tcon = tlink_tcon(tlink);
476
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400477 oparms.tcon = tcon;
478 oparms.cifs_sb = cifs_sb;
479 oparms.desired_access = GENERIC_READ;
Amir Goldstein0f060932020-02-03 21:46:43 +0200480 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400481 oparms.disposition = FILE_OPEN;
482 oparms.path = path;
483 oparms.fid = &fid;
484 oparms.reconnect = false;
485
Steve Frenchdb8b6312014-09-22 05:13:55 -0500486 if (tcon->ses->server->oplocks)
487 oplock = REQ_OPLOCK;
488 else
489 oplock = 0;
490 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400491 if (rc) {
Steve Frenchdb8b6312014-09-22 05:13:55 -0500492 cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400493 cifs_put_tlink(tlink);
494 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800495 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400496
497 /* Read header */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400498 io_parms.netfid = fid.netfid;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400499 io_parms.pid = current->tgid;
500 io_parms.tcon = tcon;
501 io_parms.offset = 0;
502 io_parms.length = 24;
503
Steve Frenchdb8b6312014-09-22 05:13:55 -0500504 rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
505 &bytes_read, &pbuf, &buf_type);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400506 if ((rc == 0) && (bytes_read >= 8)) {
507 if (memcmp("IntxBLK", pbuf, 8) == 0) {
508 cifs_dbg(FYI, "Block device\n");
509 fattr->cf_mode |= S_IFBLK;
510 fattr->cf_dtype = DT_BLK;
511 if (bytes_read == 24) {
512 /* we have enough to decode dev num */
513 __u64 mjr; /* major */
514 __u64 mnr; /* minor */
515 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
516 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
517 fattr->cf_rdev = MKDEV(mjr, mnr);
518 }
519 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
520 cifs_dbg(FYI, "Char device\n");
521 fattr->cf_mode |= S_IFCHR;
522 fattr->cf_dtype = DT_CHR;
523 if (bytes_read == 24) {
524 /* we have enough to decode dev num */
525 __u64 mjr; /* major */
526 __u64 mnr; /* minor */
527 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
528 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
529 fattr->cf_rdev = MKDEV(mjr, mnr);
530 }
531 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
532 cifs_dbg(FYI, "Symlink\n");
533 fattr->cf_mode |= S_IFLNK;
534 fattr->cf_dtype = DT_LNK;
535 } else {
536 fattr->cf_mode |= S_IFREG; /* file? */
537 fattr->cf_dtype = DT_REG;
538 rc = -EOPNOTSUPP;
539 }
540 } else {
541 fattr->cf_mode |= S_IFREG; /* then it is a file */
542 fattr->cf_dtype = DT_REG;
543 rc = -EOPNOTSUPP; /* or some unknown SFU type */
544 }
Steve Frenchdb8b6312014-09-22 05:13:55 -0500545
546 tcon->ses->server->ops->close(xid, tcon, &fid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400547 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800548 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800549}
550
Steve French9e294f12005-11-17 16:59:21 -0800551#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
552
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400553/*
554 * Fetch mode bits as provided by SFU.
555 *
556 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
557 */
558static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400559 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800560{
Steve French3020a1f2005-11-18 11:31:10 -0800561#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800562 ssize_t rc;
563 char ea_value[4];
564 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400565 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000566 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800567
Jeff Layton7ffec372010-09-29 19:51:11 -0400568 tlink = cifs_sb_tlink(cifs_sb);
569 if (IS_ERR(tlink))
570 return PTR_ERR(tlink);
571 tcon = tlink_tcon(tlink);
572
Steve Frenchd979f3b2014-02-01 23:27:18 -0600573 if (tcon->ses->server->ops->query_all_EAs == NULL) {
574 cifs_put_tlink(tlink);
575 return -EOPNOTSUPP;
576 }
577
578 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
579 "SETFILEBITS", ea_value, 4 /* size of buf */,
Steve French67b4c882017-05-12 20:59:10 -0500580 cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400581 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000582 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800583 return (int)rc;
584 else if (rc > 3) {
585 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400586 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500587 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
588 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400589 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500590 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800591 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400592
593 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800594#else
595 return -EOPNOTSUPP;
596#endif
Steve French9e294f12005-11-17 16:59:21 -0800597}
598
Steve French6a5f6592020-06-11 19:25:47 -0500599/* Fill a cifs_fattr struct with info from POSIX info struct */
600static void
601smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct smb311_posix_qinfo *info,
602 struct super_block *sb, bool adjust_tz, bool symlink)
603{
604 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
605 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
606
607 memset(fattr, 0, sizeof(*fattr));
608
609 /* no fattr->flags to set */
610 fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
611 fattr->cf_uniqueid = le64_to_cpu(info->Inode);
612
613 if (info->LastAccessTime)
614 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
615 else
616 ktime_get_coarse_real_ts64(&fattr->cf_atime);
617
618 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
619 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
620
621 if (adjust_tz) {
622 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
623 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
624 }
625
626 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
627 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
628 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
629
630 fattr->cf_nlink = le32_to_cpu(info->HardLinks);
631 fattr->cf_mode = (umode_t) le32_to_cpu(info->Mode);
632 /* The srv fs device id is overridden on network mount so setting rdev isn't needed here */
633 /* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */
634
635 if (symlink) {
636 fattr->cf_mode |= S_IFLNK;
637 fattr->cf_dtype = DT_LNK;
638 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
639 fattr->cf_mode |= S_IFDIR;
640 fattr->cf_dtype = DT_DIR;
641 } else { /* file */
642 fattr->cf_mode |= S_IFREG;
643 fattr->cf_dtype = DT_REG;
644 }
645 /* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */
646
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600647 fattr->cf_uid = cifs_sb->ctx->linux_uid; /* TODO: map uid and gid from SID */
648 fattr->cf_gid = cifs_sb->ctx->linux_gid;
Steve French6a5f6592020-06-11 19:25:47 -0500649
650 cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
651 fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
652}
653
654
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400655/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000656static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400657cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700658 struct super_block *sb, bool adjust_tz,
Steve French2e4564b2020-10-22 22:03:14 -0500659 bool symlink, u32 reparse_tag)
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000660{
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700661 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French96daf2b2011-05-27 04:34:02 +0000662 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700663
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400664 memset(fattr, 0, sizeof(*fattr));
665 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
666 if (info->DeletePending)
667 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000668
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400669 if (info->LastAccessTime)
670 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
Deepa Dinamani918c9002019-12-02 21:19:41 -0800671 else
672 ktime_get_coarse_real_ts64(&fattr->cf_atime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400673
674 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
675 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
676
677 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700678 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
679 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400680 }
681
682 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
683 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500684 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400685
Jim McDonough74d290d2013-09-21 10:36:10 -0500686 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Steve French2e4564b2020-10-22 22:03:14 -0500687 if (reparse_tag == IO_REPARSE_TAG_LX_SYMLINK) {
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600688 fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;
Steve French2e4564b2020-10-22 22:03:14 -0500689 fattr->cf_dtype = DT_LNK;
690 } else if (reparse_tag == IO_REPARSE_TAG_LX_FIFO) {
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600691 fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;
Steve French2e4564b2020-10-22 22:03:14 -0500692 fattr->cf_dtype = DT_FIFO;
693 } else if (reparse_tag == IO_REPARSE_TAG_AF_UNIX) {
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600694 fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
Steve French2e4564b2020-10-22 22:03:14 -0500695 fattr->cf_dtype = DT_SOCK;
696 } else if (reparse_tag == IO_REPARSE_TAG_LX_CHR) {
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600697 fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
Steve French2e4564b2020-10-22 22:03:14 -0500698 fattr->cf_dtype = DT_CHR;
699 } else if (reparse_tag == IO_REPARSE_TAG_LX_BLK) {
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600700 fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
Steve French2e4564b2020-10-22 22:03:14 -0500701 fattr->cf_dtype = DT_BLK;
702 } else if (symlink) { /* TODO add more reparse tag checks */
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400703 fattr->cf_mode = S_IFLNK;
704 fattr->cf_dtype = DT_LNK;
705 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600706 fattr->cf_mode = S_IFDIR | cifs_sb->ctx->dir_mode;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400707 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300708 /*
709 * Server can return wrong NumberOfLinks value for directories
710 * when Unix extensions are disabled - fake it.
711 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500712 if (!tcon->unix_ext)
713 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400714 } else {
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600715 fattr->cf_mode = S_IFREG | cifs_sb->ctx->file_mode;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400716 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400717
Jeff Laytond0c280d2009-07-09 01:46:44 -0400718 /* clear write bits if ATTR_READONLY is set */
719 if (fattr->cf_cifsattrs & ATTR_READONLY)
720 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400721
Jim McDonough74d290d2013-09-21 10:36:10 -0500722 /*
723 * Don't accept zero nlink from non-unix servers unless
724 * delete is pending. Instead mark it as unknown.
725 */
726 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
727 !info->DeletePending) {
Joe Perchesfb4b5f12020-02-21 05:20:45 -0800728 cifs_dbg(VFS, "bogus file nlink value %u\n",
729 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500730 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500731 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300732 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400733
Ronnie Sahlberg8401e932020-12-12 13:40:50 -0600734 fattr->cf_uid = cifs_sb->ctx->linux_uid;
735 fattr->cf_gid = cifs_sb->ctx->linux_gid;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000736}
737
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700738static int
739cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500740{
741 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400742 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500743 FILE_ALL_INFO find_data;
744 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500745 struct inode *inode = file_inode(filp);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700746 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000747 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700748 struct TCP_Server_Info *server = tcon->ses->server;
749
750 if (!server->ops->query_file_info)
751 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500752
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400753 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700754 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400755 switch (rc) {
756 case 0:
Steve French2e4564b2020-10-22 22:03:14 -0500757 /* TODO: add support to query reparse tag */
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700758 cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
Steve French2e4564b2020-10-22 22:03:14 -0500759 false, 0 /* no reparse tag */);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400760 break;
761 case -EREMOTE:
762 cifs_create_dfs_fattr(&fattr, inode->i_sb);
763 rc = 0;
764 break;
765 case -EOPNOTSUPP:
766 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500767 /*
768 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000769 * for now, just skip revalidating and mark inode for
770 * immediate reval.
771 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500772 rc = 0;
773 CIFS_I(inode)->time = 0;
Gustavo A. R. Silva21ac58f2020-11-20 12:24:14 -0600774 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400775 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500776 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400777 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500778
779 /*
780 * don't bother with SFU junk here -- just mark inode as needing
781 * revalidation.
782 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500783 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
784 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
785 cifs_fattr_to_inode(inode, &fattr);
786cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400787 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500788 return rc;
789}
790
Steve French7ea884c2018-03-31 18:13:38 -0500791/* Simple function to return a 64 bit hash of string. Rarely called */
792static __u64 simple_hashstr(const char *str)
793{
Geert Uytterhoeven3995bbf2018-04-05 14:57:11 +0200794 const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
Steve French7ea884c2018-03-31 18:13:38 -0500795 __u64 hash = 0;
796
797 while (*str)
798 hash = (hash + (__u64) *str++) * hash_mult;
799
800 return hash;
801}
802
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100803/**
804 * cifs_backup_query_path_info - SMB1 fallback code to get ino
805 *
806 * Fallback code to get file metadata when we don't have access to
Steve French607dfc72020-12-12 12:08:58 -0600807 * full_path (EACCES) and have backup creds.
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100808 *
Steve French607dfc72020-12-12 12:08:58 -0600809 * @xid: transaction id used to identify original request in logs
810 * @tcon: information about the server share we have mounted
811 * @sb: the superblock stores info such as disk space available
812 * @full_path: name of the file we are getting the metadata for
813 * @resp_buf: will be set to cifs resp buf and needs to be freed with
814 * cifs_buf_release() when done with @data
815 * @data: will be set to search info result buffer
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100816 */
817static int
818cifs_backup_query_path_info(int xid,
819 struct cifs_tcon *tcon,
820 struct super_block *sb,
821 const char *full_path,
822 void **resp_buf,
823 FILE_ALL_INFO **data)
824{
825 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
826 struct cifs_search_info info = {0};
827 u16 flags;
828 int rc;
829
830 *resp_buf = NULL;
831 info.endOfSearch = false;
832 if (tcon->unix_ext)
833 info.info_level = SMB_FIND_FILE_UNIX;
834 else if ((tcon->ses->capabilities &
835 tcon->ses->server->vals->cap_nt_find) == 0)
836 info.info_level = SMB_FIND_FILE_INFO_STANDARD;
837 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
838 info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
839 else /* no srvino useful for fallback to some netapp */
840 info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
841
842 flags = CIFS_SEARCH_CLOSE_ALWAYS |
843 CIFS_SEARCH_CLOSE_AT_END |
844 CIFS_SEARCH_BACKUP_SEARCH;
845
846 rc = CIFSFindFirst(xid, tcon, full_path,
847 cifs_sb, NULL, flags, &info, false);
848 if (rc)
849 return rc;
850
851 *resp_buf = (void *)info.ntwrk_buf_start;
852 *data = (FILE_ALL_INFO *)info.srch_entries_start;
853 return 0;
854}
855
856static void
857cifs_set_fattr_ino(int xid,
858 struct cifs_tcon *tcon,
859 struct super_block *sb,
860 struct inode **inode,
861 const char *full_path,
862 FILE_ALL_INFO *data,
863 struct cifs_fattr *fattr)
864{
865 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
866 struct TCP_Server_Info *server = tcon->ses->server;
867 int rc;
868
869 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
870 if (*inode)
871 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
872 else
873 fattr->cf_uniqueid = iunique(sb, ROOT_I);
874 return;
875 }
876
877 /*
878 * If we have an inode pass a NULL tcon to ensure we don't
879 * make a round trip to the server. This only works for SMB2+.
880 */
881 rc = server->ops->get_srv_inum(xid,
882 *inode ? NULL : tcon,
883 cifs_sb, full_path,
884 &fattr->cf_uniqueid,
885 data);
886 if (rc) {
887 /*
888 * If that fails reuse existing ino or generate one
889 * and disable server ones
890 */
891 if (*inode)
892 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
893 else {
894 fattr->cf_uniqueid = iunique(sb, ROOT_I);
895 cifs_autodisable_serverino(cifs_sb);
896 }
897 return;
898 }
899
900 /* If no errors, check for zero root inode (invalid) */
901 if (fattr->cf_uniqueid == 0 && strlen(full_path) == 0) {
902 cifs_dbg(FYI, "Invalid (0) inodenum\n");
903 if (*inode) {
904 /* reuse */
905 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
906 } else {
907 /* make an ino by hashing the UNC */
908 fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
909 fattr->cf_uniqueid = simple_hashstr(tcon->treeName);
910 }
911 }
912}
913
914static inline bool is_inode_cache_good(struct inode *ino)
915{
916 return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;
917}
918
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400919int
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100920cifs_get_inode_info(struct inode **inode,
921 const char *full_path,
922 FILE_ALL_INFO *in_data,
923 struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600924 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925{
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100926
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400927 struct cifs_tcon *tcon;
928 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400929 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400931 bool adjust_tz = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100932 struct cifs_fattr fattr = {0};
Steve French2e4564b2020-10-22 22:03:14 -0500933 bool is_reparse_point = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100934 FILE_ALL_INFO *data = in_data;
935 FILE_ALL_INFO *tmp_data = NULL;
936 void *smb1_backup_rsp_buf = NULL;
937 int rc = 0;
938 int tmprc = 0;
Steve French2e4564b2020-10-22 22:03:14 -0500939 __u32 reparse_tag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
Jeff Layton7ffec372010-09-29 19:51:11 -0400941 tlink = cifs_sb_tlink(cifs_sb);
942 if (IS_ERR(tlink))
943 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400944 tcon = tlink_tcon(tlink);
945 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400946
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100947 /*
948 * 1. Fetch file metadata if not provided (data)
949 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100951 if (!data) {
952 if (is_inode_cache_good(*inode)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500953 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100954 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100956 tmp_data = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
957 if (!tmp_data) {
Jeff Layton7ffec372010-09-29 19:51:11 -0400958 rc = -ENOMEM;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100959 goto out;
Jeff Layton7ffec372010-09-29 19:51:11 -0400960 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100961 rc = server->ops->query_path_info(xid, tcon, cifs_sb,
Steve French2e4564b2020-10-22 22:03:14 -0500962 full_path, tmp_data,
963 &adjust_tz, &is_reparse_point);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100964 data = tmp_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400966
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400967 /*
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100968 * 2. Convert it to internal cifs metadata (fattr)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400969 */
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100970
971 switch (rc) {
972 case 0:
Steve French2e4564b2020-10-22 22:03:14 -0500973 /*
974 * If the file is a reparse point, it is more complicated
975 * since we have to check if its reparse tag matches a known
976 * special file type e.g. symlink or fifo or char etc.
977 */
978 if ((le32_to_cpu(data->Attributes) & ATTR_REPARSE) &&
979 server->ops->query_reparse_tag) {
980 rc = server->ops->query_reparse_tag(xid, tcon, cifs_sb,
981 full_path, &reparse_tag);
982 cifs_dbg(FYI, "reparse tag 0x%x\n", reparse_tag);
983 }
984 cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz,
985 is_reparse_point, reparse_tag);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100986 break;
987 case -EREMOTE:
988 /* DFS link, no metadata available on this server */
989 cifs_create_dfs_fattr(&fattr, sb);
990 rc = 0;
991 break;
992 case -EACCES:
993 /*
994 * perm errors, try again with backup flags if possible
995 *
996 * For SMB2 and later the backup intent flag
997 * is already sent if needed on open and there
998 * is no path based FindFirst operation to use
999 * to retry with
1000 */
1001 if (backup_cred(cifs_sb) && is_smb1_server(server)) {
1002 /* for easier reading */
1003 FILE_DIRECTORY_INFO *fdi;
1004 SEARCH_ID_FULL_DIR_INFO *si;
1005
1006 rc = cifs_backup_query_path_info(xid, tcon, sb,
1007 full_path,
1008 &smb1_backup_rsp_buf,
1009 &data);
1010 if (rc)
1011 goto out;
1012
1013 fdi = (FILE_DIRECTORY_INFO *)data;
1014 si = (SEARCH_ID_FULL_DIR_INFO *)data;
1015
1016 cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb);
1017 fattr.cf_uniqueid = le64_to_cpu(si->UniqueId);
1018 /* uniqueid set, skip get inum step */
1019 goto handle_mnt_opt;
1020 } else {
1021 /* nothing we can do, bail out */
1022 goto out;
1023 }
1024 break;
1025 default:
1026 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
1027 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001028 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001029
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001030 /*
1031 * 3. Get or update inode number (fattr.cf_uniqueid)
1032 */
1033
1034 cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);
1035
1036 /*
1037 * 4. Tweak fattr based on mount options
1038 */
1039
1040handle_mnt_opt:
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001041 /* query for SFU type info if supported and needed */
1042 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
1043 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
1044 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
1045 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001046 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001047 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001048
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001049 /* fill in 0777 bits from ACL */
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001050 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
1051 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
1052 full_path, fid);
Ronnie Sahlberg01ec3722020-09-03 10:02:39 +10001053 if (rc == -EREMOTE)
1054 rc = 0;
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001055 if (rc) {
1056 cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001057 __func__, rc);
1058 goto out;
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001059 }
1060 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
1061 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
Dan Carpenter via samba-technical68464b82019-11-26 15:11:15 +03001062 full_path, fid);
Ronnie Sahlberg01ec3722020-09-03 10:02:39 +10001063 if (rc == -EREMOTE)
1064 rc = 0;
Dan Carpenter via samba-technical68464b82019-11-26 15:11:15 +03001065 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001066 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
1067 __func__, rc);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001068 goto out;
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06001069 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001070 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001071
1072 /* fill in remaining high mode bits e.g. SUID, VTX */
1073 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
1074 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
1075
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001076 /* check for Minshall+French symlinks */
1077 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +00001078 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
1079 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001080 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +00001081 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001082 }
1083
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001084 /*
1085 * 5. Update inode with final fattr data
1086 */
1087
Pavel Shilovsky1208ef12012-05-27 17:34:43 +04001088 if (!*inode) {
1089 *inode = cifs_iget(sb, &fattr);
1090 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001091 rc = -ENOMEM;
1092 } else {
Nakajima Akira7196ac12015-04-22 15:24:44 +09001093 /* we already have inode, update it */
1094
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001095 /* if uniqueid is different, return error */
1096 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1097 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001098 CIFS_I(*inode)->time = 0; /* force reval */
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001099 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001100 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001101 }
1102
Nakajima Akira7196ac12015-04-22 15:24:44 +09001103 /* if filetype is different, return error */
1104 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1105 (fattr.cf_mode & S_IFMT))) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001106 CIFS_I(*inode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +09001107 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001108 goto out;
Nakajima Akira7196ac12015-04-22 15:24:44 +09001109 }
1110
Pavel Shilovsky1208ef12012-05-27 17:34:43 +04001111 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001112 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001113out:
1114 cifs_buf_release(smb1_backup_rsp_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001115 cifs_put_tlink(tlink);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001116 kfree(tmp_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 return rc;
1118}
1119
Steve French6a5f6592020-06-11 19:25:47 -05001120int
1121smb311_posix_get_inode_info(struct inode **inode,
1122 const char *full_path,
1123 struct super_block *sb, unsigned int xid)
1124{
1125 struct cifs_tcon *tcon;
Steve French6a5f6592020-06-11 19:25:47 -05001126 struct tcon_link *tlink;
1127 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1128 bool adjust_tz = false;
1129 struct cifs_fattr fattr = {0};
1130 bool symlink = false;
1131 struct smb311_posix_qinfo *data = NULL;
1132 int rc = 0;
1133 int tmprc = 0;
1134
1135 tlink = cifs_sb_tlink(cifs_sb);
1136 if (IS_ERR(tlink))
1137 return PTR_ERR(tlink);
1138 tcon = tlink_tcon(tlink);
Steve French6a5f6592020-06-11 19:25:47 -05001139
1140 /*
1141 * 1. Fetch file metadata
1142 */
1143
1144 if (is_inode_cache_good(*inode)) {
1145 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
1146 goto out;
1147 }
1148 data = kmalloc(sizeof(struct smb311_posix_qinfo), GFP_KERNEL);
1149 if (!data) {
1150 rc = -ENOMEM;
1151 goto out;
1152 }
1153
1154 rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
1155 full_path, data,
1156 &adjust_tz, &symlink);
1157
1158 /*
1159 * 2. Convert it to internal cifs metadata (fattr)
1160 */
1161
1162 switch (rc) {
1163 case 0:
1164 smb311_posix_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
1165 break;
1166 case -EREMOTE:
1167 /* DFS link, no metadata available on this server */
1168 cifs_create_dfs_fattr(&fattr, sb);
1169 rc = 0;
1170 break;
1171 case -EACCES:
1172 /*
1173 * For SMB2 and later the backup intent flag
1174 * is already sent if needed on open and there
1175 * is no path based FindFirst operation to use
1176 * to retry with so nothing we can do, bail out
1177 */
1178 goto out;
1179 default:
1180 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
1181 goto out;
1182 }
1183
1184
1185 /*
Steve Frencha7a519a2020-06-12 14:49:47 -05001186 * 3. Tweak fattr based on mount options
Steve French6a5f6592020-06-11 19:25:47 -05001187 */
1188
1189 /* check for Minshall+French symlinks */
1190 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
1191 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
1192 full_path);
1193 if (tmprc)
1194 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1195 }
1196
1197 /*
Steve Frencha7a519a2020-06-12 14:49:47 -05001198 * 4. Update inode with final fattr data
Steve French6a5f6592020-06-11 19:25:47 -05001199 */
1200
1201 if (!*inode) {
1202 *inode = cifs_iget(sb, &fattr);
1203 if (!*inode)
1204 rc = -ENOMEM;
1205 } else {
1206 /* we already have inode, update it */
1207
1208 /* if uniqueid is different, return error */
1209 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1210 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
1211 CIFS_I(*inode)->time = 0; /* force reval */
1212 rc = -ESTALE;
1213 goto out;
1214 }
1215
1216 /* if filetype is different, return error */
1217 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1218 (fattr.cf_mode & S_IFMT))) {
1219 CIFS_I(*inode)->time = 0; /* force reval */
1220 rc = -ESTALE;
1221 goto out;
1222 }
1223
1224 cifs_fattr_to_inode(*inode, &fattr);
1225 }
1226out:
1227 cifs_put_tlink(tlink);
1228 kfree(data);
1229 return rc;
1230}
1231
1232
Steve French7f8ed422007-09-28 22:28:55 +00001233static const struct inode_operations cifs_ipc_inode_ops = {
1234 .lookup = cifs_lookup,
1235};
1236
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001237static int
1238cifs_find_inode(struct inode *inode, void *opaque)
1239{
1240 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1241
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001242 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001243 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
1244 return 0;
1245
Jeff Layton20054bd2011-01-07 11:30:27 -05001246 /* use createtime like an i_generation field */
1247 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
1248 return 0;
1249
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001250 /* don't match inode of different type */
1251 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
1252 return 0;
1253
Jeff Layton5acfec22010-08-02 17:43:54 -04001254 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -04001255 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -04001256 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -04001257
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001258 return 1;
1259}
1260
1261static int
1262cifs_init_inode(struct inode *inode, void *opaque)
1263{
1264 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1265
1266 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -05001267 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001268 return 0;
1269}
1270
Jeff Layton5acfec22010-08-02 17:43:54 -04001271/*
1272 * walk dentry list for an inode and report whether it has aliases that
1273 * are hashed. We use this to determine if a directory inode can actually
1274 * be used.
1275 */
1276static bool
1277inode_has_hashed_dentries(struct inode *inode)
1278{
1279 struct dentry *dentry;
1280
Nick Piggin873feea2011-01-07 17:50:06 +11001281 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -04001282 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001283 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +11001284 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001285 return true;
1286 }
1287 }
Nick Piggin873feea2011-01-07 17:50:06 +11001288 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001289 return false;
1290}
1291
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001292/* Given fattrs, get a corresponding inode */
1293struct inode *
1294cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
1295{
1296 unsigned long hash;
1297 struct inode *inode;
1298
Jeff Layton3d694382010-05-11 14:59:55 -04001299retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -05001300 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001301
1302 /* hash down to 32-bits on 32-bit arch */
1303 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
1304
1305 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001306 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001307 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -04001308 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -04001309 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -04001310
1311 if (inode_has_hashed_dentries(inode)) {
1312 cifs_autodisable_serverino(CIFS_SB(sb));
1313 iput(inode);
1314 fattr->cf_uniqueid = iunique(sb, ROOT_I);
1315 goto retry_iget5_locked;
1316 }
Jeff Layton3d694382010-05-11 14:59:55 -04001317 }
1318
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001319 cifs_fattr_to_inode(inode, fattr);
Linus Torvalds1751e8a2017-11-27 13:05:09 -08001320 if (sb->s_flags & SB_NOATIME)
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001321 inode->i_flags |= S_NOATIME | S_NOCMTIME;
1322 if (inode->i_state & I_NEW) {
1323 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +00001324#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301325 /* initialize per-inode cache cookie pointer */
1326 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +00001327#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001328 unlock_new_inode(inode);
1329 }
1330 }
1331
1332 return inode;
1333}
1334
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001336struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001338 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001339 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001340 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001341 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001342 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001343 char *path = NULL;
1344 int len;
1345
1346 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1347 && cifs_sb->prepath) {
1348 len = strlen(cifs_sb->prepath);
1349 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1350 if (path == NULL)
1351 return ERR_PTR(-ENOMEM);
1352 path[0] = '/';
1353 memcpy(path+1, cifs_sb->prepath, len);
1354 } else {
1355 path = kstrdup("", GFP_KERNEL);
1356 if (path == NULL)
1357 return ERR_PTR(-ENOMEM);
1358 }
David Howellsce634ab2008-02-07 00:15:33 -08001359
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001360 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001361 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001362 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001363 /* some servers mistakenly claim POSIX support */
1364 if (rc != -EOPNOTSUPP)
1365 goto iget_no_retry;
Joe Perchesa0a30362020-04-14 22:42:53 -07001366 cifs_dbg(VFS, "server does not support POSIX extensions\n");
Steve Frenchb5b374e2014-10-06 01:01:03 -05001367 tcon->unix_ext = false;
1368 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001369
Aurelien Aptela6b50582016-05-25 19:59:09 +02001370 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
Steve Frenchd3138522020-06-11 22:43:01 -05001371 if (tcon->posix_extensions)
1372 rc = smb311_posix_get_inode_info(&inode, path, sb, xid);
1373 else
1374 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001375
1376iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001377 if (!inode) {
1378 inode = ERR_PTR(rc);
1379 goto out;
1380 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001381
Steve French0ccd4802010-07-16 04:31:02 +00001382#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301383 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001384 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001385#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301386
Aurelien Aptelb327a712018-01-24 13:46:10 +01001387 if (rc && tcon->pipe) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001388 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001389 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001390 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001391 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001392 inode->i_op = &cifs_ipc_inode_ops;
1393 inode->i_fop = &simple_dir_operations;
Ronnie Sahlberg8401e932020-12-12 13:40:50 -06001394 inode->i_uid = cifs_sb->ctx->linux_uid;
1395 inode->i_gid = cifs_sb->ctx->linux_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001396 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001397 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001398 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001399 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001400 }
1401
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001402out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001403 kfree(path);
Phillip Potter31cd1062018-03-17 21:06:56 +00001404 free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001405 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406}
1407
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001408int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001409cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Al Virof6f1f172021-03-18 15:44:05 -04001410 const char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001411{
Steve French388e57b2008-09-16 23:50:58 +00001412 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001413 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001414 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001415 FILE_BASIC_INFO info_buf;
1416
Steve French1adcb712009-02-25 14:19:56 +00001417 if (attrs == NULL)
1418 return -EINVAL;
1419
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001420 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1421 if (!server->ops->set_file_info)
1422 return -ENOSYS;
1423
Steve Frenchfd09b7d2018-08-02 20:28:18 -05001424 info_buf.Pad = 0;
1425
Steve French388e57b2008-09-16 23:50:58 +00001426 if (attrs->ia_valid & ATTR_ATIME) {
1427 set_time = true;
1428 info_buf.LastAccessTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001429 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
Steve French388e57b2008-09-16 23:50:58 +00001430 } else
1431 info_buf.LastAccessTime = 0;
1432
1433 if (attrs->ia_valid & ATTR_MTIME) {
1434 set_time = true;
1435 info_buf.LastWriteTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001436 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
Steve French388e57b2008-09-16 23:50:58 +00001437 } else
1438 info_buf.LastWriteTime = 0;
1439
1440 /*
1441 * Samba throws this field away, but windows may actually use it.
1442 * Do not set ctime unless other time stamps are changed explicitly
1443 * (i.e. by utimes()) since we would then have a mix of client and
1444 * server times.
1445 */
1446 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001447 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001448 info_buf.ChangeTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001449 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
Steve French388e57b2008-09-16 23:50:58 +00001450 } else
1451 info_buf.ChangeTime = 0;
1452
1453 info_buf.CreationTime = 0; /* don't change */
1454 info_buf.Attributes = cpu_to_le32(dosattr);
1455
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001456 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001457}
1458
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001459/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001460 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001461 * and rename it to a random name that hopefully won't conflict with
1462 * anything else.
1463 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001464int
1465cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1466 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001467{
1468 int oplock = 0;
1469 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001470 struct cifs_fid fid;
1471 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001472 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001473 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1474 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001475 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001476 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001477 __u32 dosattr, origattr;
1478 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001479
Jeff Layton7ffec372010-09-29 19:51:11 -04001480 tlink = cifs_sb_tlink(cifs_sb);
1481 if (IS_ERR(tlink))
1482 return PTR_ERR(tlink);
1483 tcon = tlink_tcon(tlink);
1484
Sachin Prabhuc483a982013-03-05 19:25:56 +00001485 /*
1486 * We cannot rename the file if the server doesn't support
1487 * CAP_INFOLEVEL_PASSTHRU
1488 */
1489 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1490 rc = -EBUSY;
1491 goto out;
1492 }
1493
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001494 oparms.tcon = tcon;
1495 oparms.cifs_sb = cifs_sb;
1496 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
Amir Goldstein0f060932020-02-03 21:46:43 +02001497 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001498 oparms.disposition = FILE_OPEN;
1499 oparms.path = full_path;
1500 oparms.fid = &fid;
1501 oparms.reconnect = false;
1502
1503 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001504 if (rc != 0)
1505 goto out;
1506
Steve French32709582008-10-20 00:44:19 +00001507 origattr = cifsInode->cifsAttrs;
1508 if (origattr == 0)
1509 origattr |= ATTR_NORMAL;
1510
1511 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001512 if (dosattr == 0)
1513 dosattr |= ATTR_NORMAL;
1514 dosattr |= ATTR_HIDDEN;
1515
Steve French32709582008-10-20 00:44:19 +00001516 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1517 if (dosattr != origattr) {
1518 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1519 if (info_buf == NULL) {
1520 rc = -ENOMEM;
1521 goto out_close;
1522 }
1523 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001524 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001525 current->tgid);
1526 /* although we would like to mark the file hidden
1527 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001528 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001529 cifsInode->cifsAttrs = dosattr;
1530 else
1531 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001532 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001533
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001534 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001535 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1536 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001537 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001538 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001539 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001540 goto undo_setattr;
1541 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001542
Steve French32709582008-10-20 00:44:19 +00001543 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001544 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001545 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001546 current->tgid);
1547 /*
1548 * some samba versions return -ENOENT when we try to set the
1549 * file disposition here. Likely a samba bug, but work around
1550 * it for now. This means that some cifsXXX files may hang
1551 * around after they shouldn't.
1552 *
1553 * BB: remove this hack after more servers have the fix
1554 */
1555 if (rc == -ENOENT)
1556 rc = 0;
1557 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001558 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001559 goto undo_rename;
1560 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001561 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001562 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001563
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001564out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001565 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001566out:
Steve French32709582008-10-20 00:44:19 +00001567 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001568 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001569 return rc;
Steve French32709582008-10-20 00:44:19 +00001570
1571 /*
1572 * reset everything back to the original state. Don't bother
1573 * dealing with errors here since we can't do anything about
1574 * them anyway.
1575 */
1576undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001577 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001578 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001579undo_setattr:
1580 if (dosattr != origattr) {
1581 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001582 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001583 current->tgid))
1584 cifsInode->cifsAttrs = origattr;
1585 }
1586
1587 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001588}
1589
Steve Frenchb7ca6922012-08-03 08:43:01 -05001590/* copied from fs/nfs/dir.c with small changes */
1591static void
1592cifs_drop_nlink(struct inode *inode)
1593{
1594 spin_lock(&inode->i_lock);
1595 if (inode->i_nlink > 0)
1596 drop_nlink(inode);
1597 spin_unlock(&inode->i_lock);
1598}
Steve Frenchff694522009-04-20 19:45:13 +00001599
1600/*
David Howells2b0143b2015-03-17 22:25:59 +00001601 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001602 * is a negative dentry) then we would attempt a standard SMB delete, but
Colin Ian King413d6102018-10-26 19:07:21 +01001603 * if that fails we can not attempt the fall back mechanisms on EACCES
1604 * but will return the EACCES to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001605 * unlink on negative dentries currently.
1606 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001607int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608{
1609 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001610 unsigned int xid;
Al Virof6a9bc32021-03-05 17:36:04 -05001611 const char *full_path;
1612 void *page;
David Howells2b0143b2015-03-17 22:25:59 +00001613 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001614 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001615 struct super_block *sb = dir->i_sb;
1616 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001617 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001618 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001619 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001620 struct iattr *attrs = NULL;
1621 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
Joe Perchesf96637b2013-05-04 22:12:25 -05001623 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
Steve French087f7572021-04-29 00:18:43 -05001625 if (unlikely(cifs_forced_shutdown(cifs_sb)))
1626 return -EIO;
1627
Jeff Layton7ffec372010-09-29 19:51:11 -04001628 tlink = cifs_sb_tlink(cifs_sb);
1629 if (IS_ERR(tlink))
1630 return PTR_ERR(tlink);
1631 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001632 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001633
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001634 xid = get_xid();
Al Virof6a9bc32021-03-05 17:36:04 -05001635 page = alloc_dentry_path();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636
Steve French82e93672020-05-19 03:06:57 -05001637 if (tcon->nodelete) {
1638 rc = -EACCES;
1639 goto unlink_out;
1640 }
1641
Jeff Layton5f0319a2008-09-16 14:05:16 -04001642 /* Unlink can be called from rename so we can not take the
1643 * sb->s_vfs_rename_mutex here */
Al Virof6a9bc32021-03-05 17:36:04 -05001644 full_path = build_path_from_dentry(dentry, page);
1645 if (IS_ERR(full_path)) {
1646 rc = PTR_ERR(full_path);
Jeff Layton7ffec372010-09-29 19:51:11 -04001647 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 }
Steve French2d785a52007-07-15 01:48:57 +00001649
Rohith Surabattulac3f207a2021-04-13 00:26:42 -05001650 cifs_close_deferred_file(CIFS_I(inode));
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001651 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1652 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001653 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001654 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001655 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001656 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001657 if ((rc == 0) || (rc == -ENOENT))
1658 goto psx_del_no_retry;
1659 }
1660
Steve French60502472008-10-07 18:42:52 +00001661retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001662 if (!server->ops->unlink) {
1663 rc = -ENOSYS;
1664 goto psx_del_no_retry;
1665 }
1666
1667 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001668
Steve French2d785a52007-07-15 01:48:57 +00001669psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001671 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001672 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001674 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001675 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001676 if (server->ops->rename_pending_delete) {
1677 rc = server->ops->rename_pending_delete(full_path,
1678 dentry, xid);
1679 if (rc == 0)
1680 cifs_drop_nlink(inode);
1681 }
Steve Frenchff694522009-04-20 19:45:13 +00001682 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001683 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1684 if (attrs == NULL) {
1685 rc = -ENOMEM;
1686 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 }
Steve French388e57b2008-09-16 23:50:58 +00001688
1689 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001690 cifs_inode = CIFS_I(inode);
1691 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001692 if (origattr == 0)
1693 origattr |= ATTR_NORMAL;
1694 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001695 if (dosattr == 0)
1696 dosattr |= ATTR_NORMAL;
1697 dosattr |= ATTR_HIDDEN;
1698
1699 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001700 if (rc != 0)
1701 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001702
1703 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 }
Steve French60502472008-10-07 18:42:52 +00001705
1706 /* undo the setattr if we errored out and it's needed */
1707 if (rc != 0 && dosattr != 0)
1708 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1709
Steve French388e57b2008-09-16 23:50:58 +00001710out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001711 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001712 cifs_inode = CIFS_I(inode);
1713 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001714 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001715 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001716 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001717 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001718 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001719 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001720unlink_out:
Al Virof6a9bc32021-03-05 17:36:04 -05001721 free_dentry_path(page);
Steve French60502472008-10-07 18:42:52 +00001722 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001723 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001724 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 return rc;
1726}
1727
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001728static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001729cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001730 const char *full_path, struct cifs_sb_info *cifs_sb,
1731 struct cifs_tcon *tcon, const unsigned int xid)
1732{
1733 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001734 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001735
Steve Frenchd3138522020-06-11 22:43:01 -05001736 if (tcon->posix_extensions)
1737 rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
1738 else if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001739 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001740 xid);
1741 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001742 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1743 xid, NULL);
1744
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001745 if (rc)
1746 return rc;
1747
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001748 /*
1749 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001750 * from the server or was set bogus. Also, since this is a brand new
1751 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001752 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001753 if (inode->i_nlink < 2)
1754 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001755 mode &= ~current_umask();
1756 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001757 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001758 mode |= S_ISGID;
1759
1760 if (tcon->unix_ext) {
1761 struct cifs_unix_set_info_args args = {
1762 .mode = mode,
1763 .ctime = NO_CHANGE_64,
1764 .atime = NO_CHANGE_64,
1765 .mtime = NO_CHANGE_64,
1766 .device = 0,
1767 };
1768 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001769 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001770 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001771 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001772 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001773 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001774 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001775 args.uid = INVALID_UID; /* no change */
1776 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001777 }
1778 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1779 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001780 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001781 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001782 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001783 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001784 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001785 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001786 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001787 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1788 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001789
Jeff Layton101b92d2012-09-19 06:22:45 -07001790 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1791 inode->i_uid = current_fsuid();
1792 if (inode->i_mode & S_ISGID)
1793 inode->i_gid = parent->i_gid;
1794 else
1795 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001796 }
1797 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001798 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001799 return rc;
1800}
1801
1802static int
1803cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1804 const char *full_path, struct cifs_sb_info *cifs_sb,
1805 struct cifs_tcon *tcon, const unsigned int xid)
1806{
1807 int rc = 0;
1808 u32 oplock = 0;
1809 FILE_UNIX_BASIC_INFO *info = NULL;
1810 struct inode *newinode = NULL;
1811 struct cifs_fattr fattr;
1812
1813 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1814 if (info == NULL) {
1815 rc = -ENOMEM;
1816 goto posix_mkdir_out;
1817 }
1818
1819 mode &= ~current_umask();
1820 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1821 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001822 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001823 if (rc == -EOPNOTSUPP)
1824 goto posix_mkdir_out;
1825 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001826 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001827 d_drop(dentry);
1828 goto posix_mkdir_out;
1829 }
1830
1831 if (info->Type == cpu_to_le32(-1))
1832 /* no return info, go query for it */
1833 goto posix_mkdir_get_info;
1834 /*
1835 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1836 * need to set uid/gid.
1837 */
1838
1839 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1840 cifs_fill_uniqueid(inode->i_sb, &fattr);
1841 newinode = cifs_iget(inode->i_sb, &fattr);
1842 if (!newinode)
1843 goto posix_mkdir_get_info;
1844
1845 d_instantiate(dentry, newinode);
1846
1847#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001848 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1849 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001850
1851 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001852 cifs_dbg(FYI, "unexpected number of links %d\n",
1853 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001854#endif
1855
1856posix_mkdir_out:
1857 kfree(info);
1858 return rc;
1859posix_mkdir_get_info:
1860 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1861 xid);
1862 goto posix_mkdir_out;
1863}
1864
Christian Brauner549c7292021-01-21 14:19:43 +01001865int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode,
1866 struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001868 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001869 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001871 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001872 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001873 struct TCP_Server_Info *server;
Al Viro8e33cf22021-03-18 15:47:35 -04001874 const char *full_path;
Al Virof6a9bc32021-03-05 17:36:04 -05001875 void *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
Frank Sorensonf52aa792020-02-12 15:31:48 -06001877 cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05001878 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 cifs_sb = CIFS_SB(inode->i_sb);
Steve French087f7572021-04-29 00:18:43 -05001881 if (unlikely(cifs_forced_shutdown(cifs_sb)))
1882 return -EIO;
Jeff Layton7ffec372010-09-29 19:51:11 -04001883 tlink = cifs_sb_tlink(cifs_sb);
1884 if (IS_ERR(tlink))
1885 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001886 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001887
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001888 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889
Al Virof6a9bc32021-03-05 17:36:04 -05001890 page = alloc_dentry_path();
1891 full_path = build_path_from_dentry(direntry, page);
1892 if (IS_ERR(full_path)) {
1893 rc = PTR_ERR(full_path);
Jeff Layton7ffec372010-09-29 19:51:11 -04001894 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 }
Steve French50c2f752007-07-13 00:33:32 +00001896
Steve Frenchbea851b2018-06-14 21:56:32 -05001897 server = tcon->ses->server;
1898
Steve Frenchbea851b2018-06-14 21:56:32 -05001899 if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
1900 rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
1901 cifs_sb);
1902 d_drop(direntry); /* for time being always refresh inode info */
1903 goto mkdir_out;
1904 }
Steve Frenchbea851b2018-06-14 21:56:32 -05001905
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001906 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1907 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001908 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1909 tcon, xid);
1910 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001911 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001912 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001913
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001914 if (!server->ops->mkdir) {
1915 rc = -ENOSYS;
1916 goto mkdir_out;
1917 }
1918
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001920 rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001922 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001924 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001926
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001927 /* TODO: skip this for smb2/smb3 */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001928 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1929 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001930mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001931 /*
1932 * Force revalidate to get parent dir info when needed since cached
1933 * attributes are invalid now.
1934 */
1935 CIFS_I(inode)->time = 0;
Al Virof6a9bc32021-03-05 17:36:04 -05001936 free_dentry_path(page);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001937 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001938 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 return rc;
1940}
1941
1942int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1943{
1944 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001945 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001947 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001948 struct cifs_tcon *tcon;
1949 struct TCP_Server_Info *server;
Al Virof6a9bc32021-03-05 17:36:04 -05001950 const char *full_path;
1951 void *page = alloc_dentry_path();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 struct cifsInodeInfo *cifsInode;
1953
Joe Perchesf96637b2013-05-04 22:12:25 -05001954 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001956 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957
Al Virof6a9bc32021-03-05 17:36:04 -05001958 full_path = build_path_from_dentry(direntry, page);
1959 if (IS_ERR(full_path)) {
1960 rc = PTR_ERR(full_path);
Jeff Layton7ffec372010-09-29 19:51:11 -04001961 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 }
1963
Jeff Layton7ffec372010-09-29 19:51:11 -04001964 cifs_sb = CIFS_SB(inode->i_sb);
Steve French087f7572021-04-29 00:18:43 -05001965 if (unlikely(cifs_forced_shutdown(cifs_sb))) {
1966 rc = -EIO;
1967 goto rmdir_exit;
1968 }
1969
Jeff Layton7ffec372010-09-29 19:51:11 -04001970 tlink = cifs_sb_tlink(cifs_sb);
1971 if (IS_ERR(tlink)) {
1972 rc = PTR_ERR(tlink);
1973 goto rmdir_exit;
1974 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001975 tcon = tlink_tcon(tlink);
1976 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001977
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001978 if (!server->ops->rmdir) {
1979 rc = -ENOSYS;
1980 cifs_put_tlink(tlink);
1981 goto rmdir_exit;
1982 }
1983
Steve French82e93672020-05-19 03:06:57 -05001984 if (tcon->nodelete) {
1985 rc = -EACCES;
1986 cifs_put_tlink(tlink);
1987 goto rmdir_exit;
1988 }
1989
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001990 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001991 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
1993 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001994 spin_lock(&d_inode(direntry)->i_lock);
1995 i_size_write(d_inode(direntry), 0);
1996 clear_nlink(d_inode(direntry));
1997 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 }
1999
David Howells2b0143b2015-03-17 22:25:59 +00002000 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03002001 /* force revalidate to go get info when needed */
2002 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00002003
2004 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03002005 /*
2006 * Force revalidate to get parent dir info when needed since cached
2007 * attributes are invalid now.
2008 */
2009 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00002010
David Howells2b0143b2015-03-17 22:25:59 +00002011 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07002012 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
Jeff Layton7ffec372010-09-29 19:51:11 -04002014rmdir_exit:
Al Virof6a9bc32021-03-05 17:36:04 -05002015 free_dentry_path(page);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002016 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 return rc;
2018}
2019
Steve Frenchee2fd962008-09-23 18:23:33 +00002020static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002021cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
2022 const char *from_path, struct dentry *to_dentry,
2023 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00002024{
2025 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002026 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002027 struct cifs_tcon *tcon;
2028 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002029 struct cifs_fid fid;
2030 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00002031 int oplock, rc;
2032
Jeff Layton7ffec372010-09-29 19:51:11 -04002033 tlink = cifs_sb_tlink(cifs_sb);
2034 if (IS_ERR(tlink))
2035 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002036 tcon = tlink_tcon(tlink);
2037 server = tcon->ses->server;
2038
2039 if (!server->ops->rename)
2040 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04002041
Steve Frenchee2fd962008-09-23 18:23:33 +00002042 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002043 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00002044
2045 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002046 * Don't bother with rename by filehandle unless file is busy and
2047 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00002048 * rename by filehandle to various Windows servers.
2049 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00002050 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04002051 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00002052
Frank Sorenson652727b2019-04-16 08:37:27 -05002053 /* Don't fall back to using SMB on SMB 2+ mount */
2054 if (server->vals->protocol_id != 0)
2055 goto do_rename_exit;
2056
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04002057 /* open-file renames don't work across directories */
2058 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04002059 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04002060
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002061 oparms.tcon = tcon;
2062 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00002063 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002064 oparms.desired_access = DELETE;
Amir Goldstein0f060932020-02-03 21:46:43 +02002065 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002066 oparms.disposition = FILE_OPEN;
2067 oparms.path = from_path;
2068 oparms.fid = &fid;
2069 oparms.reconnect = false;
2070
2071 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00002072 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002073 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00002074 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05002075 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002076 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00002077 }
Jeff Layton7ffec372010-09-29 19:51:11 -04002078do_rename_exit:
Steve Frenchc7e9f782020-02-25 18:08:54 -06002079 if (rc == 0)
2080 d_move(from_dentry, to_dentry);
Jeff Layton7ffec372010-09-29 19:51:11 -04002081 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00002082 return rc;
2083}
2084
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002085int
Christian Brauner549c7292021-01-21 14:19:43 +01002086cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
2087 struct dentry *source_dentry, struct inode *target_dir,
2088 struct dentry *target_dentry, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089{
Al Virof6a9bc32021-03-05 17:36:04 -05002090 const char *from_name, *to_name;
2091 void *page1, *page2;
Jeff Layton639e7a92010-09-03 11:50:09 -04002092 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04002093 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002094 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00002095 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
2096 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002097 unsigned int xid;
2098 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002100 if (flags & ~RENAME_NOREPLACE)
2101 return -EINVAL;
2102
Jeff Layton639e7a92010-09-03 11:50:09 -04002103 cifs_sb = CIFS_SB(source_dir->i_sb);
Steve French087f7572021-04-29 00:18:43 -05002104 if (unlikely(cifs_forced_shutdown(cifs_sb)))
2105 return -EIO;
2106
Jeff Layton7ffec372010-09-29 19:51:11 -04002107 tlink = cifs_sb_tlink(cifs_sb);
2108 if (IS_ERR(tlink))
2109 return PTR_ERR(tlink);
2110 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111
Al Virof6a9bc32021-03-05 17:36:04 -05002112 page1 = alloc_dentry_path();
2113 page2 = alloc_dentry_path();
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002114 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00002115
Al Virof6a9bc32021-03-05 17:36:04 -05002116 from_name = build_path_from_dentry(source_dentry, page1);
2117 if (IS_ERR(from_name)) {
2118 rc = PTR_ERR(from_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 goto cifs_rename_exit;
2120 }
2121
Al Virof6a9bc32021-03-05 17:36:04 -05002122 to_name = build_path_from_dentry(target_dentry, page2);
2123 if (IS_ERR(to_name)) {
2124 rc = PTR_ERR(to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00002125 goto cifs_rename_exit;
2126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002128 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
2129 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00002130
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002131 /*
2132 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
2133 */
2134 if (flags & RENAME_NOREPLACE)
2135 goto cifs_rename_exit;
2136
Jeff Layton14121bd2008-10-20 14:45:22 -04002137 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00002138 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002139 * Are src and dst hardlinks of same inode? We can only tell
2140 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00002141 */
Jeff Layton14121bd2008-10-20 14:45:22 -04002142 info_buf_source =
Kees Cook6da2ec52018-06-12 13:55:00 -07002143 kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
Jeff Layton14121bd2008-10-20 14:45:22 -04002144 GFP_KERNEL);
2145 if (info_buf_source == NULL) {
2146 rc = -ENOMEM;
2147 goto cifs_rename_exit;
2148 }
2149
2150 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002151 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
2152 info_buf_source,
2153 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002154 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04002155 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04002156 goto unlink_target;
2157
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002158 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
2159 info_buf_target,
2160 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002161 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04002162
Jeff Layton8d281ef2008-10-22 13:57:01 -04002163 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05002164 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04002165 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05002166 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04002167 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05002168 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002169 }
2170 /*
2171 * else ... BB we could add the same check for Windows by
2172 * checking the UniqueId via FILE_INTERNAL_INFO
2173 */
Jeff Layton14121bd2008-10-20 14:45:22 -04002174
Jeff Layton14121bd2008-10-20 14:45:22 -04002175unlink_target:
Steve French0e670512020-07-23 14:41:29 -05002176 /* Try unlinking the target dentry if it's not negative */
2177 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04002178 if (d_is_dir(target_dentry))
2179 tmprc = cifs_rmdir(target_dir, target_dentry);
2180 else
2181 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04002182 if (tmprc)
2183 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002184 rc = cifs_do_rename(xid, source_dentry, from_name,
2185 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 }
2187
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04002188 /* force revalidate to go get info when needed */
2189 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
2190
2191 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07002192 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04002193
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00002195 kfree(info_buf_source);
Al Virof6a9bc32021-03-05 17:36:04 -05002196 free_dentry_path(page2);
2197 free_dentry_path(page1);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002198 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04002199 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 return rc;
2201}
2202
Jeff Laytondf2cf172010-02-12 07:44:16 -05002203static bool
Ronnie Sahlberged8561f2021-03-09 09:07:34 +10002204cifs_dentry_needs_reval(struct dentry *dentry)
Jeff Laytondf2cf172010-02-12 07:44:16 -05002205{
Ronnie Sahlberged8561f2021-03-09 09:07:34 +10002206 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002207 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302208 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Ronnie Sahlbergf6d23532021-03-09 09:07:35 +10002209 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2210 struct cached_fid *cfid = NULL;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002211
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002212 if (cifs_i->time == 0)
2213 return true;
2214
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002215 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05002216 return false;
2217
2218 if (!lookupCacheEnabled)
2219 return true;
2220
Ronnie Sahlbergf6d23532021-03-09 09:07:35 +10002221 if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {
2222 mutex_lock(&cfid->fid_mutex);
2223 if (cfid->time && cifs_i->time > cfid->time) {
2224 mutex_unlock(&cfid->fid_mutex);
2225 close_cached_dir(cfid);
2226 return false;
2227 }
2228 mutex_unlock(&cfid->fid_mutex);
2229 close_cached_dir(cfid);
2230 }
Steve Frenchddaf6d42021-02-23 16:16:09 -06002231 /*
2232 * depending on inode type, check if attribute caching disabled for
2233 * files or directories
2234 */
2235 if (S_ISDIR(inode->i_mode)) {
2236 if (!cifs_sb->ctx->acdirmax)
2237 return true;
2238 if (!time_in_range(jiffies, cifs_i->time,
2239 cifs_i->time + cifs_sb->ctx->acdirmax))
2240 return true;
2241 } else { /* file */
Steve French57804642021-02-24 12:12:53 -06002242 if (!cifs_sb->ctx->acregmax)
Steve Frenchddaf6d42021-02-23 16:16:09 -06002243 return true;
2244 if (!time_in_range(jiffies, cifs_i->time,
Steve French57804642021-02-24 12:12:53 -06002245 cifs_i->time + cifs_sb->ctx->acregmax))
Steve Frenchddaf6d42021-02-23 16:16:09 -06002246 return true;
2247 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05002248
Jeff Laytondb192722010-05-17 14:51:49 -04002249 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302250 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04002251 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
2252 return true;
2253
Jeff Laytondf2cf172010-02-12 07:44:16 -05002254 return false;
2255}
2256
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05302257/*
2258 * Zap the cache. Called when invalid_mapping flag is set.
2259 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002260int
Jeff Laytondf2cf172010-02-12 07:44:16 -05002261cifs_invalidate_mapping(struct inode *inode)
2262{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002263 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002264
Jeff Laytondf2cf172010-02-12 07:44:16 -05002265 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002266 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002267 if (rc)
Joe Perchesa0a30362020-04-14 22:42:53 -07002268 cifs_dbg(VFS, "%s: Could not invalidate inode %p\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05002269 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002270 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002271
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05302272 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002273 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002274}
2275
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002276/**
2277 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
Steve French607dfc72020-12-12 12:08:58 -06002278 *
2279 * @key: currently unused
2280 * @mode: the task state to sleep in
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002281 */
2282static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002283cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002284{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002285 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002286 if (signal_pending_state(mode, current))
2287 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002288 return 0;
2289}
2290
Jeff Laytone284e532014-04-30 09:31:46 -04002291int
2292cifs_revalidate_mapping(struct inode *inode)
2293{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002294 int rc;
2295 unsigned long *flags = &CIFS_I(inode)->flags;
2296
Steve French4e8aea32020-04-09 21:42:18 -05002297 /* swapfiles are not supposed to be shared */
2298 if (IS_SWAPFILE(inode))
2299 return 0;
2300
NeilBrown74316202014-07-07 15:16:04 +10002301 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
2302 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002303 if (rc)
2304 return rc;
2305
2306 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
2307 rc = cifs_invalidate_mapping(inode);
2308 if (rc)
2309 set_bit(CIFS_INO_INVALID_MAPPING, flags);
2310 }
2311
2312 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07002313 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002314 wake_up_bit(flags, CIFS_INO_LOCK);
2315
2316 return rc;
2317}
2318
2319int
2320cifs_zap_mapping(struct inode *inode)
2321{
2322 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
2323 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04002324}
2325
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002326int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05002327{
2328 int rc = 0;
Ronnie Sahlberged8561f2021-03-09 09:07:34 +10002329 struct dentry *dentry = file_dentry(filp);
Jeff Laytonba00ba642010-09-20 16:01:31 -07002330 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05002331
Ronnie Sahlberged8561f2021-03-09 09:07:34 +10002332 if (!cifs_dentry_needs_reval(dentry))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002333 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05002334
Jeff Layton13cfb732010-09-29 19:51:11 -04002335 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05002336 rc = cifs_get_file_info_unix(filp);
2337 else
2338 rc = cifs_get_file_info(filp);
2339
Jeff Laytonabab0952010-02-12 07:44:18 -05002340 return rc;
2341}
2342
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002343int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002345 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002346 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00002347 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002348 struct super_block *sb = dentry->d_sb;
Al Virof6a9bc32021-03-05 17:36:04 -05002349 const char *full_path;
2350 void *page;
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002351 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352
Jeff Laytondf2cf172010-02-12 07:44:16 -05002353 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 return -ENOENT;
2355
Ronnie Sahlberged8561f2021-03-09 09:07:34 +10002356 if (!cifs_dentry_needs_reval(dentry))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002357 return rc;
2358
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002359 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360
Al Virof6a9bc32021-03-05 17:36:04 -05002361 page = alloc_dentry_path();
2362 full_path = build_path_from_dentry(dentry, page);
2363 if (IS_ERR(full_path)) {
2364 rc = PTR_ERR(full_path);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002365 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05002367
Joe Perchesf96637b2013-05-04 22:12:25 -05002368 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
2369 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02002370 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002372again:
Steve French6a5f6592020-06-11 19:25:47 -05002373 if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
2374 rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
2375 else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05002376 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
2377 else
2378 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
2379 xid, NULL);
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002380 if (rc == -EAGAIN && count++ < 10)
2381 goto again;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002382out:
Al Virof6a9bc32021-03-05 17:36:04 -05002383 free_dentry_path(page);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002384 free_xid(xid);
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002385
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 return rc;
2387}
2388
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002389int cifs_revalidate_file(struct file *filp)
2390{
2391 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002392 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002393
2394 rc = cifs_revalidate_file_attr(filp);
2395 if (rc)
2396 return rc;
2397
Jeff Laytone284e532014-04-30 09:31:46 -04002398 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002399}
2400
2401/* revalidate a dentry's inode attributes */
2402int cifs_revalidate_dentry(struct dentry *dentry)
2403{
2404 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002405 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002406
2407 rc = cifs_revalidate_dentry_attr(dentry);
2408 if (rc)
2409 return rc;
2410
Jeff Laytone284e532014-04-30 09:31:46 -04002411 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002412}
2413
Christian Brauner549c7292021-01-21 14:19:43 +01002414int cifs_getattr(struct user_namespace *mnt_userns, const struct path *path,
2415 struct kstat *stat, u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416{
David Howellsa528d352017-01-31 16:46:22 +00002417 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002418 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002419 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002420 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002421 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002422
Steve French087f7572021-04-29 00:18:43 -05002423 if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
2424 return -EIO;
2425
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002426 /*
2427 * We need to be sure that all dirty pages are written and the server
2428 * has actual ctime, mtime and file length.
2429 */
Steve French65af8f02021-03-19 00:05:48 -05002430 if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE | STATX_BLOCKS)) &&
Steve Frenchffdec8d2020-02-18 18:07:57 -06002431 !CIFS_CACHE_READ(CIFS_I(inode)) &&
2432 inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002433 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002434 if (rc) {
2435 mapping_set_error(inode->i_mapping, rc);
2436 return rc;
2437 }
Steve French5fe14c82006-11-07 19:26:33 +00002438 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002439
Steve Frenchffdec8d2020-02-18 18:07:57 -06002440 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC)
2441 CIFS_I(inode)->time = 0; /* force revalidate */
2442
2443 /*
2444 * If the caller doesn't require syncing, only sync if
2445 * necessary (e.g. due to earlier truncate or setattr
2446 * invalidating the cached metadata)
2447 */
2448 if (((flags & AT_STATX_SYNC_TYPE) != AT_STATX_DONT_SYNC) ||
2449 (CIFS_I(inode)->time == 0)) {
2450 rc = cifs_revalidate_dentry_attr(dentry);
2451 if (rc)
2452 return rc;
2453 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002454
Christian Brauner0d56a452021-01-21 14:19:30 +01002455 generic_fillattr(&init_user_ns, inode, stat);
Ronnie Sahlberg522aa3b2020-12-14 16:40:17 +10002456 stat->blksize = cifs_sb->ctx->bsize;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002457 stat->ino = CIFS_I(inode)->uniqueid;
2458
Steve French6e70e262017-09-21 21:32:29 -05002459 /* old CIFS Unix Extensions doesn't return create time */
2460 if (CIFS_I(inode)->createtime) {
2461 stat->result_mask |= STATX_BTIME;
Arnd Bergmann95390202018-06-19 17:27:58 +02002462 stat->btime =
2463 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
Steve French6e70e262017-09-21 21:32:29 -05002464 }
2465
2466 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2467 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2468 stat->attributes |= STATX_ATTR_COMPRESSED;
2469 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2470 stat->attributes |= STATX_ATTR_ENCRYPTED;
2471
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002472 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002473 * If on a multiuser mount without unix extensions or cifsacl being
2474 * enabled, and the admin hasn't overridden them, set the ownership
2475 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002476 */
2477 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002478 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002479 !tcon->unix_ext) {
2480 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2481 stat->uid = current_fsuid();
2482 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2483 stat->gid = current_fsgid();
2484 }
Dan Carpenter39946882020-02-28 12:22:59 +03002485 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486}
2487
Ronnie Sahlberg2f3ebab2019-04-25 16:45:29 +10002488int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
2489 u64 len)
2490{
2491 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2492 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->vfs_inode.i_sb);
2493 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2494 struct TCP_Server_Info *server = tcon->ses->server;
2495 struct cifsFileInfo *cfile;
2496 int rc;
2497
Steve French087f7572021-04-29 00:18:43 -05002498 if (unlikely(cifs_forced_shutdown(cifs_sb)))
2499 return -EIO;
2500
Ronnie Sahlberg2f3ebab2019-04-25 16:45:29 +10002501 /*
2502 * We need to be sure that all dirty pages are written as they
2503 * might fill holes on the server.
2504 */
2505 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
2506 inode->i_mapping->nrpages != 0) {
2507 rc = filemap_fdatawait(inode->i_mapping);
2508 if (rc) {
2509 mapping_set_error(inode->i_mapping, rc);
2510 return rc;
2511 }
2512 }
2513
2514 cfile = find_readable_file(cifs_i, false);
2515 if (cfile == NULL)
2516 return -EINVAL;
2517
2518 if (server->ops->fiemap) {
2519 rc = server->ops->fiemap(tcon, cfile, fei, start, len);
2520 cifsFileInfo_put(cfile);
2521 return rc;
2522 }
2523
2524 cifsFileInfo_put(cfile);
2525 return -ENOTSUPP;
2526}
2527
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002528int cifs_truncate_page(struct address_space *mapping, loff_t from)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002530 pgoff_t index = from >> PAGE_SHIFT;
2531 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 int rc = 0;
2534
2535 page = grab_cache_page(mapping, index);
2536 if (!page)
2537 return -ENOMEM;
2538
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002539 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002541 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542 return rc;
2543}
2544
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002545void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002546{
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002547 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2548
Steve Frenchba6a46a2007-02-26 20:06:29 +00002549 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002550 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002551 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002552
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002553 /* Cached inode must be refreshed on truncate */
2554 cifs_i->time = 0;
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002555 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002556}
2557
Jeff Layton8efdbde2008-07-23 21:28:12 +00002558static int
2559cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Al Virof6f1f172021-03-18 15:44:05 -04002560 unsigned int xid, const char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002561{
2562 int rc;
2563 struct cifsFileInfo *open_file;
2564 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2565 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002566 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002567 struct cifs_tcon *tcon = NULL;
2568 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002569
2570 /*
2571 * To avoid spurious oplock breaks from server, in the case of
2572 * inodes that we already have open, avoid doing path based
2573 * setting of file size if we can do it by handle.
2574 * This keeps our caching token (oplock) and avoids timeouts
2575 * when the local oplock break takes longer to flush
2576 * writebehind data than the SMB timeout for the SetPathInfo
2577 * request would allow
2578 */
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002579 open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002580 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002581 tcon = tlink_tcon(open_file->tlink);
2582 server = tcon->ses->server;
2583 if (server->ops->set_file_size)
2584 rc = server->ops->set_file_size(xid, tcon, open_file,
2585 attrs->ia_size, false);
2586 else
2587 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002588 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002589 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002590 } else
2591 rc = -EINVAL;
2592
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002593 if (!rc)
2594 goto set_size_out;
Jeff Laytonba00ba642010-09-20 16:01:31 -07002595
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002596 if (tcon == NULL) {
2597 tlink = cifs_sb_tlink(cifs_sb);
2598 if (IS_ERR(tlink))
2599 return PTR_ERR(tlink);
2600 tcon = tlink_tcon(tlink);
2601 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002602 }
2603
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002604 /*
2605 * Set file size by pathname rather than by handle either because no
2606 * valid, writeable file handle for it was found or because there was
2607 * an error setting it by handle.
2608 */
2609 if (server->ops->set_path_size)
2610 rc = server->ops->set_path_size(xid, tcon, full_path,
2611 attrs->ia_size, cifs_sb, false);
2612 else
2613 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002614 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002615
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002616 if (tlink)
2617 cifs_put_tlink(tlink);
2618
2619set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002620 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002621 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002622 cifs_setsize(inode, attrs->ia_size);
Steve French65af8f02021-03-19 00:05:48 -05002623 /*
2624 * i_blocks is not related to (i_size / i_blksize), but instead
2625 * 512 byte (2**9) size is required for calculating num blocks.
2626 * Until we can query the server for actual allocation size,
2627 * this is best estimate we have for blocks allocated for a file
2628 * Number of blocks must be rounded up so size 1 is not 0 blocks
2629 */
2630 inode->i_blocks = (512 - 1 + attrs->ia_size) >> 9;
Zhang Xiaoxu56183032020-06-19 22:51:29 -04002631
2632 /*
2633 * The man page of truncate says if the size changed,
2634 * then the st_ctime and st_mtime fields for the file
2635 * are updated.
2636 */
2637 attrs->ia_ctime = attrs->ia_mtime = current_time(inode);
2638 attrs->ia_valid |= ATTR_CTIME | ATTR_MTIME;
2639
Jeff Layton8efdbde2008-07-23 21:28:12 +00002640 cifs_truncate_page(inode->i_mapping, inode->i_size);
2641 }
2642
2643 return rc;
2644}
2645
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002646static int
2647cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2648{
2649 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002650 unsigned int xid;
Al Virof6a9bc32021-03-05 17:36:04 -05002651 const char *full_path;
2652 void *page = alloc_dentry_path();
David Howells2b0143b2015-03-17 22:25:59 +00002653 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002654 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2655 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002656 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002657 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002658 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002659 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002660
Al Viro35c265e2014-08-19 20:25:34 -04002661 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2662 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002663
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002664 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002665
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002666 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2667 attrs->ia_valid |= ATTR_FORCE;
2668
Christian Brauner2f221d62021-01-21 14:19:26 +01002669 rc = setattr_prepare(&init_user_ns, direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002670 if (rc < 0)
2671 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002672
Al Virof6a9bc32021-03-05 17:36:04 -05002673 full_path = build_path_from_dentry(direntry, page);
2674 if (IS_ERR(full_path)) {
2675 rc = PTR_ERR(full_path);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002676 goto out;
2677 }
2678
Jeff Layton0f4d6342009-03-26 13:35:37 -04002679 /*
2680 * Attempt to flush data before changing attributes. We need to do
2681 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2682 * ownership or mode then we may also need to do this. Here, we take
2683 * the safe way out and just do the flush on all setattr requests. If
2684 * the flush returns error, store it to report later and continue.
2685 *
2686 * BB: This should be smarter. Why bother flushing pages that
2687 * will be truncated anyway? Also, should we error out here if
2688 * the flush returns error?
2689 */
2690 rc = filemap_write_and_wait(inode->i_mapping);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002691 if (is_interrupt_error(rc)) {
2692 rc = -ERESTARTSYS;
2693 goto out;
2694 }
2695
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002696 mapping_set_error(inode->i_mapping, rc);
2697 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002698
2699 if (attrs->ia_valid & ATTR_SIZE) {
2700 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2701 if (rc != 0)
2702 goto out;
2703 }
2704
2705 /* skip mode change if it's just for clearing setuid/setgid */
2706 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2707 attrs->ia_valid &= ~ATTR_MODE;
2708
2709 args = kmalloc(sizeof(*args), GFP_KERNEL);
2710 if (args == NULL) {
2711 rc = -ENOMEM;
2712 goto out;
2713 }
2714
2715 /* set up the struct */
2716 if (attrs->ia_valid & ATTR_MODE)
2717 args->mode = attrs->ia_mode;
2718 else
2719 args->mode = NO_CHANGE_64;
2720
2721 if (attrs->ia_valid & ATTR_UID)
2722 args->uid = attrs->ia_uid;
2723 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002724 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002725
2726 if (attrs->ia_valid & ATTR_GID)
2727 args->gid = attrs->ia_gid;
2728 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002729 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002730
2731 if (attrs->ia_valid & ATTR_ATIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002732 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002733 else
2734 args->atime = NO_CHANGE_64;
2735
2736 if (attrs->ia_valid & ATTR_MTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002737 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002738 else
2739 args->mtime = NO_CHANGE_64;
2740
2741 if (attrs->ia_valid & ATTR_CTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002742 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002743 else
2744 args->ctime = NO_CHANGE_64;
2745
2746 args->device = 0;
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002747 open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002748 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002749 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002750 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002751 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002752 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002753 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002754 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002755 tlink = cifs_sb_tlink(cifs_sb);
2756 if (IS_ERR(tlink)) {
2757 rc = PTR_ERR(tlink);
2758 goto out;
2759 }
2760 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002761 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002762 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002763 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002764 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002765 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002766
Christoph Hellwig10257742010-06-04 11:30:02 +02002767 if (rc)
2768 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002769
Christoph Hellwig10257742010-06-04 11:30:02 +02002770 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002771 attrs->ia_size != i_size_read(inode))
2772 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002773
Christian Brauner2f221d62021-01-21 14:19:26 +01002774 setattr_copy(&init_user_ns, inode, attrs);
Christoph Hellwig10257742010-06-04 11:30:02 +02002775 mark_inode_dirty(inode);
2776
2777 /* force revalidate when any of these times are set since some
2778 of the fs types (eg ext3, fat) do not have fine enough
2779 time granularity to match protocol, and we do not have a
2780 a way (yet) to query the server fs's time granularity (and
2781 whether it rounds times down).
2782 */
2783 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2784 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002785out:
2786 kfree(args);
Al Virof6a9bc32021-03-05 17:36:04 -05002787 free_dentry_path(page);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002788 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002789 return rc;
2790}
2791
Jeff Layton0510eeb2008-08-02 07:26:12 -04002792static int
2793cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002795 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002796 kuid_t uid = INVALID_UID;
2797 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002798 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002799 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002800 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002801 struct cifsFileInfo *wfile;
2802 struct cifs_tcon *tcon;
Al Virof6a9bc32021-03-05 17:36:04 -05002803 const char *full_path;
2804 void *page = alloc_dentry_path();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002806 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002807 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002808
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002809 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810
Colin Ian King63d614a2019-06-24 17:39:43 +01002811 cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
Al Viro35c265e2014-08-19 20:25:34 -04002812 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002813
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002814 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2815 attrs->ia_valid |= ATTR_FORCE;
2816
Christian Brauner2f221d62021-01-21 14:19:26 +01002817 rc = setattr_prepare(&init_user_ns, direntry, attrs);
Al Virof6a9bc32021-03-05 17:36:04 -05002818 if (rc < 0)
2819 goto cifs_setattr_exit;
Steve French50c2f752007-07-13 00:33:32 +00002820
Al Virof6a9bc32021-03-05 17:36:04 -05002821 full_path = build_path_from_dentry(direntry, page);
2822 if (IS_ERR(full_path)) {
2823 rc = PTR_ERR(full_path);
2824 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826
Jeff Layton0f4d6342009-03-26 13:35:37 -04002827 /*
2828 * Attempt to flush data before changing attributes. We need to do
Steve Frenchcf5371a2020-02-24 17:37:39 -06002829 * this for ATTR_SIZE and ATTR_MTIME. If the flush of the data
2830 * returns error, store it to report later and continue.
Jeff Layton0f4d6342009-03-26 13:35:37 -04002831 *
2832 * BB: This should be smarter. Why bother flushing pages that
2833 * will be truncated anyway? Also, should we error out here if
Steve Frenchcf5371a2020-02-24 17:37:39 -06002834 * the flush returns error? Do we need to check for ATTR_MTIME_SET flag?
Jeff Layton0f4d6342009-03-26 13:35:37 -04002835 */
Steve Frenchcf5371a2020-02-24 17:37:39 -06002836 if (attrs->ia_valid & (ATTR_MTIME | ATTR_SIZE | ATTR_CTIME)) {
2837 rc = filemap_write_and_wait(inode->i_mapping);
2838 if (is_interrupt_error(rc)) {
2839 rc = -ERESTARTSYS;
2840 goto cifs_setattr_exit;
2841 }
2842 mapping_set_error(inode->i_mapping, rc);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002843 }
2844
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002845 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002846
Steve Frenchcf5371a2020-02-24 17:37:39 -06002847 if ((attrs->ia_valid & ATTR_MTIME) &&
2848 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002849 rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002850 if (!rc) {
2851 tcon = tlink_tcon(wfile->tlink);
2852 rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
2853 cifsFileInfo_put(wfile);
2854 if (rc)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002855 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002856 } else if (rc != -EBADF)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002857 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002858 else
2859 rc = 0;
2860 }
2861
Steve French50531442008-03-14 19:21:31 +00002862 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002863 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2864 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002865 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002867
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002868 if (attrs->ia_valid & ATTR_UID)
2869 uid = attrs->ia_uid;
2870
2871 if (attrs->ia_valid & ATTR_GID)
2872 gid = attrs->ia_gid;
2873
Steve French22442172019-07-19 08:15:55 +00002874 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2875 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002876 if (uid_valid(uid) || gid_valid(gid)) {
Shyam Prasad N0f220532020-08-17 03:23:12 -07002877 mode = NO_CHANGE_64;
2878 rc = id_mode_to_cifs_acl(inode, full_path, &mode,
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002879 uid, gid);
2880 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002881 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2882 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002883 goto cifs_setattr_exit;
2884 }
2885 }
2886 } else
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002887 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002888 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889
Jeff Laytond32c4f22007-10-18 03:05:22 -07002890 /* skip mode change if it's just for clearing setuid/setgid */
2891 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2892 attrs->ia_valid &= ~ATTR_MODE;
2893
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895 mode = attrs->ia_mode;
Steve Frenchcdbce9c82005-11-19 21:04:52 -08002896 rc = 0;
Steve French22442172019-07-19 08:15:55 +00002897 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2898 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Shyam Prasad N0f220532020-08-17 03:23:12 -07002899 rc = id_mode_to_cifs_acl(inode, full_path, &mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002900 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002901 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002902 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2903 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002904 goto cifs_setattr_exit;
2905 }
Shyam Prasad N0f220532020-08-17 03:23:12 -07002906
2907 /*
2908 * In case of CIFS_MOUNT_CIFS_ACL, we cannot support all modes.
2909 * Pick up the actual mode bits that were set.
2910 */
2911 if (mode != attrs->ia_mode)
2912 attrs->ia_mode = mode;
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002913 } else
Jeff Layton51328612008-05-22 09:33:34 -04002914 if (((mode & S_IWUGO) == 0) &&
2915 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002916
2917 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2918
Jeff Layton51328612008-05-22 09:33:34 -04002919 /* fix up mode if we're not using dynperm */
2920 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2921 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2922 } else if ((mode & S_IWUGO) &&
2923 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002924
2925 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2926 /* Attributes of 0 are ignored */
2927 if (dosattr == 0)
2928 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002929
2930 /* reset local inode permissions to normal */
2931 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2932 attrs->ia_mode &= ~(S_IALLUGO);
2933 if (S_ISDIR(inode->i_mode))
2934 attrs->ia_mode |=
Ronnie Sahlberg8401e932020-12-12 13:40:50 -06002935 cifs_sb->ctx->dir_mode;
Jeff Layton51328612008-05-22 09:33:34 -04002936 else
2937 attrs->ia_mode |=
Ronnie Sahlberg8401e932020-12-12 13:40:50 -06002938 cifs_sb->ctx->file_mode;
Jeff Layton51328612008-05-22 09:33:34 -04002939 }
2940 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2941 /* ignore mode change - ATTR_READONLY hasn't changed */
2942 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 }
2945
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002946 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2947 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2948 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2949 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950
Steve Frenche30dcf32005-09-20 20:49:16 -07002951 /* Even if error on time set, no sense failing the call if
2952 the server would set the time to a reasonable value anyway,
2953 and this check ensures that we are not being called from
2954 sys_utimes in which case we ought to fail the call back to
2955 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002956 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002957 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002958 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 }
2960
2961 /* do not need local check to inode_check_ok since the server does
2962 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002963 if (rc)
2964 goto cifs_setattr_exit;
2965
2966 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002967 attrs->ia_size != i_size_read(inode))
2968 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002969
Christian Brauner2f221d62021-01-21 14:19:26 +01002970 setattr_copy(&init_user_ns, inode, attrs);
Christoph Hellwig10257742010-06-04 11:30:02 +02002971 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002972
Steve Frenche30dcf32005-09-20 20:49:16 -07002973cifs_setattr_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002974 free_xid(xid);
Al Virof6a9bc32021-03-05 17:36:04 -05002975 free_dentry_path(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 return rc;
2977}
2978
Jeff Layton0510eeb2008-08-02 07:26:12 -04002979int
Christian Brauner549c7292021-01-21 14:19:43 +01002980cifs_setattr(struct user_namespace *mnt_userns, struct dentry *direntry,
2981 struct iattr *attrs)
Jeff Layton0510eeb2008-08-02 07:26:12 -04002982{
Al Virofc640052016-04-10 01:33:30 -04002983 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002984 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Ronnie Sahlbergc6cc4c52020-10-09 09:32:56 +10002985 int rc, retries = 0;
Jeff Layton0510eeb2008-08-02 07:26:12 -04002986
Steve French087f7572021-04-29 00:18:43 -05002987 if (unlikely(cifs_forced_shutdown(cifs_sb)))
2988 return -EIO;
2989
Ronnie Sahlbergc6cc4c52020-10-09 09:32:56 +10002990 do {
2991 if (pTcon->unix_ext)
2992 rc = cifs_setattr_unix(direntry, attrs);
2993 else
2994 rc = cifs_setattr_nounix(direntry, attrs);
2995 retries++;
2996 } while (is_retryable_error(rc) && retries < 2);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002997
2998 /* BB: add cifs_setattr_legacy for really old servers */
Ronnie Sahlbergc6cc4c52020-10-09 09:32:56 +10002999 return rc;
Jeff Layton0510eeb2008-08-02 07:26:12 -04003000}