blob: 9ee5f304592f1316803bfb8436a5e134fb823d0e [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>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010029
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <asm/div64.h>
31#include "cifsfs.h"
32#include "cifspdu.h"
33#include "cifsglob.h"
34#include "cifsproto.h"
Steve French6a5f6592020-06-11 19:25:47 -050035#include "smb2proto.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include "cifs_debug.h"
37#include "cifs_fs_sb.h"
Steve French2baa2682014-09-27 02:19:01 -050038#include "cifs_unicode.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053039#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
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
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800297 fattr->cf_uid = cifs_sb->mnt_uid;
298 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
307 fattr->cf_gid = cifs_sb->mnt_gid;
308 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;
336 fattr->cf_uid = cifs_sb->mnt_uid;
337 fattr->cf_gid = cifs_sb->mnt_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
647 fattr->cf_uid = cifs_sb->mnt_uid; /* TODO: map uid and gid from SID */
648 fattr->cf_gid = cifs_sb->mnt_gid;
649
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) {
688 fattr->cf_mode |= S_IFLNK | cifs_sb->mnt_file_mode;
689 fattr->cf_dtype = DT_LNK;
690 } else if (reparse_tag == IO_REPARSE_TAG_LX_FIFO) {
691 fattr->cf_mode |= S_IFIFO | cifs_sb->mnt_file_mode;
692 fattr->cf_dtype = DT_FIFO;
693 } else if (reparse_tag == IO_REPARSE_TAG_AF_UNIX) {
694 fattr->cf_mode |= S_IFSOCK | cifs_sb->mnt_file_mode;
695 fattr->cf_dtype = DT_SOCK;
696 } else if (reparse_tag == IO_REPARSE_TAG_LX_CHR) {
697 fattr->cf_mode |= S_IFCHR | cifs_sb->mnt_file_mode;
698 fattr->cf_dtype = DT_CHR;
699 } else if (reparse_tag == IO_REPARSE_TAG_LX_BLK) {
700 fattr->cf_mode |= S_IFBLK | cifs_sb->mnt_file_mode;
701 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) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400706 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
707 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 {
715 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
716 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
734 fattr->cf_uid = cifs_sb->mnt_uid;
735 fattr->cf_gid = cifs_sb->mnt_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;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400774 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500775 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400776 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500777
778 /*
779 * don't bother with SFU junk here -- just mark inode as needing
780 * revalidation.
781 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500782 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
783 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
784 cifs_fattr_to_inode(inode, &fattr);
785cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400786 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500787 return rc;
788}
789
Steve French7ea884c2018-03-31 18:13:38 -0500790/* Simple function to return a 64 bit hash of string. Rarely called */
791static __u64 simple_hashstr(const char *str)
792{
Geert Uytterhoeven3995bbf2018-04-05 14:57:11 +0200793 const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
Steve French7ea884c2018-03-31 18:13:38 -0500794 __u64 hash = 0;
795
796 while (*str)
797 hash = (hash + (__u64) *str++) * hash_mult;
798
799 return hash;
800}
801
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100802/**
803 * cifs_backup_query_path_info - SMB1 fallback code to get ino
804 *
805 * Fallback code to get file metadata when we don't have access to
Geert Uytterhoeven3dc58df2020-05-05 15:43:35 +0200806 * @full_path (EACCES) and have backup creds.
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100807 *
808 * @data will be set to search info result buffer
809 * @resp_buf will be set to cifs resp buf and needs to be freed with
810 * cifs_buf_release() when done with @data.
811 */
812static int
813cifs_backup_query_path_info(int xid,
814 struct cifs_tcon *tcon,
815 struct super_block *sb,
816 const char *full_path,
817 void **resp_buf,
818 FILE_ALL_INFO **data)
819{
820 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
821 struct cifs_search_info info = {0};
822 u16 flags;
823 int rc;
824
825 *resp_buf = NULL;
826 info.endOfSearch = false;
827 if (tcon->unix_ext)
828 info.info_level = SMB_FIND_FILE_UNIX;
829 else if ((tcon->ses->capabilities &
830 tcon->ses->server->vals->cap_nt_find) == 0)
831 info.info_level = SMB_FIND_FILE_INFO_STANDARD;
832 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
833 info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
834 else /* no srvino useful for fallback to some netapp */
835 info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
836
837 flags = CIFS_SEARCH_CLOSE_ALWAYS |
838 CIFS_SEARCH_CLOSE_AT_END |
839 CIFS_SEARCH_BACKUP_SEARCH;
840
841 rc = CIFSFindFirst(xid, tcon, full_path,
842 cifs_sb, NULL, flags, &info, false);
843 if (rc)
844 return rc;
845
846 *resp_buf = (void *)info.ntwrk_buf_start;
847 *data = (FILE_ALL_INFO *)info.srch_entries_start;
848 return 0;
849}
850
851static void
852cifs_set_fattr_ino(int xid,
853 struct cifs_tcon *tcon,
854 struct super_block *sb,
855 struct inode **inode,
856 const char *full_path,
857 FILE_ALL_INFO *data,
858 struct cifs_fattr *fattr)
859{
860 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
861 struct TCP_Server_Info *server = tcon->ses->server;
862 int rc;
863
864 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
865 if (*inode)
866 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
867 else
868 fattr->cf_uniqueid = iunique(sb, ROOT_I);
869 return;
870 }
871
872 /*
873 * If we have an inode pass a NULL tcon to ensure we don't
874 * make a round trip to the server. This only works for SMB2+.
875 */
876 rc = server->ops->get_srv_inum(xid,
877 *inode ? NULL : tcon,
878 cifs_sb, full_path,
879 &fattr->cf_uniqueid,
880 data);
881 if (rc) {
882 /*
883 * If that fails reuse existing ino or generate one
884 * and disable server ones
885 */
886 if (*inode)
887 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
888 else {
889 fattr->cf_uniqueid = iunique(sb, ROOT_I);
890 cifs_autodisable_serverino(cifs_sb);
891 }
892 return;
893 }
894
895 /* If no errors, check for zero root inode (invalid) */
896 if (fattr->cf_uniqueid == 0 && strlen(full_path) == 0) {
897 cifs_dbg(FYI, "Invalid (0) inodenum\n");
898 if (*inode) {
899 /* reuse */
900 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
901 } else {
902 /* make an ino by hashing the UNC */
903 fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
904 fattr->cf_uniqueid = simple_hashstr(tcon->treeName);
905 }
906 }
907}
908
909static inline bool is_inode_cache_good(struct inode *ino)
910{
911 return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;
912}
913
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400914int
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100915cifs_get_inode_info(struct inode **inode,
916 const char *full_path,
917 FILE_ALL_INFO *in_data,
918 struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600919 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920{
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100921
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400922 struct cifs_tcon *tcon;
923 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400924 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400926 bool adjust_tz = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100927 struct cifs_fattr fattr = {0};
Steve French2e4564b2020-10-22 22:03:14 -0500928 bool is_reparse_point = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100929 FILE_ALL_INFO *data = in_data;
930 FILE_ALL_INFO *tmp_data = NULL;
931 void *smb1_backup_rsp_buf = NULL;
932 int rc = 0;
933 int tmprc = 0;
Steve French2e4564b2020-10-22 22:03:14 -0500934 __u32 reparse_tag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
Jeff Layton7ffec372010-09-29 19:51:11 -0400936 tlink = cifs_sb_tlink(cifs_sb);
937 if (IS_ERR(tlink))
938 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400939 tcon = tlink_tcon(tlink);
940 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400941
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100942 /*
943 * 1. Fetch file metadata if not provided (data)
944 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100946 if (!data) {
947 if (is_inode_cache_good(*inode)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500948 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100949 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100951 tmp_data = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
952 if (!tmp_data) {
Jeff Layton7ffec372010-09-29 19:51:11 -0400953 rc = -ENOMEM;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100954 goto out;
Jeff Layton7ffec372010-09-29 19:51:11 -0400955 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100956 rc = server->ops->query_path_info(xid, tcon, cifs_sb,
Steve French2e4564b2020-10-22 22:03:14 -0500957 full_path, tmp_data,
958 &adjust_tz, &is_reparse_point);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100959 data = tmp_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400961
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400962 /*
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100963 * 2. Convert it to internal cifs metadata (fattr)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400964 */
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100965
966 switch (rc) {
967 case 0:
Steve French2e4564b2020-10-22 22:03:14 -0500968 /*
969 * If the file is a reparse point, it is more complicated
970 * since we have to check if its reparse tag matches a known
971 * special file type e.g. symlink or fifo or char etc.
972 */
973 if ((le32_to_cpu(data->Attributes) & ATTR_REPARSE) &&
974 server->ops->query_reparse_tag) {
975 rc = server->ops->query_reparse_tag(xid, tcon, cifs_sb,
976 full_path, &reparse_tag);
977 cifs_dbg(FYI, "reparse tag 0x%x\n", reparse_tag);
978 }
979 cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz,
980 is_reparse_point, reparse_tag);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100981 break;
982 case -EREMOTE:
983 /* DFS link, no metadata available on this server */
984 cifs_create_dfs_fattr(&fattr, sb);
985 rc = 0;
986 break;
987 case -EACCES:
988 /*
989 * perm errors, try again with backup flags if possible
990 *
991 * For SMB2 and later the backup intent flag
992 * is already sent if needed on open and there
993 * is no path based FindFirst operation to use
994 * to retry with
995 */
996 if (backup_cred(cifs_sb) && is_smb1_server(server)) {
997 /* for easier reading */
998 FILE_DIRECTORY_INFO *fdi;
999 SEARCH_ID_FULL_DIR_INFO *si;
1000
1001 rc = cifs_backup_query_path_info(xid, tcon, sb,
1002 full_path,
1003 &smb1_backup_rsp_buf,
1004 &data);
1005 if (rc)
1006 goto out;
1007
1008 fdi = (FILE_DIRECTORY_INFO *)data;
1009 si = (SEARCH_ID_FULL_DIR_INFO *)data;
1010
1011 cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb);
1012 fattr.cf_uniqueid = le64_to_cpu(si->UniqueId);
1013 /* uniqueid set, skip get inum step */
1014 goto handle_mnt_opt;
1015 } else {
1016 /* nothing we can do, bail out */
1017 goto out;
1018 }
1019 break;
1020 default:
1021 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
1022 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001023 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001024
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001025 /*
1026 * 3. Get or update inode number (fattr.cf_uniqueid)
1027 */
1028
1029 cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);
1030
1031 /*
1032 * 4. Tweak fattr based on mount options
1033 */
1034
1035handle_mnt_opt:
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001036 /* query for SFU type info if supported and needed */
1037 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
1038 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
1039 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
1040 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001041 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001042 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001043
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001044 /* fill in 0777 bits from ACL */
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001045 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
1046 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
1047 full_path, fid);
Ronnie Sahlberg01ec3722020-09-03 10:02:39 +10001048 if (rc == -EREMOTE)
1049 rc = 0;
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001050 if (rc) {
1051 cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001052 __func__, rc);
1053 goto out;
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001054 }
1055 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
1056 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
Dan Carpenter via samba-technical68464b82019-11-26 15:11:15 +03001057 full_path, fid);
Ronnie Sahlberg01ec3722020-09-03 10:02:39 +10001058 if (rc == -EREMOTE)
1059 rc = 0;
Dan Carpenter via samba-technical68464b82019-11-26 15:11:15 +03001060 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001061 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
1062 __func__, rc);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001063 goto out;
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06001064 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001065 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001066
1067 /* fill in remaining high mode bits e.g. SUID, VTX */
1068 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
1069 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
1070
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001071 /* check for Minshall+French symlinks */
1072 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +00001073 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
1074 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001075 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +00001076 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001077 }
1078
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001079 /*
1080 * 5. Update inode with final fattr data
1081 */
1082
Pavel Shilovsky1208ef12012-05-27 17:34:43 +04001083 if (!*inode) {
1084 *inode = cifs_iget(sb, &fattr);
1085 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001086 rc = -ENOMEM;
1087 } else {
Nakajima Akira7196ac12015-04-22 15:24:44 +09001088 /* we already have inode, update it */
1089
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001090 /* if uniqueid is different, return error */
1091 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1092 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001093 CIFS_I(*inode)->time = 0; /* force reval */
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001094 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001095 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001096 }
1097
Nakajima Akira7196ac12015-04-22 15:24:44 +09001098 /* if filetype is different, return error */
1099 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1100 (fattr.cf_mode & S_IFMT))) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001101 CIFS_I(*inode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +09001102 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001103 goto out;
Nakajima Akira7196ac12015-04-22 15:24:44 +09001104 }
1105
Pavel Shilovsky1208ef12012-05-27 17:34:43 +04001106 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001107 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001108out:
1109 cifs_buf_release(smb1_backup_rsp_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001110 cifs_put_tlink(tlink);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001111 kfree(tmp_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 return rc;
1113}
1114
Steve French6a5f6592020-06-11 19:25:47 -05001115int
1116smb311_posix_get_inode_info(struct inode **inode,
1117 const char *full_path,
1118 struct super_block *sb, unsigned int xid)
1119{
1120 struct cifs_tcon *tcon;
Steve French6a5f6592020-06-11 19:25:47 -05001121 struct tcon_link *tlink;
1122 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1123 bool adjust_tz = false;
1124 struct cifs_fattr fattr = {0};
1125 bool symlink = false;
1126 struct smb311_posix_qinfo *data = NULL;
1127 int rc = 0;
1128 int tmprc = 0;
1129
1130 tlink = cifs_sb_tlink(cifs_sb);
1131 if (IS_ERR(tlink))
1132 return PTR_ERR(tlink);
1133 tcon = tlink_tcon(tlink);
Steve French6a5f6592020-06-11 19:25:47 -05001134
1135 /*
1136 * 1. Fetch file metadata
1137 */
1138
1139 if (is_inode_cache_good(*inode)) {
1140 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
1141 goto out;
1142 }
1143 data = kmalloc(sizeof(struct smb311_posix_qinfo), GFP_KERNEL);
1144 if (!data) {
1145 rc = -ENOMEM;
1146 goto out;
1147 }
1148
1149 rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
1150 full_path, data,
1151 &adjust_tz, &symlink);
1152
1153 /*
1154 * 2. Convert it to internal cifs metadata (fattr)
1155 */
1156
1157 switch (rc) {
1158 case 0:
1159 smb311_posix_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
1160 break;
1161 case -EREMOTE:
1162 /* DFS link, no metadata available on this server */
1163 cifs_create_dfs_fattr(&fattr, sb);
1164 rc = 0;
1165 break;
1166 case -EACCES:
1167 /*
1168 * For SMB2 and later the backup intent flag
1169 * is already sent if needed on open and there
1170 * is no path based FindFirst operation to use
1171 * to retry with so nothing we can do, bail out
1172 */
1173 goto out;
1174 default:
1175 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
1176 goto out;
1177 }
1178
1179
1180 /*
Steve Frencha7a519a2020-06-12 14:49:47 -05001181 * 3. Tweak fattr based on mount options
Steve French6a5f6592020-06-11 19:25:47 -05001182 */
1183
1184 /* check for Minshall+French symlinks */
1185 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
1186 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
1187 full_path);
1188 if (tmprc)
1189 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1190 }
1191
1192 /*
Steve Frencha7a519a2020-06-12 14:49:47 -05001193 * 4. Update inode with final fattr data
Steve French6a5f6592020-06-11 19:25:47 -05001194 */
1195
1196 if (!*inode) {
1197 *inode = cifs_iget(sb, &fattr);
1198 if (!*inode)
1199 rc = -ENOMEM;
1200 } else {
1201 /* we already have inode, update it */
1202
1203 /* if uniqueid is different, return error */
1204 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1205 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
1206 CIFS_I(*inode)->time = 0; /* force reval */
1207 rc = -ESTALE;
1208 goto out;
1209 }
1210
1211 /* if filetype is different, return error */
1212 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1213 (fattr.cf_mode & S_IFMT))) {
1214 CIFS_I(*inode)->time = 0; /* force reval */
1215 rc = -ESTALE;
1216 goto out;
1217 }
1218
1219 cifs_fattr_to_inode(*inode, &fattr);
1220 }
1221out:
1222 cifs_put_tlink(tlink);
1223 kfree(data);
1224 return rc;
1225}
1226
1227
Steve French7f8ed422007-09-28 22:28:55 +00001228static const struct inode_operations cifs_ipc_inode_ops = {
1229 .lookup = cifs_lookup,
1230};
1231
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001232static int
1233cifs_find_inode(struct inode *inode, void *opaque)
1234{
1235 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1236
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001237 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001238 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
1239 return 0;
1240
Jeff Layton20054bd2011-01-07 11:30:27 -05001241 /* use createtime like an i_generation field */
1242 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
1243 return 0;
1244
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001245 /* don't match inode of different type */
1246 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
1247 return 0;
1248
Jeff Layton5acfec22010-08-02 17:43:54 -04001249 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -04001250 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -04001251 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -04001252
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001253 return 1;
1254}
1255
1256static int
1257cifs_init_inode(struct inode *inode, void *opaque)
1258{
1259 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1260
1261 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -05001262 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001263 return 0;
1264}
1265
Jeff Layton5acfec22010-08-02 17:43:54 -04001266/*
1267 * walk dentry list for an inode and report whether it has aliases that
1268 * are hashed. We use this to determine if a directory inode can actually
1269 * be used.
1270 */
1271static bool
1272inode_has_hashed_dentries(struct inode *inode)
1273{
1274 struct dentry *dentry;
1275
Nick Piggin873feea2011-01-07 17:50:06 +11001276 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -04001277 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001278 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +11001279 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001280 return true;
1281 }
1282 }
Nick Piggin873feea2011-01-07 17:50:06 +11001283 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001284 return false;
1285}
1286
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001287/* Given fattrs, get a corresponding inode */
1288struct inode *
1289cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
1290{
1291 unsigned long hash;
1292 struct inode *inode;
1293
Jeff Layton3d694382010-05-11 14:59:55 -04001294retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -05001295 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001296
1297 /* hash down to 32-bits on 32-bit arch */
1298 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
1299
1300 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001301 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001302 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -04001303 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -04001304 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -04001305
1306 if (inode_has_hashed_dentries(inode)) {
1307 cifs_autodisable_serverino(CIFS_SB(sb));
1308 iput(inode);
1309 fattr->cf_uniqueid = iunique(sb, ROOT_I);
1310 goto retry_iget5_locked;
1311 }
Jeff Layton3d694382010-05-11 14:59:55 -04001312 }
1313
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001314 cifs_fattr_to_inode(inode, fattr);
Linus Torvalds1751e8a2017-11-27 13:05:09 -08001315 if (sb->s_flags & SB_NOATIME)
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001316 inode->i_flags |= S_NOATIME | S_NOCMTIME;
1317 if (inode->i_state & I_NEW) {
1318 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +00001319#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301320 /* initialize per-inode cache cookie pointer */
1321 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +00001322#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001323 unlock_new_inode(inode);
1324 }
1325 }
1326
1327 return inode;
1328}
1329
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001331struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001333 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001334 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001335 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001336 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001337 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001338 char *path = NULL;
1339 int len;
1340
1341 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1342 && cifs_sb->prepath) {
1343 len = strlen(cifs_sb->prepath);
1344 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1345 if (path == NULL)
1346 return ERR_PTR(-ENOMEM);
1347 path[0] = '/';
1348 memcpy(path+1, cifs_sb->prepath, len);
1349 } else {
1350 path = kstrdup("", GFP_KERNEL);
1351 if (path == NULL)
1352 return ERR_PTR(-ENOMEM);
1353 }
David Howellsce634ab2008-02-07 00:15:33 -08001354
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001355 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001356 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001357 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001358 /* some servers mistakenly claim POSIX support */
1359 if (rc != -EOPNOTSUPP)
1360 goto iget_no_retry;
Joe Perchesa0a30362020-04-14 22:42:53 -07001361 cifs_dbg(VFS, "server does not support POSIX extensions\n");
Steve Frenchb5b374e2014-10-06 01:01:03 -05001362 tcon->unix_ext = false;
1363 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001364
Aurelien Aptela6b50582016-05-25 19:59:09 +02001365 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
Steve Frenchd3138522020-06-11 22:43:01 -05001366 if (tcon->posix_extensions)
1367 rc = smb311_posix_get_inode_info(&inode, path, sb, xid);
1368 else
1369 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001370
1371iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001372 if (!inode) {
1373 inode = ERR_PTR(rc);
1374 goto out;
1375 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001376
Steve French0ccd4802010-07-16 04:31:02 +00001377#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301378 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001379 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001380#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301381
Aurelien Aptelb327a712018-01-24 13:46:10 +01001382 if (rc && tcon->pipe) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001383 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001384 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001385 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001386 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001387 inode->i_op = &cifs_ipc_inode_ops;
1388 inode->i_fop = &simple_dir_operations;
1389 inode->i_uid = cifs_sb->mnt_uid;
1390 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001391 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001392 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001393 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001394 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001395 }
1396
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001397out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001398 kfree(path);
Phillip Potter31cd1062018-03-17 21:06:56 +00001399 free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001400 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401}
1402
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001403int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001404cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001405 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001406{
Steve French388e57b2008-09-16 23:50:58 +00001407 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001408 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001409 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001410 FILE_BASIC_INFO info_buf;
1411
Steve French1adcb712009-02-25 14:19:56 +00001412 if (attrs == NULL)
1413 return -EINVAL;
1414
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001415 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1416 if (!server->ops->set_file_info)
1417 return -ENOSYS;
1418
Steve Frenchfd09b7d2018-08-02 20:28:18 -05001419 info_buf.Pad = 0;
1420
Steve French388e57b2008-09-16 23:50:58 +00001421 if (attrs->ia_valid & ATTR_ATIME) {
1422 set_time = true;
1423 info_buf.LastAccessTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001424 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
Steve French388e57b2008-09-16 23:50:58 +00001425 } else
1426 info_buf.LastAccessTime = 0;
1427
1428 if (attrs->ia_valid & ATTR_MTIME) {
1429 set_time = true;
1430 info_buf.LastWriteTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001431 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
Steve French388e57b2008-09-16 23:50:58 +00001432 } else
1433 info_buf.LastWriteTime = 0;
1434
1435 /*
1436 * Samba throws this field away, but windows may actually use it.
1437 * Do not set ctime unless other time stamps are changed explicitly
1438 * (i.e. by utimes()) since we would then have a mix of client and
1439 * server times.
1440 */
1441 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001442 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001443 info_buf.ChangeTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001444 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
Steve French388e57b2008-09-16 23:50:58 +00001445 } else
1446 info_buf.ChangeTime = 0;
1447
1448 info_buf.CreationTime = 0; /* don't change */
1449 info_buf.Attributes = cpu_to_le32(dosattr);
1450
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001451 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001452}
1453
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001454/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001455 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001456 * and rename it to a random name that hopefully won't conflict with
1457 * anything else.
1458 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001459int
1460cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1461 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001462{
1463 int oplock = 0;
1464 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001465 struct cifs_fid fid;
1466 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001467 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001468 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1469 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001470 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001471 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001472 __u32 dosattr, origattr;
1473 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001474
Jeff Layton7ffec372010-09-29 19:51:11 -04001475 tlink = cifs_sb_tlink(cifs_sb);
1476 if (IS_ERR(tlink))
1477 return PTR_ERR(tlink);
1478 tcon = tlink_tcon(tlink);
1479
Sachin Prabhuc483a982013-03-05 19:25:56 +00001480 /*
1481 * We cannot rename the file if the server doesn't support
1482 * CAP_INFOLEVEL_PASSTHRU
1483 */
1484 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1485 rc = -EBUSY;
1486 goto out;
1487 }
1488
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001489 oparms.tcon = tcon;
1490 oparms.cifs_sb = cifs_sb;
1491 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
Amir Goldstein0f060932020-02-03 21:46:43 +02001492 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001493 oparms.disposition = FILE_OPEN;
1494 oparms.path = full_path;
1495 oparms.fid = &fid;
1496 oparms.reconnect = false;
1497
1498 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001499 if (rc != 0)
1500 goto out;
1501
Steve French32709582008-10-20 00:44:19 +00001502 origattr = cifsInode->cifsAttrs;
1503 if (origattr == 0)
1504 origattr |= ATTR_NORMAL;
1505
1506 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001507 if (dosattr == 0)
1508 dosattr |= ATTR_NORMAL;
1509 dosattr |= ATTR_HIDDEN;
1510
Steve French32709582008-10-20 00:44:19 +00001511 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1512 if (dosattr != origattr) {
1513 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1514 if (info_buf == NULL) {
1515 rc = -ENOMEM;
1516 goto out_close;
1517 }
1518 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001519 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001520 current->tgid);
1521 /* although we would like to mark the file hidden
1522 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001523 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001524 cifsInode->cifsAttrs = dosattr;
1525 else
1526 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001527 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001528
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001529 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001530 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1531 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001532 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001533 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001534 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001535 goto undo_setattr;
1536 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001537
Steve French32709582008-10-20 00:44:19 +00001538 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001539 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001540 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001541 current->tgid);
1542 /*
1543 * some samba versions return -ENOENT when we try to set the
1544 * file disposition here. Likely a samba bug, but work around
1545 * it for now. This means that some cifsXXX files may hang
1546 * around after they shouldn't.
1547 *
1548 * BB: remove this hack after more servers have the fix
1549 */
1550 if (rc == -ENOENT)
1551 rc = 0;
1552 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001553 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001554 goto undo_rename;
1555 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001556 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001557 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001558
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001559out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001560 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001561out:
Steve French32709582008-10-20 00:44:19 +00001562 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001563 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001564 return rc;
Steve French32709582008-10-20 00:44:19 +00001565
1566 /*
1567 * reset everything back to the original state. Don't bother
1568 * dealing with errors here since we can't do anything about
1569 * them anyway.
1570 */
1571undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001572 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001573 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001574undo_setattr:
1575 if (dosattr != origattr) {
1576 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001577 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001578 current->tgid))
1579 cifsInode->cifsAttrs = origattr;
1580 }
1581
1582 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001583}
1584
Steve Frenchb7ca6922012-08-03 08:43:01 -05001585/* copied from fs/nfs/dir.c with small changes */
1586static void
1587cifs_drop_nlink(struct inode *inode)
1588{
1589 spin_lock(&inode->i_lock);
1590 if (inode->i_nlink > 0)
1591 drop_nlink(inode);
1592 spin_unlock(&inode->i_lock);
1593}
Steve Frenchff694522009-04-20 19:45:13 +00001594
1595/*
David Howells2b0143b2015-03-17 22:25:59 +00001596 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001597 * is a negative dentry) then we would attempt a standard SMB delete, but
Colin Ian King413d6102018-10-26 19:07:21 +01001598 * if that fails we can not attempt the fall back mechanisms on EACCES
1599 * but will return the EACCES to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001600 * unlink on negative dentries currently.
1601 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001602int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603{
1604 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001605 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001607 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001608 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001609 struct super_block *sb = dir->i_sb;
1610 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001611 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001612 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001613 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001614 struct iattr *attrs = NULL;
1615 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
Joe Perchesf96637b2013-05-04 22:12:25 -05001617 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
Jeff Layton7ffec372010-09-29 19:51:11 -04001619 tlink = cifs_sb_tlink(cifs_sb);
1620 if (IS_ERR(tlink))
1621 return PTR_ERR(tlink);
1622 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001623 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001624
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001625 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626
Steve French82e93672020-05-19 03:06:57 -05001627 if (tcon->nodelete) {
1628 rc = -EACCES;
1629 goto unlink_out;
1630 }
1631
Jeff Layton5f0319a2008-09-16 14:05:16 -04001632 /* Unlink can be called from rename so we can not take the
1633 * sb->s_vfs_rename_mutex here */
1634 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301636 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001637 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 }
Steve French2d785a52007-07-15 01:48:57 +00001639
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001640 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1641 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001642 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001643 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001644 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001645 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001646 if ((rc == 0) || (rc == -ENOENT))
1647 goto psx_del_no_retry;
1648 }
1649
Steve French60502472008-10-07 18:42:52 +00001650retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001651 if (!server->ops->unlink) {
1652 rc = -ENOSYS;
1653 goto psx_del_no_retry;
1654 }
1655
1656 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001657
Steve French2d785a52007-07-15 01:48:57 +00001658psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001660 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001661 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001663 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001664 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001665 if (server->ops->rename_pending_delete) {
1666 rc = server->ops->rename_pending_delete(full_path,
1667 dentry, xid);
1668 if (rc == 0)
1669 cifs_drop_nlink(inode);
1670 }
Steve Frenchff694522009-04-20 19:45:13 +00001671 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001672 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1673 if (attrs == NULL) {
1674 rc = -ENOMEM;
1675 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 }
Steve French388e57b2008-09-16 23:50:58 +00001677
1678 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001679 cifs_inode = CIFS_I(inode);
1680 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001681 if (origattr == 0)
1682 origattr |= ATTR_NORMAL;
1683 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001684 if (dosattr == 0)
1685 dosattr |= ATTR_NORMAL;
1686 dosattr |= ATTR_HIDDEN;
1687
1688 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001689 if (rc != 0)
1690 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001691
1692 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 }
Steve French60502472008-10-07 18:42:52 +00001694
1695 /* undo the setattr if we errored out and it's needed */
1696 if (rc != 0 && dosattr != 0)
1697 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1698
Steve French388e57b2008-09-16 23:50:58 +00001699out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001700 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001701 cifs_inode = CIFS_I(inode);
1702 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001703 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001704 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001705 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001706 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001707 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001708 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001709unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001711 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001712 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001713 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 return rc;
1715}
1716
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001717static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001718cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001719 const char *full_path, struct cifs_sb_info *cifs_sb,
1720 struct cifs_tcon *tcon, const unsigned int xid)
1721{
1722 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001723 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001724
Steve Frenchd3138522020-06-11 22:43:01 -05001725 if (tcon->posix_extensions)
1726 rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
1727 else if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001728 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001729 xid);
1730 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001731 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1732 xid, NULL);
1733
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001734 if (rc)
1735 return rc;
1736
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001737 /*
1738 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001739 * from the server or was set bogus. Also, since this is a brand new
1740 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001741 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001742 if (inode->i_nlink < 2)
1743 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001744 mode &= ~current_umask();
1745 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001746 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001747 mode |= S_ISGID;
1748
1749 if (tcon->unix_ext) {
1750 struct cifs_unix_set_info_args args = {
1751 .mode = mode,
1752 .ctime = NO_CHANGE_64,
1753 .atime = NO_CHANGE_64,
1754 .mtime = NO_CHANGE_64,
1755 .device = 0,
1756 };
1757 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001758 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001759 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001760 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001761 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001762 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001763 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001764 args.uid = INVALID_UID; /* no change */
1765 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001766 }
1767 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1768 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001769 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001770 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001771 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001772 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001773 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001774 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001775 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001776 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1777 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001778
Jeff Layton101b92d2012-09-19 06:22:45 -07001779 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1780 inode->i_uid = current_fsuid();
1781 if (inode->i_mode & S_ISGID)
1782 inode->i_gid = parent->i_gid;
1783 else
1784 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001785 }
1786 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001787 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001788 return rc;
1789}
1790
1791static int
1792cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1793 const char *full_path, struct cifs_sb_info *cifs_sb,
1794 struct cifs_tcon *tcon, const unsigned int xid)
1795{
1796 int rc = 0;
1797 u32 oplock = 0;
1798 FILE_UNIX_BASIC_INFO *info = NULL;
1799 struct inode *newinode = NULL;
1800 struct cifs_fattr fattr;
1801
1802 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1803 if (info == NULL) {
1804 rc = -ENOMEM;
1805 goto posix_mkdir_out;
1806 }
1807
1808 mode &= ~current_umask();
1809 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1810 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001811 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001812 if (rc == -EOPNOTSUPP)
1813 goto posix_mkdir_out;
1814 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001815 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001816 d_drop(dentry);
1817 goto posix_mkdir_out;
1818 }
1819
1820 if (info->Type == cpu_to_le32(-1))
1821 /* no return info, go query for it */
1822 goto posix_mkdir_get_info;
1823 /*
1824 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1825 * need to set uid/gid.
1826 */
1827
1828 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1829 cifs_fill_uniqueid(inode->i_sb, &fattr);
1830 newinode = cifs_iget(inode->i_sb, &fattr);
1831 if (!newinode)
1832 goto posix_mkdir_get_info;
1833
1834 d_instantiate(dentry, newinode);
1835
1836#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001837 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1838 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001839
1840 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001841 cifs_dbg(FYI, "unexpected number of links %d\n",
1842 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001843#endif
1844
1845posix_mkdir_out:
1846 kfree(info);
1847 return rc;
1848posix_mkdir_get_info:
1849 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1850 xid);
1851 goto posix_mkdir_out;
1852}
1853
Al Viro18bb1db2011-07-26 01:41:39 -04001854int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001856 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001857 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001859 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001860 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001861 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001862 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
Frank Sorensonf52aa792020-02-12 15:31:48 -06001864 cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05001865 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001868 tlink = cifs_sb_tlink(cifs_sb);
1869 if (IS_ERR(tlink))
1870 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001871 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001872
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001873 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874
Steve French7f573562005-08-30 11:32:14 -07001875 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301877 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001878 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 }
Steve French50c2f752007-07-13 00:33:32 +00001880
Steve Frenchbea851b2018-06-14 21:56:32 -05001881 server = tcon->ses->server;
1882
Steve Frenchbea851b2018-06-14 21:56:32 -05001883 if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
1884 rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
1885 cifs_sb);
1886 d_drop(direntry); /* for time being always refresh inode info */
1887 goto mkdir_out;
1888 }
Steve Frenchbea851b2018-06-14 21:56:32 -05001889
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001890 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1891 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001892 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1893 tcon, xid);
1894 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001895 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001896 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001897
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001898 if (!server->ops->mkdir) {
1899 rc = -ENOSYS;
1900 goto mkdir_out;
1901 }
1902
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001904 rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001906 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001908 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001910
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001911 /* TODO: skip this for smb2/smb3 */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001912 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1913 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001914mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001915 /*
1916 * Force revalidate to get parent dir info when needed since cached
1917 * attributes are invalid now.
1918 */
1919 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001921 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001922 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 return rc;
1924}
1925
1926int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1927{
1928 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001929 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001931 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001932 struct cifs_tcon *tcon;
1933 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 char *full_path = NULL;
1935 struct cifsInodeInfo *cifsInode;
1936
Joe Perchesf96637b2013-05-04 22:12:25 -05001937 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001939 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
Steve French7f573562005-08-30 11:32:14 -07001941 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301943 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001944 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 }
1946
Jeff Layton7ffec372010-09-29 19:51:11 -04001947 cifs_sb = CIFS_SB(inode->i_sb);
1948 tlink = cifs_sb_tlink(cifs_sb);
1949 if (IS_ERR(tlink)) {
1950 rc = PTR_ERR(tlink);
1951 goto rmdir_exit;
1952 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001953 tcon = tlink_tcon(tlink);
1954 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001955
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001956 if (!server->ops->rmdir) {
1957 rc = -ENOSYS;
1958 cifs_put_tlink(tlink);
1959 goto rmdir_exit;
1960 }
1961
Steve French82e93672020-05-19 03:06:57 -05001962 if (tcon->nodelete) {
1963 rc = -EACCES;
1964 cifs_put_tlink(tlink);
1965 goto rmdir_exit;
1966 }
1967
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001968 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001969 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970
1971 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001972 spin_lock(&d_inode(direntry)->i_lock);
1973 i_size_write(d_inode(direntry), 0);
1974 clear_nlink(d_inode(direntry));
1975 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 }
1977
David Howells2b0143b2015-03-17 22:25:59 +00001978 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001979 /* force revalidate to go get info when needed */
1980 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001981
1982 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001983 /*
1984 * Force revalidate to get parent dir info when needed since cached
1985 * attributes are invalid now.
1986 */
1987 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001988
David Howells2b0143b2015-03-17 22:25:59 +00001989 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001990 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991
Jeff Layton7ffec372010-09-29 19:51:11 -04001992rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001994 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 return rc;
1996}
1997
Steve Frenchee2fd962008-09-23 18:23:33 +00001998static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001999cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
2000 const char *from_path, struct dentry *to_dentry,
2001 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00002002{
2003 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002004 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002005 struct cifs_tcon *tcon;
2006 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002007 struct cifs_fid fid;
2008 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00002009 int oplock, rc;
2010
Jeff Layton7ffec372010-09-29 19:51:11 -04002011 tlink = cifs_sb_tlink(cifs_sb);
2012 if (IS_ERR(tlink))
2013 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002014 tcon = tlink_tcon(tlink);
2015 server = tcon->ses->server;
2016
2017 if (!server->ops->rename)
2018 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04002019
Steve Frenchee2fd962008-09-23 18:23:33 +00002020 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002021 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00002022
2023 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002024 * Don't bother with rename by filehandle unless file is busy and
2025 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00002026 * rename by filehandle to various Windows servers.
2027 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00002028 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04002029 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00002030
Frank Sorenson652727b2019-04-16 08:37:27 -05002031 /* Don't fall back to using SMB on SMB 2+ mount */
2032 if (server->vals->protocol_id != 0)
2033 goto do_rename_exit;
2034
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04002035 /* open-file renames don't work across directories */
2036 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04002037 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04002038
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002039 oparms.tcon = tcon;
2040 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00002041 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002042 oparms.desired_access = DELETE;
Amir Goldstein0f060932020-02-03 21:46:43 +02002043 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002044 oparms.disposition = FILE_OPEN;
2045 oparms.path = from_path;
2046 oparms.fid = &fid;
2047 oparms.reconnect = false;
2048
2049 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00002050 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002051 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00002052 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05002053 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002054 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00002055 }
Jeff Layton7ffec372010-09-29 19:51:11 -04002056do_rename_exit:
Steve Frenchc7e9f782020-02-25 18:08:54 -06002057 if (rc == 0)
2058 d_move(from_dentry, to_dentry);
Jeff Layton7ffec372010-09-29 19:51:11 -04002059 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00002060 return rc;
2061}
2062
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002063int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002064cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
2065 struct inode *target_dir, struct dentry *target_dentry,
2066 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002068 char *from_name = NULL;
2069 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04002070 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04002071 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002072 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00002073 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
2074 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002075 unsigned int xid;
2076 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002078 if (flags & ~RENAME_NOREPLACE)
2079 return -EINVAL;
2080
Jeff Layton639e7a92010-09-03 11:50:09 -04002081 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002082 tlink = cifs_sb_tlink(cifs_sb);
2083 if (IS_ERR(tlink))
2084 return PTR_ERR(tlink);
2085 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002087 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00002088
2089 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00002090 * we already have the rename sem so we do not need to
2091 * grab it again here to protect the path integrity
2092 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002093 from_name = build_path_from_dentry(source_dentry);
2094 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 rc = -ENOMEM;
2096 goto cifs_rename_exit;
2097 }
2098
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002099 to_name = build_path_from_dentry(target_dentry);
2100 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00002101 rc = -ENOMEM;
2102 goto cifs_rename_exit;
2103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002105 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
2106 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00002107
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002108 /*
2109 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
2110 */
2111 if (flags & RENAME_NOREPLACE)
2112 goto cifs_rename_exit;
2113
Jeff Layton14121bd2008-10-20 14:45:22 -04002114 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00002115 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002116 * Are src and dst hardlinks of same inode? We can only tell
2117 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00002118 */
Jeff Layton14121bd2008-10-20 14:45:22 -04002119 info_buf_source =
Kees Cook6da2ec52018-06-12 13:55:00 -07002120 kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
Jeff Layton14121bd2008-10-20 14:45:22 -04002121 GFP_KERNEL);
2122 if (info_buf_source == NULL) {
2123 rc = -ENOMEM;
2124 goto cifs_rename_exit;
2125 }
2126
2127 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002128 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
2129 info_buf_source,
2130 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002131 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04002132 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04002133 goto unlink_target;
2134
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002135 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
2136 info_buf_target,
2137 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002138 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04002139
Jeff Layton8d281ef2008-10-22 13:57:01 -04002140 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05002141 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04002142 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05002143 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04002144 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05002145 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002146 }
2147 /*
2148 * else ... BB we could add the same check for Windows by
2149 * checking the UniqueId via FILE_INTERNAL_INFO
2150 */
Jeff Layton14121bd2008-10-20 14:45:22 -04002151
Jeff Layton14121bd2008-10-20 14:45:22 -04002152unlink_target:
Steve French0e670512020-07-23 14:41:29 -05002153 /* Try unlinking the target dentry if it's not negative */
2154 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04002155 if (d_is_dir(target_dentry))
2156 tmprc = cifs_rmdir(target_dir, target_dentry);
2157 else
2158 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04002159 if (tmprc)
2160 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002161 rc = cifs_do_rename(xid, source_dentry, from_name,
2162 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 }
2164
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04002165 /* force revalidate to go get info when needed */
2166 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
2167
2168 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07002169 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04002170
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00002172 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002173 kfree(from_name);
2174 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002175 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04002176 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 return rc;
2178}
2179
Jeff Laytondf2cf172010-02-12 07:44:16 -05002180static bool
2181cifs_inode_needs_reval(struct inode *inode)
2182{
2183 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302184 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002185
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002186 if (cifs_i->time == 0)
2187 return true;
2188
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002189 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05002190 return false;
2191
2192 if (!lookupCacheEnabled)
2193 return true;
2194
Jeff Laytona87c9ad2014-03-26 07:24:23 -07002195 if (!cifs_sb->actimeo)
2196 return true;
2197
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302198 if (!time_in_range(jiffies, cifs_i->time,
2199 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05002200 return true;
2201
Jeff Laytondb192722010-05-17 14:51:49 -04002202 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302203 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04002204 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
2205 return true;
2206
Jeff Laytondf2cf172010-02-12 07:44:16 -05002207 return false;
2208}
2209
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05302210/*
2211 * Zap the cache. Called when invalid_mapping flag is set.
2212 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002213int
Jeff Laytondf2cf172010-02-12 07:44:16 -05002214cifs_invalidate_mapping(struct inode *inode)
2215{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002216 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002217
Jeff Laytondf2cf172010-02-12 07:44:16 -05002218 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002219 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002220 if (rc)
Joe Perchesa0a30362020-04-14 22:42:53 -07002221 cifs_dbg(VFS, "%s: Could not invalidate inode %p\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05002222 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002223 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002224
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05302225 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002226 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002227}
2228
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002229/**
2230 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
2231 * @word: long word containing the bit lock
2232 */
2233static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002234cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002235{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002236 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002237 if (signal_pending_state(mode, current))
2238 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002239 return 0;
2240}
2241
Jeff Laytone284e532014-04-30 09:31:46 -04002242int
2243cifs_revalidate_mapping(struct inode *inode)
2244{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002245 int rc;
2246 unsigned long *flags = &CIFS_I(inode)->flags;
2247
Steve French4e8aea32020-04-09 21:42:18 -05002248 /* swapfiles are not supposed to be shared */
2249 if (IS_SWAPFILE(inode))
2250 return 0;
2251
NeilBrown74316202014-07-07 15:16:04 +10002252 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
2253 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002254 if (rc)
2255 return rc;
2256
2257 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
2258 rc = cifs_invalidate_mapping(inode);
2259 if (rc)
2260 set_bit(CIFS_INO_INVALID_MAPPING, flags);
2261 }
2262
2263 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07002264 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002265 wake_up_bit(flags, CIFS_INO_LOCK);
2266
2267 return rc;
2268}
2269
2270int
2271cifs_zap_mapping(struct inode *inode)
2272{
2273 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
2274 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04002275}
2276
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002277int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05002278{
2279 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05002280 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba642010-09-20 16:01:31 -07002281 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05002282
2283 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002284 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05002285
Jeff Layton13cfb732010-09-29 19:51:11 -04002286 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05002287 rc = cifs_get_file_info_unix(filp);
2288 else
2289 rc = cifs_get_file_info(filp);
2290
Jeff Laytonabab0952010-02-12 07:44:18 -05002291 return rc;
2292}
2293
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002294int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002296 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002297 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00002298 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002299 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002300 char *full_path = NULL;
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002301 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302
Jeff Laytondf2cf172010-02-12 07:44:16 -05002303 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 return -ENOENT;
2305
Jeff Laytondf2cf172010-02-12 07:44:16 -05002306 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002307 return rc;
2308
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002309 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
2311 /* can not safely grab the rename sem here if rename calls revalidate
2312 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05002313 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302315 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002316 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05002318
Joe Perchesf96637b2013-05-04 22:12:25 -05002319 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
2320 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02002321 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002323again:
Steve French6a5f6592020-06-11 19:25:47 -05002324 if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
2325 rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
2326 else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05002327 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
2328 else
2329 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
2330 xid, NULL);
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002331 if (rc == -EAGAIN && count++ < 10)
2332 goto again;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002333out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002335 free_xid(xid);
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 return rc;
2338}
2339
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002340int cifs_revalidate_file(struct file *filp)
2341{
2342 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002343 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002344
2345 rc = cifs_revalidate_file_attr(filp);
2346 if (rc)
2347 return rc;
2348
Jeff Laytone284e532014-04-30 09:31:46 -04002349 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002350}
2351
2352/* revalidate a dentry's inode attributes */
2353int cifs_revalidate_dentry(struct dentry *dentry)
2354{
2355 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002356 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002357
2358 rc = cifs_revalidate_dentry_attr(dentry);
2359 if (rc)
2360 return rc;
2361
Jeff Laytone284e532014-04-30 09:31:46 -04002362 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002363}
2364
David Howellsa528d352017-01-31 16:46:22 +00002365int cifs_getattr(const struct path *path, struct kstat *stat,
2366 u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367{
David Howellsa528d352017-01-31 16:46:22 +00002368 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002369 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002370 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002371 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002372 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002373
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002374 /*
2375 * We need to be sure that all dirty pages are written and the server
2376 * has actual ctime, mtime and file length.
2377 */
Steve Frenchffdec8d2020-02-18 18:07:57 -06002378 if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE)) &&
2379 !CIFS_CACHE_READ(CIFS_I(inode)) &&
2380 inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002381 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002382 if (rc) {
2383 mapping_set_error(inode->i_mapping, rc);
2384 return rc;
2385 }
Steve French5fe14c82006-11-07 19:26:33 +00002386 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002387
Steve Frenchffdec8d2020-02-18 18:07:57 -06002388 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC)
2389 CIFS_I(inode)->time = 0; /* force revalidate */
2390
2391 /*
2392 * If the caller doesn't require syncing, only sync if
2393 * necessary (e.g. due to earlier truncate or setattr
2394 * invalidating the cached metadata)
2395 */
2396 if (((flags & AT_STATX_SYNC_TYPE) != AT_STATX_DONT_SYNC) ||
2397 (CIFS_I(inode)->time == 0)) {
2398 rc = cifs_revalidate_dentry_attr(dentry);
2399 if (rc)
2400 return rc;
2401 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002402
2403 generic_fillattr(inode, stat);
Steve Frenche8506d22019-02-28 21:32:15 -06002404 stat->blksize = cifs_sb->bsize;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002405 stat->ino = CIFS_I(inode)->uniqueid;
2406
Steve French6e70e262017-09-21 21:32:29 -05002407 /* old CIFS Unix Extensions doesn't return create time */
2408 if (CIFS_I(inode)->createtime) {
2409 stat->result_mask |= STATX_BTIME;
Arnd Bergmann95390202018-06-19 17:27:58 +02002410 stat->btime =
2411 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
Steve French6e70e262017-09-21 21:32:29 -05002412 }
2413
2414 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2415 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2416 stat->attributes |= STATX_ATTR_COMPRESSED;
2417 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2418 stat->attributes |= STATX_ATTR_ENCRYPTED;
2419
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002420 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002421 * If on a multiuser mount without unix extensions or cifsacl being
2422 * enabled, and the admin hasn't overridden them, set the ownership
2423 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002424 */
2425 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002426 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002427 !tcon->unix_ext) {
2428 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2429 stat->uid = current_fsuid();
2430 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2431 stat->gid = current_fsgid();
2432 }
Dan Carpenter39946882020-02-28 12:22:59 +03002433 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434}
2435
Ronnie Sahlberg2f3ebab2019-04-25 16:45:29 +10002436int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
2437 u64 len)
2438{
2439 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2440 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->vfs_inode.i_sb);
2441 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2442 struct TCP_Server_Info *server = tcon->ses->server;
2443 struct cifsFileInfo *cfile;
2444 int rc;
2445
2446 /*
2447 * We need to be sure that all dirty pages are written as they
2448 * might fill holes on the server.
2449 */
2450 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
2451 inode->i_mapping->nrpages != 0) {
2452 rc = filemap_fdatawait(inode->i_mapping);
2453 if (rc) {
2454 mapping_set_error(inode->i_mapping, rc);
2455 return rc;
2456 }
2457 }
2458
2459 cfile = find_readable_file(cifs_i, false);
2460 if (cfile == NULL)
2461 return -EINVAL;
2462
2463 if (server->ops->fiemap) {
2464 rc = server->ops->fiemap(tcon, cfile, fei, start, len);
2465 cifsFileInfo_put(cfile);
2466 return rc;
2467 }
2468
2469 cifsFileInfo_put(cfile);
2470 return -ENOTSUPP;
2471}
2472
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002473int cifs_truncate_page(struct address_space *mapping, loff_t from)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002475 pgoff_t index = from >> PAGE_SHIFT;
2476 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 int rc = 0;
2479
2480 page = grab_cache_page(mapping, index);
2481 if (!page)
2482 return -ENOMEM;
2483
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002484 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002486 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 return rc;
2488}
2489
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002490void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002491{
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002492 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2493
Steve Frenchba6a46a2007-02-26 20:06:29 +00002494 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002495 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002496 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002497
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002498 /* Cached inode must be refreshed on truncate */
2499 cifs_i->time = 0;
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002500 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002501}
2502
Jeff Layton8efdbde2008-07-23 21:28:12 +00002503static int
2504cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002505 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002506{
2507 int rc;
2508 struct cifsFileInfo *open_file;
2509 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2510 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002511 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002512 struct cifs_tcon *tcon = NULL;
2513 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002514
2515 /*
2516 * To avoid spurious oplock breaks from server, in the case of
2517 * inodes that we already have open, avoid doing path based
2518 * setting of file size if we can do it by handle.
2519 * This keeps our caching token (oplock) and avoids timeouts
2520 * when the local oplock break takes longer to flush
2521 * writebehind data than the SMB timeout for the SetPathInfo
2522 * request would allow
2523 */
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002524 open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002525 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002526 tcon = tlink_tcon(open_file->tlink);
2527 server = tcon->ses->server;
2528 if (server->ops->set_file_size)
2529 rc = server->ops->set_file_size(xid, tcon, open_file,
2530 attrs->ia_size, false);
2531 else
2532 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002533 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002534 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002535 } else
2536 rc = -EINVAL;
2537
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002538 if (!rc)
2539 goto set_size_out;
Jeff Laytonba00ba642010-09-20 16:01:31 -07002540
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002541 if (tcon == NULL) {
2542 tlink = cifs_sb_tlink(cifs_sb);
2543 if (IS_ERR(tlink))
2544 return PTR_ERR(tlink);
2545 tcon = tlink_tcon(tlink);
2546 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002547 }
2548
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002549 /*
2550 * Set file size by pathname rather than by handle either because no
2551 * valid, writeable file handle for it was found or because there was
2552 * an error setting it by handle.
2553 */
2554 if (server->ops->set_path_size)
2555 rc = server->ops->set_path_size(xid, tcon, full_path,
2556 attrs->ia_size, cifs_sb, false);
2557 else
2558 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002559 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002560
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002561 if (tlink)
2562 cifs_put_tlink(tlink);
2563
2564set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002565 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002566 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002567 cifs_setsize(inode, attrs->ia_size);
Zhang Xiaoxu56183032020-06-19 22:51:29 -04002568
2569 /*
2570 * The man page of truncate says if the size changed,
2571 * then the st_ctime and st_mtime fields for the file
2572 * are updated.
2573 */
2574 attrs->ia_ctime = attrs->ia_mtime = current_time(inode);
2575 attrs->ia_valid |= ATTR_CTIME | ATTR_MTIME;
2576
Jeff Layton8efdbde2008-07-23 21:28:12 +00002577 cifs_truncate_page(inode->i_mapping, inode->i_size);
2578 }
2579
2580 return rc;
2581}
2582
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002583static int
2584cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2585{
2586 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002587 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002588 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002589 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002590 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2591 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002592 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002593 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002594 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002595 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002596
Al Viro35c265e2014-08-19 20:25:34 -04002597 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2598 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002599
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002600 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002601
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002602 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2603 attrs->ia_valid |= ATTR_FORCE;
2604
Jan Kara31051c82016-05-26 16:55:18 +02002605 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002606 if (rc < 0)
2607 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002608
2609 full_path = build_path_from_dentry(direntry);
2610 if (full_path == NULL) {
2611 rc = -ENOMEM;
2612 goto out;
2613 }
2614
Jeff Layton0f4d6342009-03-26 13:35:37 -04002615 /*
2616 * Attempt to flush data before changing attributes. We need to do
2617 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2618 * ownership or mode then we may also need to do this. Here, we take
2619 * the safe way out and just do the flush on all setattr requests. If
2620 * the flush returns error, store it to report later and continue.
2621 *
2622 * BB: This should be smarter. Why bother flushing pages that
2623 * will be truncated anyway? Also, should we error out here if
2624 * the flush returns error?
2625 */
2626 rc = filemap_write_and_wait(inode->i_mapping);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002627 if (is_interrupt_error(rc)) {
2628 rc = -ERESTARTSYS;
2629 goto out;
2630 }
2631
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002632 mapping_set_error(inode->i_mapping, rc);
2633 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002634
2635 if (attrs->ia_valid & ATTR_SIZE) {
2636 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2637 if (rc != 0)
2638 goto out;
2639 }
2640
2641 /* skip mode change if it's just for clearing setuid/setgid */
2642 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2643 attrs->ia_valid &= ~ATTR_MODE;
2644
2645 args = kmalloc(sizeof(*args), GFP_KERNEL);
2646 if (args == NULL) {
2647 rc = -ENOMEM;
2648 goto out;
2649 }
2650
2651 /* set up the struct */
2652 if (attrs->ia_valid & ATTR_MODE)
2653 args->mode = attrs->ia_mode;
2654 else
2655 args->mode = NO_CHANGE_64;
2656
2657 if (attrs->ia_valid & ATTR_UID)
2658 args->uid = attrs->ia_uid;
2659 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002660 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002661
2662 if (attrs->ia_valid & ATTR_GID)
2663 args->gid = attrs->ia_gid;
2664 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002665 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002666
2667 if (attrs->ia_valid & ATTR_ATIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002668 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002669 else
2670 args->atime = NO_CHANGE_64;
2671
2672 if (attrs->ia_valid & ATTR_MTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002673 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002674 else
2675 args->mtime = NO_CHANGE_64;
2676
2677 if (attrs->ia_valid & ATTR_CTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002678 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002679 else
2680 args->ctime = NO_CHANGE_64;
2681
2682 args->device = 0;
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002683 open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002684 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002685 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002686 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002687 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002688 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002689 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002690 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002691 tlink = cifs_sb_tlink(cifs_sb);
2692 if (IS_ERR(tlink)) {
2693 rc = PTR_ERR(tlink);
2694 goto out;
2695 }
2696 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002697 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002698 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002699 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002700 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002701 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002702
Christoph Hellwig10257742010-06-04 11:30:02 +02002703 if (rc)
2704 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002705
Christoph Hellwig10257742010-06-04 11:30:02 +02002706 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002707 attrs->ia_size != i_size_read(inode))
2708 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002709
2710 setattr_copy(inode, attrs);
2711 mark_inode_dirty(inode);
2712
2713 /* force revalidate when any of these times are set since some
2714 of the fs types (eg ext3, fat) do not have fine enough
2715 time granularity to match protocol, and we do not have a
2716 a way (yet) to query the server fs's time granularity (and
2717 whether it rounds times down).
2718 */
2719 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2720 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002721out:
2722 kfree(args);
2723 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002724 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002725 return rc;
2726}
2727
Jeff Layton0510eeb2008-08-02 07:26:12 -04002728static int
2729cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002731 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002732 kuid_t uid = INVALID_UID;
2733 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002734 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002735 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002736 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002737 struct cifsFileInfo *wfile;
2738 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 char *full_path = NULL;
2740 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002741 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002742 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002743
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002744 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745
Colin Ian King63d614a2019-06-24 17:39:43 +01002746 cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
Al Viro35c265e2014-08-19 20:25:34 -04002747 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002748
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002749 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2750 attrs->ia_valid |= ATTR_FORCE;
2751
Jan Kara31051c82016-05-26 16:55:18 +02002752 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002753 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002754 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002755 return rc;
Steve French6473a552005-11-29 20:20:10 -08002756 }
Steve French50c2f752007-07-13 00:33:32 +00002757
Steve French7f573562005-08-30 11:32:14 -07002758 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302760 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002761 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302762 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764
Jeff Layton0f4d6342009-03-26 13:35:37 -04002765 /*
2766 * Attempt to flush data before changing attributes. We need to do
Steve Frenchcf5371a2020-02-24 17:37:39 -06002767 * this for ATTR_SIZE and ATTR_MTIME. If the flush of the data
2768 * returns error, store it to report later and continue.
Jeff Layton0f4d6342009-03-26 13:35:37 -04002769 *
2770 * BB: This should be smarter. Why bother flushing pages that
2771 * will be truncated anyway? Also, should we error out here if
Steve Frenchcf5371a2020-02-24 17:37:39 -06002772 * the flush returns error? Do we need to check for ATTR_MTIME_SET flag?
Jeff Layton0f4d6342009-03-26 13:35:37 -04002773 */
Steve Frenchcf5371a2020-02-24 17:37:39 -06002774 if (attrs->ia_valid & (ATTR_MTIME | ATTR_SIZE | ATTR_CTIME)) {
2775 rc = filemap_write_and_wait(inode->i_mapping);
2776 if (is_interrupt_error(rc)) {
2777 rc = -ERESTARTSYS;
2778 goto cifs_setattr_exit;
2779 }
2780 mapping_set_error(inode->i_mapping, rc);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002781 }
2782
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002783 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002784
Steve Frenchcf5371a2020-02-24 17:37:39 -06002785 if ((attrs->ia_valid & ATTR_MTIME) &&
2786 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002787 rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002788 if (!rc) {
2789 tcon = tlink_tcon(wfile->tlink);
2790 rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
2791 cifsFileInfo_put(wfile);
2792 if (rc)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002793 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002794 } else if (rc != -EBADF)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002795 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002796 else
2797 rc = 0;
2798 }
2799
Steve French50531442008-03-14 19:21:31 +00002800 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002801 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2802 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002803 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002805
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002806 if (attrs->ia_valid & ATTR_UID)
2807 uid = attrs->ia_uid;
2808
2809 if (attrs->ia_valid & ATTR_GID)
2810 gid = attrs->ia_gid;
2811
Steve French22442172019-07-19 08:15:55 +00002812 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2813 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002814 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002815 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2816 uid, gid);
2817 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002818 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2819 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002820 goto cifs_setattr_exit;
2821 }
2822 }
2823 } else
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002824 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002825 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826
Jeff Laytond32c4f22007-10-18 03:05:22 -07002827 /* skip mode change if it's just for clearing setuid/setgid */
2828 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2829 attrs->ia_valid &= ~ATTR_MODE;
2830
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 mode = attrs->ia_mode;
Steve Frenchcdbce9c82005-11-19 21:04:52 -08002833 rc = 0;
Steve French22442172019-07-19 08:15:55 +00002834 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2835 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002836 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002837 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002838 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002839 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2840 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002841 goto cifs_setattr_exit;
2842 }
2843 } else
Jeff Layton51328612008-05-22 09:33:34 -04002844 if (((mode & S_IWUGO) == 0) &&
2845 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002846
2847 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2848
Jeff Layton51328612008-05-22 09:33:34 -04002849 /* fix up mode if we're not using dynperm */
2850 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2851 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2852 } else if ((mode & S_IWUGO) &&
2853 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002854
2855 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2856 /* Attributes of 0 are ignored */
2857 if (dosattr == 0)
2858 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002859
2860 /* reset local inode permissions to normal */
2861 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2862 attrs->ia_mode &= ~(S_IALLUGO);
2863 if (S_ISDIR(inode->i_mode))
2864 attrs->ia_mode |=
2865 cifs_sb->mnt_dir_mode;
2866 else
2867 attrs->ia_mode |=
2868 cifs_sb->mnt_file_mode;
2869 }
2870 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2871 /* ignore mode change - ATTR_READONLY hasn't changed */
2872 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 }
2875
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002876 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2877 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2878 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2879 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880
Steve Frenche30dcf32005-09-20 20:49:16 -07002881 /* Even if error on time set, no sense failing the call if
2882 the server would set the time to a reasonable value anyway,
2883 and this check ensures that we are not being called from
2884 sys_utimes in which case we ought to fail the call back to
2885 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002886 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002887 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002888 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889 }
2890
2891 /* do not need local check to inode_check_ok since the server does
2892 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002893 if (rc)
2894 goto cifs_setattr_exit;
2895
2896 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002897 attrs->ia_size != i_size_read(inode))
2898 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002899
2900 setattr_copy(inode, attrs);
2901 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002902
Steve Frenche30dcf32005-09-20 20:49:16 -07002903cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002905 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 return rc;
2907}
2908
Jeff Layton0510eeb2008-08-02 07:26:12 -04002909int
2910cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2911{
Al Virofc640052016-04-10 01:33:30 -04002912 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002913 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Ronnie Sahlbergc6cc4c52020-10-09 09:32:56 +10002914 int rc, retries = 0;
Jeff Layton0510eeb2008-08-02 07:26:12 -04002915
Ronnie Sahlbergc6cc4c52020-10-09 09:32:56 +10002916 do {
2917 if (pTcon->unix_ext)
2918 rc = cifs_setattr_unix(direntry, attrs);
2919 else
2920 rc = cifs_setattr_nounix(direntry, attrs);
2921 retries++;
2922 } while (is_retryable_error(rc) && retries < 2);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002923
2924 /* BB: add cifs_setattr_legacy for really old servers */
Ronnie Sahlbergc6cc4c52020-10-09 09:32:56 +10002925 return rc;
Jeff Layton0510eeb2008-08-02 07:26:12 -04002926}
2927
Steve French99ee4db2007-02-27 05:35:17 +00002928#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929void cifs_delete_inode(struct inode *inode)
2930{
Joe Perchesf96637b2013-05-04 22:12:25 -05002931 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 /* may have to add back in if and when safe distributed caching of
2933 directories added e.g. via FindNotify */
2934}
Steve French99ee4db2007-02-27 05:35:17 +00002935#endif