blob: c367195bdb0837768ed5007d86825b1d30f8ca09 [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,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400659 bool symlink)
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);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400687
688 if (symlink) {
689 fattr->cf_mode = S_IFLNK;
690 fattr->cf_dtype = DT_LNK;
691 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400692 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
693 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300694 /*
695 * Server can return wrong NumberOfLinks value for directories
696 * when Unix extensions are disabled - fake it.
697 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500698 if (!tcon->unix_ext)
699 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400700 } else {
701 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
702 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400703
Jeff Laytond0c280d2009-07-09 01:46:44 -0400704 /* clear write bits if ATTR_READONLY is set */
705 if (fattr->cf_cifsattrs & ATTR_READONLY)
706 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400707
Jim McDonough74d290d2013-09-21 10:36:10 -0500708 /*
709 * Don't accept zero nlink from non-unix servers unless
710 * delete is pending. Instead mark it as unknown.
711 */
712 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
713 !info->DeletePending) {
Joe Perchesfb4b5f12020-02-21 05:20:45 -0800714 cifs_dbg(VFS, "bogus file nlink value %u\n",
715 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500716 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500717 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300718 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400719
720 fattr->cf_uid = cifs_sb->mnt_uid;
721 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000722}
723
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700724static int
725cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500726{
727 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400728 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500729 FILE_ALL_INFO find_data;
730 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500731 struct inode *inode = file_inode(filp);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700732 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000733 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700734 struct TCP_Server_Info *server = tcon->ses->server;
735
736 if (!server->ops->query_file_info)
737 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500738
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400739 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700740 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400741 switch (rc) {
742 case 0:
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700743 cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400744 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400745 break;
746 case -EREMOTE:
747 cifs_create_dfs_fattr(&fattr, inode->i_sb);
748 rc = 0;
749 break;
750 case -EOPNOTSUPP:
751 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500752 /*
753 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000754 * for now, just skip revalidating and mark inode for
755 * immediate reval.
756 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500757 rc = 0;
758 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400759 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500760 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400761 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500762
763 /*
764 * don't bother with SFU junk here -- just mark inode as needing
765 * revalidation.
766 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500767 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
768 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
769 cifs_fattr_to_inode(inode, &fattr);
770cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400771 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500772 return rc;
773}
774
Steve French7ea884c2018-03-31 18:13:38 -0500775/* Simple function to return a 64 bit hash of string. Rarely called */
776static __u64 simple_hashstr(const char *str)
777{
Geert Uytterhoeven3995bbf2018-04-05 14:57:11 +0200778 const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
Steve French7ea884c2018-03-31 18:13:38 -0500779 __u64 hash = 0;
780
781 while (*str)
782 hash = (hash + (__u64) *str++) * hash_mult;
783
784 return hash;
785}
786
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100787/**
788 * cifs_backup_query_path_info - SMB1 fallback code to get ino
789 *
790 * Fallback code to get file metadata when we don't have access to
Geert Uytterhoeven3dc58df2020-05-05 15:43:35 +0200791 * @full_path (EACCES) and have backup creds.
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100792 *
793 * @data will be set to search info result buffer
794 * @resp_buf will be set to cifs resp buf and needs to be freed with
795 * cifs_buf_release() when done with @data.
796 */
797static int
798cifs_backup_query_path_info(int xid,
799 struct cifs_tcon *tcon,
800 struct super_block *sb,
801 const char *full_path,
802 void **resp_buf,
803 FILE_ALL_INFO **data)
804{
805 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
806 struct cifs_search_info info = {0};
807 u16 flags;
808 int rc;
809
810 *resp_buf = NULL;
811 info.endOfSearch = false;
812 if (tcon->unix_ext)
813 info.info_level = SMB_FIND_FILE_UNIX;
814 else if ((tcon->ses->capabilities &
815 tcon->ses->server->vals->cap_nt_find) == 0)
816 info.info_level = SMB_FIND_FILE_INFO_STANDARD;
817 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
818 info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
819 else /* no srvino useful for fallback to some netapp */
820 info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
821
822 flags = CIFS_SEARCH_CLOSE_ALWAYS |
823 CIFS_SEARCH_CLOSE_AT_END |
824 CIFS_SEARCH_BACKUP_SEARCH;
825
826 rc = CIFSFindFirst(xid, tcon, full_path,
827 cifs_sb, NULL, flags, &info, false);
828 if (rc)
829 return rc;
830
831 *resp_buf = (void *)info.ntwrk_buf_start;
832 *data = (FILE_ALL_INFO *)info.srch_entries_start;
833 return 0;
834}
835
836static void
837cifs_set_fattr_ino(int xid,
838 struct cifs_tcon *tcon,
839 struct super_block *sb,
840 struct inode **inode,
841 const char *full_path,
842 FILE_ALL_INFO *data,
843 struct cifs_fattr *fattr)
844{
845 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
846 struct TCP_Server_Info *server = tcon->ses->server;
847 int rc;
848
849 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
850 if (*inode)
851 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
852 else
853 fattr->cf_uniqueid = iunique(sb, ROOT_I);
854 return;
855 }
856
857 /*
858 * If we have an inode pass a NULL tcon to ensure we don't
859 * make a round trip to the server. This only works for SMB2+.
860 */
861 rc = server->ops->get_srv_inum(xid,
862 *inode ? NULL : tcon,
863 cifs_sb, full_path,
864 &fattr->cf_uniqueid,
865 data);
866 if (rc) {
867 /*
868 * If that fails reuse existing ino or generate one
869 * and disable server ones
870 */
871 if (*inode)
872 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
873 else {
874 fattr->cf_uniqueid = iunique(sb, ROOT_I);
875 cifs_autodisable_serverino(cifs_sb);
876 }
877 return;
878 }
879
880 /* If no errors, check for zero root inode (invalid) */
881 if (fattr->cf_uniqueid == 0 && strlen(full_path) == 0) {
882 cifs_dbg(FYI, "Invalid (0) inodenum\n");
883 if (*inode) {
884 /* reuse */
885 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
886 } else {
887 /* make an ino by hashing the UNC */
888 fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
889 fattr->cf_uniqueid = simple_hashstr(tcon->treeName);
890 }
891 }
892}
893
894static inline bool is_inode_cache_good(struct inode *ino)
895{
896 return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;
897}
898
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400899int
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100900cifs_get_inode_info(struct inode **inode,
901 const char *full_path,
902 FILE_ALL_INFO *in_data,
903 struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600904 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905{
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100906
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400907 struct cifs_tcon *tcon;
908 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400909 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400911 bool adjust_tz = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100912 struct cifs_fattr fattr = {0};
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400913 bool symlink = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100914 FILE_ALL_INFO *data = in_data;
915 FILE_ALL_INFO *tmp_data = NULL;
916 void *smb1_backup_rsp_buf = NULL;
917 int rc = 0;
918 int tmprc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Jeff Layton7ffec372010-09-29 19:51:11 -0400920 tlink = cifs_sb_tlink(cifs_sb);
921 if (IS_ERR(tlink))
922 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400923 tcon = tlink_tcon(tlink);
924 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400925
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100926 /*
927 * 1. Fetch file metadata if not provided (data)
928 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100930 if (!data) {
931 if (is_inode_cache_good(*inode)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500932 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100933 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100935 tmp_data = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
936 if (!tmp_data) {
Jeff Layton7ffec372010-09-29 19:51:11 -0400937 rc = -ENOMEM;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100938 goto out;
Jeff Layton7ffec372010-09-29 19:51:11 -0400939 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100940 rc = server->ops->query_path_info(xid, tcon, cifs_sb,
941 full_path, tmp_data,
942 &adjust_tz, &symlink);
943 data = tmp_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400945
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400946 /*
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100947 * 2. Convert it to internal cifs metadata (fattr)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400948 */
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100949
950 switch (rc) {
951 case 0:
952 cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
953 break;
954 case -EREMOTE:
955 /* DFS link, no metadata available on this server */
956 cifs_create_dfs_fattr(&fattr, sb);
957 rc = 0;
958 break;
959 case -EACCES:
960 /*
961 * perm errors, try again with backup flags if possible
962 *
963 * For SMB2 and later the backup intent flag
964 * is already sent if needed on open and there
965 * is no path based FindFirst operation to use
966 * to retry with
967 */
968 if (backup_cred(cifs_sb) && is_smb1_server(server)) {
969 /* for easier reading */
970 FILE_DIRECTORY_INFO *fdi;
971 SEARCH_ID_FULL_DIR_INFO *si;
972
973 rc = cifs_backup_query_path_info(xid, tcon, sb,
974 full_path,
975 &smb1_backup_rsp_buf,
976 &data);
977 if (rc)
978 goto out;
979
980 fdi = (FILE_DIRECTORY_INFO *)data;
981 si = (SEARCH_ID_FULL_DIR_INFO *)data;
982
983 cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb);
984 fattr.cf_uniqueid = le64_to_cpu(si->UniqueId);
985 /* uniqueid set, skip get inum step */
986 goto handle_mnt_opt;
987 } else {
988 /* nothing we can do, bail out */
989 goto out;
990 }
991 break;
992 default:
993 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
994 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000995 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000996
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100997 /*
998 * 3. Get or update inode number (fattr.cf_uniqueid)
999 */
1000
1001 cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);
1002
1003 /*
1004 * 4. Tweak fattr based on mount options
1005 */
1006
1007handle_mnt_opt:
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001008 /* query for SFU type info if supported and needed */
1009 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
1010 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
1011 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
1012 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001013 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001014 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001015
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001016 /* fill in 0777 bits from ACL */
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001017 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
1018 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
1019 full_path, fid);
1020 if (rc) {
1021 cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001022 __func__, rc);
1023 goto out;
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001024 }
1025 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
1026 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
Dan Carpenter via samba-technical68464b82019-11-26 15:11:15 +03001027 full_path, fid);
1028 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001029 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
1030 __func__, rc);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001031 goto out;
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06001032 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001033 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001034
1035 /* fill in remaining high mode bits e.g. SUID, VTX */
1036 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
1037 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
1038
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001039 /* check for Minshall+French symlinks */
1040 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +00001041 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
1042 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001043 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +00001044 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001045 }
1046
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001047 /*
1048 * 5. Update inode with final fattr data
1049 */
1050
Pavel Shilovsky1208ef12012-05-27 17:34:43 +04001051 if (!*inode) {
1052 *inode = cifs_iget(sb, &fattr);
1053 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001054 rc = -ENOMEM;
1055 } else {
Nakajima Akira7196ac12015-04-22 15:24:44 +09001056 /* we already have inode, update it */
1057
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001058 /* if uniqueid is different, return error */
1059 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1060 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001061 CIFS_I(*inode)->time = 0; /* force reval */
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001062 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001063 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001064 }
1065
Nakajima Akira7196ac12015-04-22 15:24:44 +09001066 /* if filetype is different, return error */
1067 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1068 (fattr.cf_mode & S_IFMT))) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001069 CIFS_I(*inode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +09001070 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001071 goto out;
Nakajima Akira7196ac12015-04-22 15:24:44 +09001072 }
1073
Pavel Shilovsky1208ef12012-05-27 17:34:43 +04001074 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001075 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001076out:
1077 cifs_buf_release(smb1_backup_rsp_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001078 cifs_put_tlink(tlink);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001079 kfree(tmp_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 return rc;
1081}
1082
Steve French6a5f6592020-06-11 19:25:47 -05001083int
1084smb311_posix_get_inode_info(struct inode **inode,
1085 const char *full_path,
1086 struct super_block *sb, unsigned int xid)
1087{
1088 struct cifs_tcon *tcon;
1089 struct TCP_Server_Info *server;
1090 struct tcon_link *tlink;
1091 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1092 bool adjust_tz = false;
1093 struct cifs_fattr fattr = {0};
1094 bool symlink = false;
1095 struct smb311_posix_qinfo *data = NULL;
1096 int rc = 0;
1097 int tmprc = 0;
1098
1099 tlink = cifs_sb_tlink(cifs_sb);
1100 if (IS_ERR(tlink))
1101 return PTR_ERR(tlink);
1102 tcon = tlink_tcon(tlink);
1103 server = tcon->ses->server;
1104
1105 /*
1106 * 1. Fetch file metadata
1107 */
1108
1109 if (is_inode_cache_good(*inode)) {
1110 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
1111 goto out;
1112 }
1113 data = kmalloc(sizeof(struct smb311_posix_qinfo), GFP_KERNEL);
1114 if (!data) {
1115 rc = -ENOMEM;
1116 goto out;
1117 }
1118
1119 rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
1120 full_path, data,
1121 &adjust_tz, &symlink);
1122
1123 /*
1124 * 2. Convert it to internal cifs metadata (fattr)
1125 */
1126
1127 switch (rc) {
1128 case 0:
1129 smb311_posix_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
1130 break;
1131 case -EREMOTE:
1132 /* DFS link, no metadata available on this server */
1133 cifs_create_dfs_fattr(&fattr, sb);
1134 rc = 0;
1135 break;
1136 case -EACCES:
1137 /*
1138 * For SMB2 and later the backup intent flag
1139 * is already sent if needed on open and there
1140 * is no path based FindFirst operation to use
1141 * to retry with so nothing we can do, bail out
1142 */
1143 goto out;
1144 default:
1145 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
1146 goto out;
1147 }
1148
1149
1150 /*
1151 * 4. Tweak fattr based on mount options
1152 */
1153
1154 /* check for Minshall+French symlinks */
1155 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
1156 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
1157 full_path);
1158 if (tmprc)
1159 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1160 }
1161
1162 /*
1163 * 5. Update inode with final fattr data
1164 */
1165
1166 if (!*inode) {
1167 *inode = cifs_iget(sb, &fattr);
1168 if (!*inode)
1169 rc = -ENOMEM;
1170 } else {
1171 /* we already have inode, update it */
1172
1173 /* if uniqueid is different, return error */
1174 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1175 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
1176 CIFS_I(*inode)->time = 0; /* force reval */
1177 rc = -ESTALE;
1178 goto out;
1179 }
1180
1181 /* if filetype is different, return error */
1182 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1183 (fattr.cf_mode & S_IFMT))) {
1184 CIFS_I(*inode)->time = 0; /* force reval */
1185 rc = -ESTALE;
1186 goto out;
1187 }
1188
1189 cifs_fattr_to_inode(*inode, &fattr);
1190 }
1191out:
1192 cifs_put_tlink(tlink);
1193 kfree(data);
1194 return rc;
1195}
1196
1197
Steve French7f8ed422007-09-28 22:28:55 +00001198static const struct inode_operations cifs_ipc_inode_ops = {
1199 .lookup = cifs_lookup,
1200};
1201
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001202static int
1203cifs_find_inode(struct inode *inode, void *opaque)
1204{
1205 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1206
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001207 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001208 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
1209 return 0;
1210
Jeff Layton20054bd2011-01-07 11:30:27 -05001211 /* use createtime like an i_generation field */
1212 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
1213 return 0;
1214
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001215 /* don't match inode of different type */
1216 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
1217 return 0;
1218
Jeff Layton5acfec22010-08-02 17:43:54 -04001219 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -04001220 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -04001221 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -04001222
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001223 return 1;
1224}
1225
1226static int
1227cifs_init_inode(struct inode *inode, void *opaque)
1228{
1229 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1230
1231 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -05001232 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001233 return 0;
1234}
1235
Jeff Layton5acfec22010-08-02 17:43:54 -04001236/*
1237 * walk dentry list for an inode and report whether it has aliases that
1238 * are hashed. We use this to determine if a directory inode can actually
1239 * be used.
1240 */
1241static bool
1242inode_has_hashed_dentries(struct inode *inode)
1243{
1244 struct dentry *dentry;
1245
Nick Piggin873feea2011-01-07 17:50:06 +11001246 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -04001247 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001248 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +11001249 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001250 return true;
1251 }
1252 }
Nick Piggin873feea2011-01-07 17:50:06 +11001253 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001254 return false;
1255}
1256
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001257/* Given fattrs, get a corresponding inode */
1258struct inode *
1259cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
1260{
1261 unsigned long hash;
1262 struct inode *inode;
1263
Jeff Layton3d694382010-05-11 14:59:55 -04001264retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -05001265 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001266
1267 /* hash down to 32-bits on 32-bit arch */
1268 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
1269
1270 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001271 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001272 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -04001273 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -04001274 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -04001275
1276 if (inode_has_hashed_dentries(inode)) {
1277 cifs_autodisable_serverino(CIFS_SB(sb));
1278 iput(inode);
1279 fattr->cf_uniqueid = iunique(sb, ROOT_I);
1280 goto retry_iget5_locked;
1281 }
Jeff Layton3d694382010-05-11 14:59:55 -04001282 }
1283
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001284 cifs_fattr_to_inode(inode, fattr);
Linus Torvalds1751e8a2017-11-27 13:05:09 -08001285 if (sb->s_flags & SB_NOATIME)
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001286 inode->i_flags |= S_NOATIME | S_NOCMTIME;
1287 if (inode->i_state & I_NEW) {
1288 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +00001289#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301290 /* initialize per-inode cache cookie pointer */
1291 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +00001292#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001293 unlock_new_inode(inode);
1294 }
1295 }
1296
1297 return inode;
1298}
1299
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001301struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001303 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001304 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001305 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001306 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001307 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001308 char *path = NULL;
1309 int len;
1310
1311 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1312 && cifs_sb->prepath) {
1313 len = strlen(cifs_sb->prepath);
1314 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1315 if (path == NULL)
1316 return ERR_PTR(-ENOMEM);
1317 path[0] = '/';
1318 memcpy(path+1, cifs_sb->prepath, len);
1319 } else {
1320 path = kstrdup("", GFP_KERNEL);
1321 if (path == NULL)
1322 return ERR_PTR(-ENOMEM);
1323 }
David Howellsce634ab2008-02-07 00:15:33 -08001324
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001325 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001326 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001327 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001328 /* some servers mistakenly claim POSIX support */
1329 if (rc != -EOPNOTSUPP)
1330 goto iget_no_retry;
Joe Perchesa0a30362020-04-14 22:42:53 -07001331 cifs_dbg(VFS, "server does not support POSIX extensions\n");
Steve Frenchb5b374e2014-10-06 01:01:03 -05001332 tcon->unix_ext = false;
1333 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001334
Aurelien Aptela6b50582016-05-25 19:59:09 +02001335 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
1336 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001337
1338iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001339 if (!inode) {
1340 inode = ERR_PTR(rc);
1341 goto out;
1342 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001343
Steve French0ccd4802010-07-16 04:31:02 +00001344#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301345 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001346 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001347#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301348
Aurelien Aptelb327a712018-01-24 13:46:10 +01001349 if (rc && tcon->pipe) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001350 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001351 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001352 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001353 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001354 inode->i_op = &cifs_ipc_inode_ops;
1355 inode->i_fop = &simple_dir_operations;
1356 inode->i_uid = cifs_sb->mnt_uid;
1357 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001358 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001359 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001360 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001361 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001362 }
1363
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001364out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001365 kfree(path);
Phillip Potter31cd1062018-03-17 21:06:56 +00001366 free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001367 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368}
1369
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001370int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001371cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001372 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001373{
Steve French388e57b2008-09-16 23:50:58 +00001374 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001375 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001376 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001377 FILE_BASIC_INFO info_buf;
1378
Steve French1adcb712009-02-25 14:19:56 +00001379 if (attrs == NULL)
1380 return -EINVAL;
1381
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001382 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1383 if (!server->ops->set_file_info)
1384 return -ENOSYS;
1385
Steve Frenchfd09b7d2018-08-02 20:28:18 -05001386 info_buf.Pad = 0;
1387
Steve French388e57b2008-09-16 23:50:58 +00001388 if (attrs->ia_valid & ATTR_ATIME) {
1389 set_time = true;
1390 info_buf.LastAccessTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001391 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
Steve French388e57b2008-09-16 23:50:58 +00001392 } else
1393 info_buf.LastAccessTime = 0;
1394
1395 if (attrs->ia_valid & ATTR_MTIME) {
1396 set_time = true;
1397 info_buf.LastWriteTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001398 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
Steve French388e57b2008-09-16 23:50:58 +00001399 } else
1400 info_buf.LastWriteTime = 0;
1401
1402 /*
1403 * Samba throws this field away, but windows may actually use it.
1404 * Do not set ctime unless other time stamps are changed explicitly
1405 * (i.e. by utimes()) since we would then have a mix of client and
1406 * server times.
1407 */
1408 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001409 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001410 info_buf.ChangeTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001411 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
Steve French388e57b2008-09-16 23:50:58 +00001412 } else
1413 info_buf.ChangeTime = 0;
1414
1415 info_buf.CreationTime = 0; /* don't change */
1416 info_buf.Attributes = cpu_to_le32(dosattr);
1417
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001418 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001419}
1420
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001421/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001422 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001423 * and rename it to a random name that hopefully won't conflict with
1424 * anything else.
1425 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001426int
1427cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1428 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001429{
1430 int oplock = 0;
1431 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001432 struct cifs_fid fid;
1433 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001434 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001435 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1436 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001437 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001438 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001439 __u32 dosattr, origattr;
1440 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001441
Jeff Layton7ffec372010-09-29 19:51:11 -04001442 tlink = cifs_sb_tlink(cifs_sb);
1443 if (IS_ERR(tlink))
1444 return PTR_ERR(tlink);
1445 tcon = tlink_tcon(tlink);
1446
Sachin Prabhuc483a982013-03-05 19:25:56 +00001447 /*
1448 * We cannot rename the file if the server doesn't support
1449 * CAP_INFOLEVEL_PASSTHRU
1450 */
1451 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1452 rc = -EBUSY;
1453 goto out;
1454 }
1455
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001456 oparms.tcon = tcon;
1457 oparms.cifs_sb = cifs_sb;
1458 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
Amir Goldstein0f060932020-02-03 21:46:43 +02001459 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001460 oparms.disposition = FILE_OPEN;
1461 oparms.path = full_path;
1462 oparms.fid = &fid;
1463 oparms.reconnect = false;
1464
1465 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001466 if (rc != 0)
1467 goto out;
1468
Steve French32709582008-10-20 00:44:19 +00001469 origattr = cifsInode->cifsAttrs;
1470 if (origattr == 0)
1471 origattr |= ATTR_NORMAL;
1472
1473 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001474 if (dosattr == 0)
1475 dosattr |= ATTR_NORMAL;
1476 dosattr |= ATTR_HIDDEN;
1477
Steve French32709582008-10-20 00:44:19 +00001478 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1479 if (dosattr != origattr) {
1480 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1481 if (info_buf == NULL) {
1482 rc = -ENOMEM;
1483 goto out_close;
1484 }
1485 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001486 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001487 current->tgid);
1488 /* although we would like to mark the file hidden
1489 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001490 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001491 cifsInode->cifsAttrs = dosattr;
1492 else
1493 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001494 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001495
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001496 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001497 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1498 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001499 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001500 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001501 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001502 goto undo_setattr;
1503 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001504
Steve French32709582008-10-20 00:44:19 +00001505 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001506 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001507 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001508 current->tgid);
1509 /*
1510 * some samba versions return -ENOENT when we try to set the
1511 * file disposition here. Likely a samba bug, but work around
1512 * it for now. This means that some cifsXXX files may hang
1513 * around after they shouldn't.
1514 *
1515 * BB: remove this hack after more servers have the fix
1516 */
1517 if (rc == -ENOENT)
1518 rc = 0;
1519 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001520 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001521 goto undo_rename;
1522 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001523 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001524 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001525
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001526out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001527 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001528out:
Steve French32709582008-10-20 00:44:19 +00001529 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001530 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001531 return rc;
Steve French32709582008-10-20 00:44:19 +00001532
1533 /*
1534 * reset everything back to the original state. Don't bother
1535 * dealing with errors here since we can't do anything about
1536 * them anyway.
1537 */
1538undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001539 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001540 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001541undo_setattr:
1542 if (dosattr != origattr) {
1543 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001544 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001545 current->tgid))
1546 cifsInode->cifsAttrs = origattr;
1547 }
1548
1549 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001550}
1551
Steve Frenchb7ca6922012-08-03 08:43:01 -05001552/* copied from fs/nfs/dir.c with small changes */
1553static void
1554cifs_drop_nlink(struct inode *inode)
1555{
1556 spin_lock(&inode->i_lock);
1557 if (inode->i_nlink > 0)
1558 drop_nlink(inode);
1559 spin_unlock(&inode->i_lock);
1560}
Steve Frenchff694522009-04-20 19:45:13 +00001561
1562/*
David Howells2b0143b2015-03-17 22:25:59 +00001563 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001564 * is a negative dentry) then we would attempt a standard SMB delete, but
Colin Ian King413d6102018-10-26 19:07:21 +01001565 * if that fails we can not attempt the fall back mechanisms on EACCES
1566 * but will return the EACCES to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001567 * unlink on negative dentries currently.
1568 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001569int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570{
1571 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001572 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001574 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001575 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001576 struct super_block *sb = dir->i_sb;
1577 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001578 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001579 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001580 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001581 struct iattr *attrs = NULL;
1582 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Joe Perchesf96637b2013-05-04 22:12:25 -05001584 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585
Jeff Layton7ffec372010-09-29 19:51:11 -04001586 tlink = cifs_sb_tlink(cifs_sb);
1587 if (IS_ERR(tlink))
1588 return PTR_ERR(tlink);
1589 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001590 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001591
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001592 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593
Steve French82e93672020-05-19 03:06:57 -05001594 if (tcon->nodelete) {
1595 rc = -EACCES;
1596 goto unlink_out;
1597 }
1598
Jeff Layton5f0319a2008-09-16 14:05:16 -04001599 /* Unlink can be called from rename so we can not take the
1600 * sb->s_vfs_rename_mutex here */
1601 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301603 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001604 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 }
Steve French2d785a52007-07-15 01:48:57 +00001606
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001607 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1608 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001609 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001610 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001611 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001612 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001613 if ((rc == 0) || (rc == -ENOENT))
1614 goto psx_del_no_retry;
1615 }
1616
Steve French60502472008-10-07 18:42:52 +00001617retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001618 if (!server->ops->unlink) {
1619 rc = -ENOSYS;
1620 goto psx_del_no_retry;
1621 }
1622
1623 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001624
Steve French2d785a52007-07-15 01:48:57 +00001625psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001627 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001628 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001630 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001631 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001632 if (server->ops->rename_pending_delete) {
1633 rc = server->ops->rename_pending_delete(full_path,
1634 dentry, xid);
1635 if (rc == 0)
1636 cifs_drop_nlink(inode);
1637 }
Steve Frenchff694522009-04-20 19:45:13 +00001638 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001639 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1640 if (attrs == NULL) {
1641 rc = -ENOMEM;
1642 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 }
Steve French388e57b2008-09-16 23:50:58 +00001644
1645 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001646 cifs_inode = CIFS_I(inode);
1647 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001648 if (origattr == 0)
1649 origattr |= ATTR_NORMAL;
1650 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001651 if (dosattr == 0)
1652 dosattr |= ATTR_NORMAL;
1653 dosattr |= ATTR_HIDDEN;
1654
1655 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001656 if (rc != 0)
1657 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001658
1659 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 }
Steve French60502472008-10-07 18:42:52 +00001661
1662 /* undo the setattr if we errored out and it's needed */
1663 if (rc != 0 && dosattr != 0)
1664 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1665
Steve French388e57b2008-09-16 23:50:58 +00001666out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001667 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001668 cifs_inode = CIFS_I(inode);
1669 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001670 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001671 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001672 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001673 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001674 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001675 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001676unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001678 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001679 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001680 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 return rc;
1682}
1683
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001684static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001685cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001686 const char *full_path, struct cifs_sb_info *cifs_sb,
1687 struct cifs_tcon *tcon, const unsigned int xid)
1688{
1689 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001690 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001691
1692 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001693 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001694 xid);
1695 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001696 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1697 xid, NULL);
1698
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001699 if (rc)
1700 return rc;
1701
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001702 /*
1703 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001704 * from the server or was set bogus. Also, since this is a brand new
1705 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001706 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001707 if (inode->i_nlink < 2)
1708 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001709 mode &= ~current_umask();
1710 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001711 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001712 mode |= S_ISGID;
1713
1714 if (tcon->unix_ext) {
1715 struct cifs_unix_set_info_args args = {
1716 .mode = mode,
1717 .ctime = NO_CHANGE_64,
1718 .atime = NO_CHANGE_64,
1719 .mtime = NO_CHANGE_64,
1720 .device = 0,
1721 };
1722 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001723 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001724 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001725 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001726 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001727 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001728 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001729 args.uid = INVALID_UID; /* no change */
1730 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001731 }
1732 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1733 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001734 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001735 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001736 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001737 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001738 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001739 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001740 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001741 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1742 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001743
Jeff Layton101b92d2012-09-19 06:22:45 -07001744 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1745 inode->i_uid = current_fsuid();
1746 if (inode->i_mode & S_ISGID)
1747 inode->i_gid = parent->i_gid;
1748 else
1749 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001750 }
1751 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001752 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001753 return rc;
1754}
1755
1756static int
1757cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1758 const char *full_path, struct cifs_sb_info *cifs_sb,
1759 struct cifs_tcon *tcon, const unsigned int xid)
1760{
1761 int rc = 0;
1762 u32 oplock = 0;
1763 FILE_UNIX_BASIC_INFO *info = NULL;
1764 struct inode *newinode = NULL;
1765 struct cifs_fattr fattr;
1766
1767 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1768 if (info == NULL) {
1769 rc = -ENOMEM;
1770 goto posix_mkdir_out;
1771 }
1772
1773 mode &= ~current_umask();
1774 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1775 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001776 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001777 if (rc == -EOPNOTSUPP)
1778 goto posix_mkdir_out;
1779 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001780 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001781 d_drop(dentry);
1782 goto posix_mkdir_out;
1783 }
1784
1785 if (info->Type == cpu_to_le32(-1))
1786 /* no return info, go query for it */
1787 goto posix_mkdir_get_info;
1788 /*
1789 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1790 * need to set uid/gid.
1791 */
1792
1793 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1794 cifs_fill_uniqueid(inode->i_sb, &fattr);
1795 newinode = cifs_iget(inode->i_sb, &fattr);
1796 if (!newinode)
1797 goto posix_mkdir_get_info;
1798
1799 d_instantiate(dentry, newinode);
1800
1801#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001802 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1803 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001804
1805 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001806 cifs_dbg(FYI, "unexpected number of links %d\n",
1807 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001808#endif
1809
1810posix_mkdir_out:
1811 kfree(info);
1812 return rc;
1813posix_mkdir_get_info:
1814 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1815 xid);
1816 goto posix_mkdir_out;
1817}
1818
Al Viro18bb1db2011-07-26 01:41:39 -04001819int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001821 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001822 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001824 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001825 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001826 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001827 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828
Frank Sorensonf52aa792020-02-12 15:31:48 -06001829 cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05001830 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001833 tlink = cifs_sb_tlink(cifs_sb);
1834 if (IS_ERR(tlink))
1835 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001836 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001837
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001838 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
Steve French7f573562005-08-30 11:32:14 -07001840 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301842 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001843 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 }
Steve French50c2f752007-07-13 00:33:32 +00001845
Steve Frenchbea851b2018-06-14 21:56:32 -05001846 server = tcon->ses->server;
1847
Steve Frenchbea851b2018-06-14 21:56:32 -05001848 if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
1849 rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
1850 cifs_sb);
1851 d_drop(direntry); /* for time being always refresh inode info */
1852 goto mkdir_out;
1853 }
Steve Frenchbea851b2018-06-14 21:56:32 -05001854
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001855 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1856 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001857 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1858 tcon, xid);
1859 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001860 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001861 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001862
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001863 if (!server->ops->mkdir) {
1864 rc = -ENOSYS;
1865 goto mkdir_out;
1866 }
1867
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001869 rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001871 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001873 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001875
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001876 /* TODO: skip this for smb2/smb3 */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001877 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1878 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001879mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001880 /*
1881 * Force revalidate to get parent dir info when needed since cached
1882 * attributes are invalid now.
1883 */
1884 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001886 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001887 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 return rc;
1889}
1890
1891int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1892{
1893 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001894 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001896 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001897 struct cifs_tcon *tcon;
1898 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 char *full_path = NULL;
1900 struct cifsInodeInfo *cifsInode;
1901
Joe Perchesf96637b2013-05-04 22:12:25 -05001902 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001904 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905
Steve French7f573562005-08-30 11:32:14 -07001906 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301908 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001909 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 }
1911
Jeff Layton7ffec372010-09-29 19:51:11 -04001912 cifs_sb = CIFS_SB(inode->i_sb);
1913 tlink = cifs_sb_tlink(cifs_sb);
1914 if (IS_ERR(tlink)) {
1915 rc = PTR_ERR(tlink);
1916 goto rmdir_exit;
1917 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001918 tcon = tlink_tcon(tlink);
1919 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001920
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001921 if (!server->ops->rmdir) {
1922 rc = -ENOSYS;
1923 cifs_put_tlink(tlink);
1924 goto rmdir_exit;
1925 }
1926
Steve French82e93672020-05-19 03:06:57 -05001927 if (tcon->nodelete) {
1928 rc = -EACCES;
1929 cifs_put_tlink(tlink);
1930 goto rmdir_exit;
1931 }
1932
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001933 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001934 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935
1936 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001937 spin_lock(&d_inode(direntry)->i_lock);
1938 i_size_write(d_inode(direntry), 0);
1939 clear_nlink(d_inode(direntry));
1940 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 }
1942
David Howells2b0143b2015-03-17 22:25:59 +00001943 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001944 /* force revalidate to go get info when needed */
1945 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001946
1947 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001948 /*
1949 * Force revalidate to get parent dir info when needed since cached
1950 * attributes are invalid now.
1951 */
1952 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001953
David Howells2b0143b2015-03-17 22:25:59 +00001954 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001955 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956
Jeff Layton7ffec372010-09-29 19:51:11 -04001957rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001959 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 return rc;
1961}
1962
Steve Frenchee2fd962008-09-23 18:23:33 +00001963static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001964cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1965 const char *from_path, struct dentry *to_dentry,
1966 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001967{
1968 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001969 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001970 struct cifs_tcon *tcon;
1971 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001972 struct cifs_fid fid;
1973 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001974 int oplock, rc;
1975
Jeff Layton7ffec372010-09-29 19:51:11 -04001976 tlink = cifs_sb_tlink(cifs_sb);
1977 if (IS_ERR(tlink))
1978 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001979 tcon = tlink_tcon(tlink);
1980 server = tcon->ses->server;
1981
1982 if (!server->ops->rename)
1983 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001984
Steve Frenchee2fd962008-09-23 18:23:33 +00001985 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001986 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001987
1988 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001989 * Don't bother with rename by filehandle unless file is busy and
1990 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001991 * rename by filehandle to various Windows servers.
1992 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001993 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001994 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001995
Frank Sorenson652727b2019-04-16 08:37:27 -05001996 /* Don't fall back to using SMB on SMB 2+ mount */
1997 if (server->vals->protocol_id != 0)
1998 goto do_rename_exit;
1999
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04002000 /* open-file renames don't work across directories */
2001 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04002002 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04002003
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002004 oparms.tcon = tcon;
2005 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00002006 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002007 oparms.desired_access = DELETE;
Amir Goldstein0f060932020-02-03 21:46:43 +02002008 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002009 oparms.disposition = FILE_OPEN;
2010 oparms.path = from_path;
2011 oparms.fid = &fid;
2012 oparms.reconnect = false;
2013
2014 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00002015 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002016 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00002017 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05002018 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002019 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00002020 }
Jeff Layton7ffec372010-09-29 19:51:11 -04002021do_rename_exit:
Steve Frenchc7e9f782020-02-25 18:08:54 -06002022 if (rc == 0)
2023 d_move(from_dentry, to_dentry);
Jeff Layton7ffec372010-09-29 19:51:11 -04002024 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00002025 return rc;
2026}
2027
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002028int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002029cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
2030 struct inode *target_dir, struct dentry *target_dentry,
2031 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002033 char *from_name = NULL;
2034 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04002035 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04002036 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002037 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00002038 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
2039 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002040 unsigned int xid;
2041 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002043 if (flags & ~RENAME_NOREPLACE)
2044 return -EINVAL;
2045
Jeff Layton639e7a92010-09-03 11:50:09 -04002046 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002047 tlink = cifs_sb_tlink(cifs_sb);
2048 if (IS_ERR(tlink))
2049 return PTR_ERR(tlink);
2050 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002052 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00002053
2054 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00002055 * we already have the rename sem so we do not need to
2056 * grab it again here to protect the path integrity
2057 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002058 from_name = build_path_from_dentry(source_dentry);
2059 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 rc = -ENOMEM;
2061 goto cifs_rename_exit;
2062 }
2063
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002064 to_name = build_path_from_dentry(target_dentry);
2065 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00002066 rc = -ENOMEM;
2067 goto cifs_rename_exit;
2068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002070 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
2071 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00002072
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002073 /*
2074 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
2075 */
2076 if (flags & RENAME_NOREPLACE)
2077 goto cifs_rename_exit;
2078
Jeff Layton14121bd2008-10-20 14:45:22 -04002079 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00002080 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002081 * Are src and dst hardlinks of same inode? We can only tell
2082 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00002083 */
Jeff Layton14121bd2008-10-20 14:45:22 -04002084 info_buf_source =
Kees Cook6da2ec52018-06-12 13:55:00 -07002085 kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
Jeff Layton14121bd2008-10-20 14:45:22 -04002086 GFP_KERNEL);
2087 if (info_buf_source == NULL) {
2088 rc = -ENOMEM;
2089 goto cifs_rename_exit;
2090 }
2091
2092 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002093 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
2094 info_buf_source,
2095 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002096 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04002097 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04002098 goto unlink_target;
2099
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002100 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
2101 info_buf_target,
2102 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002103 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04002104
Jeff Layton8d281ef2008-10-22 13:57:01 -04002105 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05002106 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04002107 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05002108 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04002109 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05002110 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002111 }
2112 /*
2113 * else ... BB we could add the same check for Windows by
2114 * checking the UniqueId via FILE_INTERNAL_INFO
2115 */
Jeff Layton14121bd2008-10-20 14:45:22 -04002116
Jeff Layton14121bd2008-10-20 14:45:22 -04002117unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04002118 /* Try unlinking the target dentry if it's not negative */
David Howells2b0143b2015-03-17 22:25:59 +00002119 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04002120 if (d_is_dir(target_dentry))
2121 tmprc = cifs_rmdir(target_dir, target_dentry);
2122 else
2123 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04002124 if (tmprc)
2125 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002126 rc = cifs_do_rename(xid, source_dentry, from_name,
2127 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 }
2129
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04002130 /* force revalidate to go get info when needed */
2131 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
2132
2133 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07002134 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04002135
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00002137 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002138 kfree(from_name);
2139 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002140 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04002141 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 return rc;
2143}
2144
Jeff Laytondf2cf172010-02-12 07:44:16 -05002145static bool
2146cifs_inode_needs_reval(struct inode *inode)
2147{
2148 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302149 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002150
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002151 if (cifs_i->time == 0)
2152 return true;
2153
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002154 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05002155 return false;
2156
2157 if (!lookupCacheEnabled)
2158 return true;
2159
Jeff Laytona87c9ad2014-03-26 07:24:23 -07002160 if (!cifs_sb->actimeo)
2161 return true;
2162
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302163 if (!time_in_range(jiffies, cifs_i->time,
2164 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05002165 return true;
2166
Jeff Laytondb192722010-05-17 14:51:49 -04002167 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302168 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04002169 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
2170 return true;
2171
Jeff Laytondf2cf172010-02-12 07:44:16 -05002172 return false;
2173}
2174
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05302175/*
2176 * Zap the cache. Called when invalid_mapping flag is set.
2177 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002178int
Jeff Laytondf2cf172010-02-12 07:44:16 -05002179cifs_invalidate_mapping(struct inode *inode)
2180{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002181 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002182
Jeff Laytondf2cf172010-02-12 07:44:16 -05002183 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002184 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002185 if (rc)
Joe Perchesa0a30362020-04-14 22:42:53 -07002186 cifs_dbg(VFS, "%s: Could not invalidate inode %p\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05002187 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002188 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002189
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05302190 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002191 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002192}
2193
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002194/**
2195 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
2196 * @word: long word containing the bit lock
2197 */
2198static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002199cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002200{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002201 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002202 if (signal_pending_state(mode, current))
2203 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002204 return 0;
2205}
2206
Jeff Laytone284e532014-04-30 09:31:46 -04002207int
2208cifs_revalidate_mapping(struct inode *inode)
2209{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002210 int rc;
2211 unsigned long *flags = &CIFS_I(inode)->flags;
2212
Steve French4e8aea32020-04-09 21:42:18 -05002213 /* swapfiles are not supposed to be shared */
2214 if (IS_SWAPFILE(inode))
2215 return 0;
2216
NeilBrown74316202014-07-07 15:16:04 +10002217 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
2218 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002219 if (rc)
2220 return rc;
2221
2222 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
2223 rc = cifs_invalidate_mapping(inode);
2224 if (rc)
2225 set_bit(CIFS_INO_INVALID_MAPPING, flags);
2226 }
2227
2228 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07002229 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002230 wake_up_bit(flags, CIFS_INO_LOCK);
2231
2232 return rc;
2233}
2234
2235int
2236cifs_zap_mapping(struct inode *inode)
2237{
2238 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
2239 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04002240}
2241
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002242int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05002243{
2244 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05002245 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba642010-09-20 16:01:31 -07002246 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05002247
2248 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002249 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05002250
Jeff Layton13cfb732010-09-29 19:51:11 -04002251 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05002252 rc = cifs_get_file_info_unix(filp);
2253 else
2254 rc = cifs_get_file_info(filp);
2255
Jeff Laytonabab0952010-02-12 07:44:18 -05002256 return rc;
2257}
2258
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002259int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002261 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002262 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00002263 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002264 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002265 char *full_path = NULL;
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002266 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267
Jeff Laytondf2cf172010-02-12 07:44:16 -05002268 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 return -ENOENT;
2270
Jeff Laytondf2cf172010-02-12 07:44:16 -05002271 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002272 return rc;
2273
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002274 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
2276 /* can not safely grab the rename sem here if rename calls revalidate
2277 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05002278 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302280 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002281 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05002283
Joe Perchesf96637b2013-05-04 22:12:25 -05002284 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
2285 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02002286 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002288again:
Steve French6a5f6592020-06-11 19:25:47 -05002289 if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
2290 rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
2291 else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05002292 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
2293 else
2294 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
2295 xid, NULL);
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002296 if (rc == -EAGAIN && count++ < 10)
2297 goto again;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002298out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002300 free_xid(xid);
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002301
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 return rc;
2303}
2304
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002305int cifs_revalidate_file(struct file *filp)
2306{
2307 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002308 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002309
2310 rc = cifs_revalidate_file_attr(filp);
2311 if (rc)
2312 return rc;
2313
Jeff Laytone284e532014-04-30 09:31:46 -04002314 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002315}
2316
2317/* revalidate a dentry's inode attributes */
2318int cifs_revalidate_dentry(struct dentry *dentry)
2319{
2320 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002321 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002322
2323 rc = cifs_revalidate_dentry_attr(dentry);
2324 if (rc)
2325 return rc;
2326
Jeff Laytone284e532014-04-30 09:31:46 -04002327 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002328}
2329
David Howellsa528d352017-01-31 16:46:22 +00002330int cifs_getattr(const struct path *path, struct kstat *stat,
2331 u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332{
David Howellsa528d352017-01-31 16:46:22 +00002333 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002334 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002335 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002336 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002337 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002338
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002339 /*
2340 * We need to be sure that all dirty pages are written and the server
2341 * has actual ctime, mtime and file length.
2342 */
Steve Frenchffdec8d2020-02-18 18:07:57 -06002343 if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE)) &&
2344 !CIFS_CACHE_READ(CIFS_I(inode)) &&
2345 inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002346 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002347 if (rc) {
2348 mapping_set_error(inode->i_mapping, rc);
2349 return rc;
2350 }
Steve French5fe14c82006-11-07 19:26:33 +00002351 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002352
Steve Frenchffdec8d2020-02-18 18:07:57 -06002353 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC)
2354 CIFS_I(inode)->time = 0; /* force revalidate */
2355
2356 /*
2357 * If the caller doesn't require syncing, only sync if
2358 * necessary (e.g. due to earlier truncate or setattr
2359 * invalidating the cached metadata)
2360 */
2361 if (((flags & AT_STATX_SYNC_TYPE) != AT_STATX_DONT_SYNC) ||
2362 (CIFS_I(inode)->time == 0)) {
2363 rc = cifs_revalidate_dentry_attr(dentry);
2364 if (rc)
2365 return rc;
2366 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002367
2368 generic_fillattr(inode, stat);
Steve Frenche8506d22019-02-28 21:32:15 -06002369 stat->blksize = cifs_sb->bsize;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002370 stat->ino = CIFS_I(inode)->uniqueid;
2371
Steve French6e70e262017-09-21 21:32:29 -05002372 /* old CIFS Unix Extensions doesn't return create time */
2373 if (CIFS_I(inode)->createtime) {
2374 stat->result_mask |= STATX_BTIME;
Arnd Bergmann95390202018-06-19 17:27:58 +02002375 stat->btime =
2376 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
Steve French6e70e262017-09-21 21:32:29 -05002377 }
2378
2379 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2380 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2381 stat->attributes |= STATX_ATTR_COMPRESSED;
2382 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2383 stat->attributes |= STATX_ATTR_ENCRYPTED;
2384
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002385 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002386 * If on a multiuser mount without unix extensions or cifsacl being
2387 * enabled, and the admin hasn't overridden them, set the ownership
2388 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002389 */
2390 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002391 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002392 !tcon->unix_ext) {
2393 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2394 stat->uid = current_fsuid();
2395 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2396 stat->gid = current_fsgid();
2397 }
Dan Carpenter39946882020-02-28 12:22:59 +03002398 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399}
2400
Ronnie Sahlberg2f3ebab2019-04-25 16:45:29 +10002401int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
2402 u64 len)
2403{
2404 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2405 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->vfs_inode.i_sb);
2406 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2407 struct TCP_Server_Info *server = tcon->ses->server;
2408 struct cifsFileInfo *cfile;
2409 int rc;
2410
2411 /*
2412 * We need to be sure that all dirty pages are written as they
2413 * might fill holes on the server.
2414 */
2415 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
2416 inode->i_mapping->nrpages != 0) {
2417 rc = filemap_fdatawait(inode->i_mapping);
2418 if (rc) {
2419 mapping_set_error(inode->i_mapping, rc);
2420 return rc;
2421 }
2422 }
2423
2424 cfile = find_readable_file(cifs_i, false);
2425 if (cfile == NULL)
2426 return -EINVAL;
2427
2428 if (server->ops->fiemap) {
2429 rc = server->ops->fiemap(tcon, cfile, fei, start, len);
2430 cifsFileInfo_put(cfile);
2431 return rc;
2432 }
2433
2434 cifsFileInfo_put(cfile);
2435 return -ENOTSUPP;
2436}
2437
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002438int cifs_truncate_page(struct address_space *mapping, loff_t from)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002440 pgoff_t index = from >> PAGE_SHIFT;
2441 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 int rc = 0;
2444
2445 page = grab_cache_page(mapping, index);
2446 if (!page)
2447 return -ENOMEM;
2448
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002449 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002451 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 return rc;
2453}
2454
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002455void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002456{
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002457 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2458
Steve Frenchba6a46a2007-02-26 20:06:29 +00002459 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002460 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002461 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002462
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002463 /* Cached inode must be refreshed on truncate */
2464 cifs_i->time = 0;
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002465 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002466}
2467
Jeff Layton8efdbde2008-07-23 21:28:12 +00002468static int
2469cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002470 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002471{
2472 int rc;
2473 struct cifsFileInfo *open_file;
2474 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2475 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002476 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002477 struct cifs_tcon *tcon = NULL;
2478 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002479
2480 /*
2481 * To avoid spurious oplock breaks from server, in the case of
2482 * inodes that we already have open, avoid doing path based
2483 * setting of file size if we can do it by handle.
2484 * This keeps our caching token (oplock) and avoids timeouts
2485 * when the local oplock break takes longer to flush
2486 * writebehind data than the SMB timeout for the SetPathInfo
2487 * request would allow
2488 */
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002489 open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002490 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002491 tcon = tlink_tcon(open_file->tlink);
2492 server = tcon->ses->server;
2493 if (server->ops->set_file_size)
2494 rc = server->ops->set_file_size(xid, tcon, open_file,
2495 attrs->ia_size, false);
2496 else
2497 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002498 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002499 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002500 } else
2501 rc = -EINVAL;
2502
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002503 if (!rc)
2504 goto set_size_out;
Jeff Laytonba00ba642010-09-20 16:01:31 -07002505
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002506 if (tcon == NULL) {
2507 tlink = cifs_sb_tlink(cifs_sb);
2508 if (IS_ERR(tlink))
2509 return PTR_ERR(tlink);
2510 tcon = tlink_tcon(tlink);
2511 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002512 }
2513
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002514 /*
2515 * Set file size by pathname rather than by handle either because no
2516 * valid, writeable file handle for it was found or because there was
2517 * an error setting it by handle.
2518 */
2519 if (server->ops->set_path_size)
2520 rc = server->ops->set_path_size(xid, tcon, full_path,
2521 attrs->ia_size, cifs_sb, false);
2522 else
2523 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002524 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002525
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002526 if (tlink)
2527 cifs_put_tlink(tlink);
2528
2529set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002530 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002531 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002532 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002533 cifs_truncate_page(inode->i_mapping, inode->i_size);
2534 }
2535
2536 return rc;
2537}
2538
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002539static int
2540cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2541{
2542 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002543 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002544 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002545 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002546 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2547 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002548 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002549 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002550 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002551 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002552
Al Viro35c265e2014-08-19 20:25:34 -04002553 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2554 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002555
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002556 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002557
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002558 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2559 attrs->ia_valid |= ATTR_FORCE;
2560
Jan Kara31051c82016-05-26 16:55:18 +02002561 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002562 if (rc < 0)
2563 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002564
2565 full_path = build_path_from_dentry(direntry);
2566 if (full_path == NULL) {
2567 rc = -ENOMEM;
2568 goto out;
2569 }
2570
Jeff Layton0f4d6342009-03-26 13:35:37 -04002571 /*
2572 * Attempt to flush data before changing attributes. We need to do
2573 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2574 * ownership or mode then we may also need to do this. Here, we take
2575 * the safe way out and just do the flush on all setattr requests. If
2576 * the flush returns error, store it to report later and continue.
2577 *
2578 * BB: This should be smarter. Why bother flushing pages that
2579 * will be truncated anyway? Also, should we error out here if
2580 * the flush returns error?
2581 */
2582 rc = filemap_write_and_wait(inode->i_mapping);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002583 if (is_interrupt_error(rc)) {
2584 rc = -ERESTARTSYS;
2585 goto out;
2586 }
2587
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002588 mapping_set_error(inode->i_mapping, rc);
2589 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002590
2591 if (attrs->ia_valid & ATTR_SIZE) {
2592 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2593 if (rc != 0)
2594 goto out;
2595 }
2596
2597 /* skip mode change if it's just for clearing setuid/setgid */
2598 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2599 attrs->ia_valid &= ~ATTR_MODE;
2600
2601 args = kmalloc(sizeof(*args), GFP_KERNEL);
2602 if (args == NULL) {
2603 rc = -ENOMEM;
2604 goto out;
2605 }
2606
2607 /* set up the struct */
2608 if (attrs->ia_valid & ATTR_MODE)
2609 args->mode = attrs->ia_mode;
2610 else
2611 args->mode = NO_CHANGE_64;
2612
2613 if (attrs->ia_valid & ATTR_UID)
2614 args->uid = attrs->ia_uid;
2615 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002616 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002617
2618 if (attrs->ia_valid & ATTR_GID)
2619 args->gid = attrs->ia_gid;
2620 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002621 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002622
2623 if (attrs->ia_valid & ATTR_ATIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002624 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002625 else
2626 args->atime = NO_CHANGE_64;
2627
2628 if (attrs->ia_valid & ATTR_MTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002629 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002630 else
2631 args->mtime = NO_CHANGE_64;
2632
2633 if (attrs->ia_valid & ATTR_CTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002634 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002635 else
2636 args->ctime = NO_CHANGE_64;
2637
2638 args->device = 0;
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002639 open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002640 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002641 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002642 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002643 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002644 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002645 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002646 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002647 tlink = cifs_sb_tlink(cifs_sb);
2648 if (IS_ERR(tlink)) {
2649 rc = PTR_ERR(tlink);
2650 goto out;
2651 }
2652 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002653 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002654 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002655 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002656 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002657 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002658
Christoph Hellwig10257742010-06-04 11:30:02 +02002659 if (rc)
2660 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002661
Christoph Hellwig10257742010-06-04 11:30:02 +02002662 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002663 attrs->ia_size != i_size_read(inode))
2664 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002665
2666 setattr_copy(inode, attrs);
2667 mark_inode_dirty(inode);
2668
2669 /* force revalidate when any of these times are set since some
2670 of the fs types (eg ext3, fat) do not have fine enough
2671 time granularity to match protocol, and we do not have a
2672 a way (yet) to query the server fs's time granularity (and
2673 whether it rounds times down).
2674 */
2675 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2676 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002677out:
2678 kfree(args);
2679 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002680 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002681 return rc;
2682}
2683
Jeff Layton0510eeb2008-08-02 07:26:12 -04002684static int
2685cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002687 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002688 kuid_t uid = INVALID_UID;
2689 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002690 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002691 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002692 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002693 struct cifsFileInfo *wfile;
2694 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 char *full_path = NULL;
2696 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002697 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002698 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002699
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002700 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701
Colin Ian King63d614a2019-06-24 17:39:43 +01002702 cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
Al Viro35c265e2014-08-19 20:25:34 -04002703 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002704
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002705 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2706 attrs->ia_valid |= ATTR_FORCE;
2707
Jan Kara31051c82016-05-26 16:55:18 +02002708 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002709 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002710 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002711 return rc;
Steve French6473a552005-11-29 20:20:10 -08002712 }
Steve French50c2f752007-07-13 00:33:32 +00002713
Steve French7f573562005-08-30 11:32:14 -07002714 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302716 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002717 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302718 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720
Jeff Layton0f4d6342009-03-26 13:35:37 -04002721 /*
2722 * Attempt to flush data before changing attributes. We need to do
Steve Frenchcf5371a2020-02-24 17:37:39 -06002723 * this for ATTR_SIZE and ATTR_MTIME. If the flush of the data
2724 * returns error, store it to report later and continue.
Jeff Layton0f4d6342009-03-26 13:35:37 -04002725 *
2726 * BB: This should be smarter. Why bother flushing pages that
2727 * will be truncated anyway? Also, should we error out here if
Steve Frenchcf5371a2020-02-24 17:37:39 -06002728 * the flush returns error? Do we need to check for ATTR_MTIME_SET flag?
Jeff Layton0f4d6342009-03-26 13:35:37 -04002729 */
Steve Frenchcf5371a2020-02-24 17:37:39 -06002730 if (attrs->ia_valid & (ATTR_MTIME | ATTR_SIZE | ATTR_CTIME)) {
2731 rc = filemap_write_and_wait(inode->i_mapping);
2732 if (is_interrupt_error(rc)) {
2733 rc = -ERESTARTSYS;
2734 goto cifs_setattr_exit;
2735 }
2736 mapping_set_error(inode->i_mapping, rc);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002737 }
2738
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002739 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002740
Steve Frenchcf5371a2020-02-24 17:37:39 -06002741 if ((attrs->ia_valid & ATTR_MTIME) &&
2742 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002743 rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002744 if (!rc) {
2745 tcon = tlink_tcon(wfile->tlink);
2746 rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
2747 cifsFileInfo_put(wfile);
2748 if (rc)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002749 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002750 } else if (rc != -EBADF)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002751 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002752 else
2753 rc = 0;
2754 }
2755
Steve French50531442008-03-14 19:21:31 +00002756 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002757 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2758 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002759 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002761
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002762 if (attrs->ia_valid & ATTR_UID)
2763 uid = attrs->ia_uid;
2764
2765 if (attrs->ia_valid & ATTR_GID)
2766 gid = attrs->ia_gid;
2767
Steve French22442172019-07-19 08:15:55 +00002768 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2769 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002770 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002771 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2772 uid, gid);
2773 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002774 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2775 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002776 goto cifs_setattr_exit;
2777 }
2778 }
2779 } else
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002780 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002781 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782
Jeff Laytond32c4f22007-10-18 03:05:22 -07002783 /* skip mode change if it's just for clearing setuid/setgid */
2784 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2785 attrs->ia_valid &= ~ATTR_MODE;
2786
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 mode = attrs->ia_mode;
Steve Frenchcdbce9c82005-11-19 21:04:52 -08002789 rc = 0;
Steve French22442172019-07-19 08:15:55 +00002790 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2791 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002792 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002793 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002794 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002795 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2796 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002797 goto cifs_setattr_exit;
2798 }
2799 } else
Jeff Layton51328612008-05-22 09:33:34 -04002800 if (((mode & S_IWUGO) == 0) &&
2801 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002802
2803 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2804
Jeff Layton51328612008-05-22 09:33:34 -04002805 /* fix up mode if we're not using dynperm */
2806 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2807 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2808 } else if ((mode & S_IWUGO) &&
2809 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002810
2811 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2812 /* Attributes of 0 are ignored */
2813 if (dosattr == 0)
2814 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002815
2816 /* reset local inode permissions to normal */
2817 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2818 attrs->ia_mode &= ~(S_IALLUGO);
2819 if (S_ISDIR(inode->i_mode))
2820 attrs->ia_mode |=
2821 cifs_sb->mnt_dir_mode;
2822 else
2823 attrs->ia_mode |=
2824 cifs_sb->mnt_file_mode;
2825 }
2826 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2827 /* ignore mode change - ATTR_READONLY hasn't changed */
2828 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830 }
2831
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002832 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2833 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2834 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2835 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836
Steve Frenche30dcf32005-09-20 20:49:16 -07002837 /* Even if error on time set, no sense failing the call if
2838 the server would set the time to a reasonable value anyway,
2839 and this check ensures that we are not being called from
2840 sys_utimes in which case we ought to fail the call back to
2841 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002842 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002843 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002844 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 }
2846
2847 /* do not need local check to inode_check_ok since the server does
2848 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002849 if (rc)
2850 goto cifs_setattr_exit;
2851
2852 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002853 attrs->ia_size != i_size_read(inode))
2854 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002855
2856 setattr_copy(inode, attrs);
2857 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002858
Steve Frenche30dcf32005-09-20 20:49:16 -07002859cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002861 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 return rc;
2863}
2864
Jeff Layton0510eeb2008-08-02 07:26:12 -04002865int
2866cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2867{
Al Virofc640052016-04-10 01:33:30 -04002868 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002869 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002870
2871 if (pTcon->unix_ext)
2872 return cifs_setattr_unix(direntry, attrs);
2873
2874 return cifs_setattr_nounix(direntry, attrs);
2875
2876 /* BB: add cifs_setattr_legacy for really old servers */
2877}
2878
Steve French99ee4db2007-02-27 05:35:17 +00002879#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880void cifs_delete_inode(struct inode *inode)
2881{
Joe Perchesf96637b2013-05-04 22:12:25 -05002882 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883 /* may have to add back in if and when safe distributed caching of
2884 directories added e.g. via FindNotify */
2885}
Steve French99ee4db2007-02-27 05:35:17 +00002886#endif