blob: 3989d08396acb077512888e4954fea8964b3d7b5 [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;
Steve French6a5f6592020-06-11 19:25:47 -05001089 struct tcon_link *tlink;
1090 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1091 bool adjust_tz = false;
1092 struct cifs_fattr fattr = {0};
1093 bool symlink = false;
1094 struct smb311_posix_qinfo *data = NULL;
1095 int rc = 0;
1096 int tmprc = 0;
1097
1098 tlink = cifs_sb_tlink(cifs_sb);
1099 if (IS_ERR(tlink))
1100 return PTR_ERR(tlink);
1101 tcon = tlink_tcon(tlink);
Steve French6a5f6592020-06-11 19:25:47 -05001102
1103 /*
1104 * 1. Fetch file metadata
1105 */
1106
1107 if (is_inode_cache_good(*inode)) {
1108 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
1109 goto out;
1110 }
1111 data = kmalloc(sizeof(struct smb311_posix_qinfo), GFP_KERNEL);
1112 if (!data) {
1113 rc = -ENOMEM;
1114 goto out;
1115 }
1116
1117 rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
1118 full_path, data,
1119 &adjust_tz, &symlink);
1120
1121 /*
1122 * 2. Convert it to internal cifs metadata (fattr)
1123 */
1124
1125 switch (rc) {
1126 case 0:
1127 smb311_posix_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
1128 break;
1129 case -EREMOTE:
1130 /* DFS link, no metadata available on this server */
1131 cifs_create_dfs_fattr(&fattr, sb);
1132 rc = 0;
1133 break;
1134 case -EACCES:
1135 /*
1136 * For SMB2 and later the backup intent flag
1137 * is already sent if needed on open and there
1138 * is no path based FindFirst operation to use
1139 * to retry with so nothing we can do, bail out
1140 */
1141 goto out;
1142 default:
1143 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
1144 goto out;
1145 }
1146
1147
1148 /*
Steve Frencha7a519a2020-06-12 14:49:47 -05001149 * 3. Tweak fattr based on mount options
Steve French6a5f6592020-06-11 19:25:47 -05001150 */
1151
1152 /* check for Minshall+French symlinks */
1153 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
1154 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
1155 full_path);
1156 if (tmprc)
1157 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1158 }
1159
1160 /*
Steve Frencha7a519a2020-06-12 14:49:47 -05001161 * 4. Update inode with final fattr data
Steve French6a5f6592020-06-11 19:25:47 -05001162 */
1163
1164 if (!*inode) {
1165 *inode = cifs_iget(sb, &fattr);
1166 if (!*inode)
1167 rc = -ENOMEM;
1168 } else {
1169 /* we already have inode, update it */
1170
1171 /* if uniqueid is different, return error */
1172 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1173 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
1174 CIFS_I(*inode)->time = 0; /* force reval */
1175 rc = -ESTALE;
1176 goto out;
1177 }
1178
1179 /* if filetype is different, return error */
1180 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1181 (fattr.cf_mode & S_IFMT))) {
1182 CIFS_I(*inode)->time = 0; /* force reval */
1183 rc = -ESTALE;
1184 goto out;
1185 }
1186
1187 cifs_fattr_to_inode(*inode, &fattr);
1188 }
1189out:
1190 cifs_put_tlink(tlink);
1191 kfree(data);
1192 return rc;
1193}
1194
1195
Steve French7f8ed422007-09-28 22:28:55 +00001196static const struct inode_operations cifs_ipc_inode_ops = {
1197 .lookup = cifs_lookup,
1198};
1199
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001200static int
1201cifs_find_inode(struct inode *inode, void *opaque)
1202{
1203 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1204
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001205 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001206 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
1207 return 0;
1208
Jeff Layton20054bd2011-01-07 11:30:27 -05001209 /* use createtime like an i_generation field */
1210 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
1211 return 0;
1212
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001213 /* don't match inode of different type */
1214 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
1215 return 0;
1216
Jeff Layton5acfec22010-08-02 17:43:54 -04001217 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -04001218 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -04001219 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -04001220
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001221 return 1;
1222}
1223
1224static int
1225cifs_init_inode(struct inode *inode, void *opaque)
1226{
1227 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1228
1229 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -05001230 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001231 return 0;
1232}
1233
Jeff Layton5acfec22010-08-02 17:43:54 -04001234/*
1235 * walk dentry list for an inode and report whether it has aliases that
1236 * are hashed. We use this to determine if a directory inode can actually
1237 * be used.
1238 */
1239static bool
1240inode_has_hashed_dentries(struct inode *inode)
1241{
1242 struct dentry *dentry;
1243
Nick Piggin873feea2011-01-07 17:50:06 +11001244 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -04001245 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001246 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +11001247 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001248 return true;
1249 }
1250 }
Nick Piggin873feea2011-01-07 17:50:06 +11001251 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001252 return false;
1253}
1254
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001255/* Given fattrs, get a corresponding inode */
1256struct inode *
1257cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
1258{
1259 unsigned long hash;
1260 struct inode *inode;
1261
Jeff Layton3d694382010-05-11 14:59:55 -04001262retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -05001263 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001264
1265 /* hash down to 32-bits on 32-bit arch */
1266 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
1267
1268 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001269 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001270 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -04001271 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -04001272 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -04001273
1274 if (inode_has_hashed_dentries(inode)) {
1275 cifs_autodisable_serverino(CIFS_SB(sb));
1276 iput(inode);
1277 fattr->cf_uniqueid = iunique(sb, ROOT_I);
1278 goto retry_iget5_locked;
1279 }
Jeff Layton3d694382010-05-11 14:59:55 -04001280 }
1281
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001282 cifs_fattr_to_inode(inode, fattr);
Linus Torvalds1751e8a2017-11-27 13:05:09 -08001283 if (sb->s_flags & SB_NOATIME)
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001284 inode->i_flags |= S_NOATIME | S_NOCMTIME;
1285 if (inode->i_state & I_NEW) {
1286 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +00001287#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301288 /* initialize per-inode cache cookie pointer */
1289 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +00001290#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001291 unlock_new_inode(inode);
1292 }
1293 }
1294
1295 return inode;
1296}
1297
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001299struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001301 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001302 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001303 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001304 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001305 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001306 char *path = NULL;
1307 int len;
1308
1309 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1310 && cifs_sb->prepath) {
1311 len = strlen(cifs_sb->prepath);
1312 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1313 if (path == NULL)
1314 return ERR_PTR(-ENOMEM);
1315 path[0] = '/';
1316 memcpy(path+1, cifs_sb->prepath, len);
1317 } else {
1318 path = kstrdup("", GFP_KERNEL);
1319 if (path == NULL)
1320 return ERR_PTR(-ENOMEM);
1321 }
David Howellsce634ab2008-02-07 00:15:33 -08001322
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001323 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001324 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001325 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001326 /* some servers mistakenly claim POSIX support */
1327 if (rc != -EOPNOTSUPP)
1328 goto iget_no_retry;
Joe Perchesa0a30362020-04-14 22:42:53 -07001329 cifs_dbg(VFS, "server does not support POSIX extensions\n");
Steve Frenchb5b374e2014-10-06 01:01:03 -05001330 tcon->unix_ext = false;
1331 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001332
Aurelien Aptela6b50582016-05-25 19:59:09 +02001333 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
Steve Frenchd3138522020-06-11 22:43:01 -05001334 if (tcon->posix_extensions)
1335 rc = smb311_posix_get_inode_info(&inode, path, sb, xid);
1336 else
1337 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001338
1339iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001340 if (!inode) {
1341 inode = ERR_PTR(rc);
1342 goto out;
1343 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001344
Steve French0ccd4802010-07-16 04:31:02 +00001345#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301346 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001347 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001348#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301349
Aurelien Aptelb327a712018-01-24 13:46:10 +01001350 if (rc && tcon->pipe) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001351 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001352 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001353 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001354 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001355 inode->i_op = &cifs_ipc_inode_ops;
1356 inode->i_fop = &simple_dir_operations;
1357 inode->i_uid = cifs_sb->mnt_uid;
1358 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001359 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001360 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001361 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001362 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001363 }
1364
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001365out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001366 kfree(path);
Phillip Potter31cd1062018-03-17 21:06:56 +00001367 free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001368 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369}
1370
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001371int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001372cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001373 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001374{
Steve French388e57b2008-09-16 23:50:58 +00001375 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001376 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001377 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001378 FILE_BASIC_INFO info_buf;
1379
Steve French1adcb712009-02-25 14:19:56 +00001380 if (attrs == NULL)
1381 return -EINVAL;
1382
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001383 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1384 if (!server->ops->set_file_info)
1385 return -ENOSYS;
1386
Steve Frenchfd09b7d2018-08-02 20:28:18 -05001387 info_buf.Pad = 0;
1388
Steve French388e57b2008-09-16 23:50:58 +00001389 if (attrs->ia_valid & ATTR_ATIME) {
1390 set_time = true;
1391 info_buf.LastAccessTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001392 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
Steve French388e57b2008-09-16 23:50:58 +00001393 } else
1394 info_buf.LastAccessTime = 0;
1395
1396 if (attrs->ia_valid & ATTR_MTIME) {
1397 set_time = true;
1398 info_buf.LastWriteTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001399 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
Steve French388e57b2008-09-16 23:50:58 +00001400 } else
1401 info_buf.LastWriteTime = 0;
1402
1403 /*
1404 * Samba throws this field away, but windows may actually use it.
1405 * Do not set ctime unless other time stamps are changed explicitly
1406 * (i.e. by utimes()) since we would then have a mix of client and
1407 * server times.
1408 */
1409 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001410 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001411 info_buf.ChangeTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001412 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
Steve French388e57b2008-09-16 23:50:58 +00001413 } else
1414 info_buf.ChangeTime = 0;
1415
1416 info_buf.CreationTime = 0; /* don't change */
1417 info_buf.Attributes = cpu_to_le32(dosattr);
1418
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001419 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001420}
1421
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001422/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001423 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001424 * and rename it to a random name that hopefully won't conflict with
1425 * anything else.
1426 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001427int
1428cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1429 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001430{
1431 int oplock = 0;
1432 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001433 struct cifs_fid fid;
1434 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001435 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001436 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1437 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001438 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001439 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001440 __u32 dosattr, origattr;
1441 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001442
Jeff Layton7ffec372010-09-29 19:51:11 -04001443 tlink = cifs_sb_tlink(cifs_sb);
1444 if (IS_ERR(tlink))
1445 return PTR_ERR(tlink);
1446 tcon = tlink_tcon(tlink);
1447
Sachin Prabhuc483a982013-03-05 19:25:56 +00001448 /*
1449 * We cannot rename the file if the server doesn't support
1450 * CAP_INFOLEVEL_PASSTHRU
1451 */
1452 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1453 rc = -EBUSY;
1454 goto out;
1455 }
1456
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001457 oparms.tcon = tcon;
1458 oparms.cifs_sb = cifs_sb;
1459 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
Amir Goldstein0f060932020-02-03 21:46:43 +02001460 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001461 oparms.disposition = FILE_OPEN;
1462 oparms.path = full_path;
1463 oparms.fid = &fid;
1464 oparms.reconnect = false;
1465
1466 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001467 if (rc != 0)
1468 goto out;
1469
Steve French32709582008-10-20 00:44:19 +00001470 origattr = cifsInode->cifsAttrs;
1471 if (origattr == 0)
1472 origattr |= ATTR_NORMAL;
1473
1474 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001475 if (dosattr == 0)
1476 dosattr |= ATTR_NORMAL;
1477 dosattr |= ATTR_HIDDEN;
1478
Steve French32709582008-10-20 00:44:19 +00001479 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1480 if (dosattr != origattr) {
1481 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1482 if (info_buf == NULL) {
1483 rc = -ENOMEM;
1484 goto out_close;
1485 }
1486 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001487 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001488 current->tgid);
1489 /* although we would like to mark the file hidden
1490 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001491 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001492 cifsInode->cifsAttrs = dosattr;
1493 else
1494 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001495 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001496
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001497 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001498 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1499 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001500 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001501 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001502 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001503 goto undo_setattr;
1504 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001505
Steve French32709582008-10-20 00:44:19 +00001506 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001507 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001508 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001509 current->tgid);
1510 /*
1511 * some samba versions return -ENOENT when we try to set the
1512 * file disposition here. Likely a samba bug, but work around
1513 * it for now. This means that some cifsXXX files may hang
1514 * around after they shouldn't.
1515 *
1516 * BB: remove this hack after more servers have the fix
1517 */
1518 if (rc == -ENOENT)
1519 rc = 0;
1520 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001521 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001522 goto undo_rename;
1523 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001524 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001525 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001526
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001527out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001528 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001529out:
Steve French32709582008-10-20 00:44:19 +00001530 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001531 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001532 return rc;
Steve French32709582008-10-20 00:44:19 +00001533
1534 /*
1535 * reset everything back to the original state. Don't bother
1536 * dealing with errors here since we can't do anything about
1537 * them anyway.
1538 */
1539undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001540 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001541 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001542undo_setattr:
1543 if (dosattr != origattr) {
1544 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001545 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001546 current->tgid))
1547 cifsInode->cifsAttrs = origattr;
1548 }
1549
1550 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001551}
1552
Steve Frenchb7ca6922012-08-03 08:43:01 -05001553/* copied from fs/nfs/dir.c with small changes */
1554static void
1555cifs_drop_nlink(struct inode *inode)
1556{
1557 spin_lock(&inode->i_lock);
1558 if (inode->i_nlink > 0)
1559 drop_nlink(inode);
1560 spin_unlock(&inode->i_lock);
1561}
Steve Frenchff694522009-04-20 19:45:13 +00001562
1563/*
David Howells2b0143b2015-03-17 22:25:59 +00001564 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001565 * is a negative dentry) then we would attempt a standard SMB delete, but
Colin Ian King413d6102018-10-26 19:07:21 +01001566 * if that fails we can not attempt the fall back mechanisms on EACCES
1567 * but will return the EACCES to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001568 * unlink on negative dentries currently.
1569 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001570int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571{
1572 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001573 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001575 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001576 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001577 struct super_block *sb = dir->i_sb;
1578 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001579 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001580 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001581 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001582 struct iattr *attrs = NULL;
1583 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
Joe Perchesf96637b2013-05-04 22:12:25 -05001585 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
Jeff Layton7ffec372010-09-29 19:51:11 -04001587 tlink = cifs_sb_tlink(cifs_sb);
1588 if (IS_ERR(tlink))
1589 return PTR_ERR(tlink);
1590 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001591 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001592
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001593 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
Steve French82e93672020-05-19 03:06:57 -05001595 if (tcon->nodelete) {
1596 rc = -EACCES;
1597 goto unlink_out;
1598 }
1599
Jeff Layton5f0319a2008-09-16 14:05:16 -04001600 /* Unlink can be called from rename so we can not take the
1601 * sb->s_vfs_rename_mutex here */
1602 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301604 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001605 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 }
Steve French2d785a52007-07-15 01:48:57 +00001607
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001608 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1609 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001610 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001611 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001612 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001613 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001614 if ((rc == 0) || (rc == -ENOENT))
1615 goto psx_del_no_retry;
1616 }
1617
Steve French60502472008-10-07 18:42:52 +00001618retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001619 if (!server->ops->unlink) {
1620 rc = -ENOSYS;
1621 goto psx_del_no_retry;
1622 }
1623
1624 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001625
Steve French2d785a52007-07-15 01:48:57 +00001626psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001628 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001629 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001631 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001632 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001633 if (server->ops->rename_pending_delete) {
1634 rc = server->ops->rename_pending_delete(full_path,
1635 dentry, xid);
1636 if (rc == 0)
1637 cifs_drop_nlink(inode);
1638 }
Steve Frenchff694522009-04-20 19:45:13 +00001639 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001640 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1641 if (attrs == NULL) {
1642 rc = -ENOMEM;
1643 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 }
Steve French388e57b2008-09-16 23:50:58 +00001645
1646 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001647 cifs_inode = CIFS_I(inode);
1648 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001649 if (origattr == 0)
1650 origattr |= ATTR_NORMAL;
1651 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001652 if (dosattr == 0)
1653 dosattr |= ATTR_NORMAL;
1654 dosattr |= ATTR_HIDDEN;
1655
1656 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001657 if (rc != 0)
1658 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001659
1660 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 }
Steve French60502472008-10-07 18:42:52 +00001662
1663 /* undo the setattr if we errored out and it's needed */
1664 if (rc != 0 && dosattr != 0)
1665 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1666
Steve French388e57b2008-09-16 23:50:58 +00001667out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001668 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001669 cifs_inode = CIFS_I(inode);
1670 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001671 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001672 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001673 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001674 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001675 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001676 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001677unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001679 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001680 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001681 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 return rc;
1683}
1684
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001685static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001686cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001687 const char *full_path, struct cifs_sb_info *cifs_sb,
1688 struct cifs_tcon *tcon, const unsigned int xid)
1689{
1690 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001691 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001692
Steve Frenchd3138522020-06-11 22:43:01 -05001693 if (tcon->posix_extensions)
1694 rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
1695 else if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001696 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001697 xid);
1698 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001699 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1700 xid, NULL);
1701
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001702 if (rc)
1703 return rc;
1704
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001705 /*
1706 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001707 * from the server or was set bogus. Also, since this is a brand new
1708 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001709 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001710 if (inode->i_nlink < 2)
1711 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001712 mode &= ~current_umask();
1713 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001714 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001715 mode |= S_ISGID;
1716
1717 if (tcon->unix_ext) {
1718 struct cifs_unix_set_info_args args = {
1719 .mode = mode,
1720 .ctime = NO_CHANGE_64,
1721 .atime = NO_CHANGE_64,
1722 .mtime = NO_CHANGE_64,
1723 .device = 0,
1724 };
1725 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001726 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001727 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001728 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001729 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001730 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001731 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001732 args.uid = INVALID_UID; /* no change */
1733 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001734 }
1735 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1736 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001737 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001738 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001739 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001740 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001741 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001742 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001743 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001744 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1745 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001746
Jeff Layton101b92d2012-09-19 06:22:45 -07001747 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1748 inode->i_uid = current_fsuid();
1749 if (inode->i_mode & S_ISGID)
1750 inode->i_gid = parent->i_gid;
1751 else
1752 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001753 }
1754 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001755 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001756 return rc;
1757}
1758
1759static int
1760cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1761 const char *full_path, struct cifs_sb_info *cifs_sb,
1762 struct cifs_tcon *tcon, const unsigned int xid)
1763{
1764 int rc = 0;
1765 u32 oplock = 0;
1766 FILE_UNIX_BASIC_INFO *info = NULL;
1767 struct inode *newinode = NULL;
1768 struct cifs_fattr fattr;
1769
1770 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1771 if (info == NULL) {
1772 rc = -ENOMEM;
1773 goto posix_mkdir_out;
1774 }
1775
1776 mode &= ~current_umask();
1777 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1778 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001779 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001780 if (rc == -EOPNOTSUPP)
1781 goto posix_mkdir_out;
1782 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001783 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001784 d_drop(dentry);
1785 goto posix_mkdir_out;
1786 }
1787
1788 if (info->Type == cpu_to_le32(-1))
1789 /* no return info, go query for it */
1790 goto posix_mkdir_get_info;
1791 /*
1792 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1793 * need to set uid/gid.
1794 */
1795
1796 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1797 cifs_fill_uniqueid(inode->i_sb, &fattr);
1798 newinode = cifs_iget(inode->i_sb, &fattr);
1799 if (!newinode)
1800 goto posix_mkdir_get_info;
1801
1802 d_instantiate(dentry, newinode);
1803
1804#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001805 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1806 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001807
1808 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001809 cifs_dbg(FYI, "unexpected number of links %d\n",
1810 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001811#endif
1812
1813posix_mkdir_out:
1814 kfree(info);
1815 return rc;
1816posix_mkdir_get_info:
1817 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1818 xid);
1819 goto posix_mkdir_out;
1820}
1821
Al Viro18bb1db2011-07-26 01:41:39 -04001822int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001824 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001825 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001827 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001828 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001829 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001830 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831
Frank Sorensonf52aa792020-02-12 15:31:48 -06001832 cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05001833 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001836 tlink = cifs_sb_tlink(cifs_sb);
1837 if (IS_ERR(tlink))
1838 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001839 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001840
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001841 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842
Steve French7f573562005-08-30 11:32:14 -07001843 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301845 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001846 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 }
Steve French50c2f752007-07-13 00:33:32 +00001848
Steve Frenchbea851b2018-06-14 21:56:32 -05001849 server = tcon->ses->server;
1850
Steve Frenchbea851b2018-06-14 21:56:32 -05001851 if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
1852 rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
1853 cifs_sb);
1854 d_drop(direntry); /* for time being always refresh inode info */
1855 goto mkdir_out;
1856 }
Steve Frenchbea851b2018-06-14 21:56:32 -05001857
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001858 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1859 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001860 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1861 tcon, xid);
1862 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001863 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001864 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001865
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001866 if (!server->ops->mkdir) {
1867 rc = -ENOSYS;
1868 goto mkdir_out;
1869 }
1870
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001872 rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001874 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001876 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001878
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001879 /* TODO: skip this for smb2/smb3 */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001880 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1881 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001882mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001883 /*
1884 * Force revalidate to get parent dir info when needed since cached
1885 * attributes are invalid now.
1886 */
1887 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001889 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001890 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 return rc;
1892}
1893
1894int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1895{
1896 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001897 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001899 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001900 struct cifs_tcon *tcon;
1901 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 char *full_path = NULL;
1903 struct cifsInodeInfo *cifsInode;
1904
Joe Perchesf96637b2013-05-04 22:12:25 -05001905 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001907 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Steve French7f573562005-08-30 11:32:14 -07001909 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301911 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001912 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 }
1914
Jeff Layton7ffec372010-09-29 19:51:11 -04001915 cifs_sb = CIFS_SB(inode->i_sb);
1916 tlink = cifs_sb_tlink(cifs_sb);
1917 if (IS_ERR(tlink)) {
1918 rc = PTR_ERR(tlink);
1919 goto rmdir_exit;
1920 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001921 tcon = tlink_tcon(tlink);
1922 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001923
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001924 if (!server->ops->rmdir) {
1925 rc = -ENOSYS;
1926 cifs_put_tlink(tlink);
1927 goto rmdir_exit;
1928 }
1929
Steve French82e93672020-05-19 03:06:57 -05001930 if (tcon->nodelete) {
1931 rc = -EACCES;
1932 cifs_put_tlink(tlink);
1933 goto rmdir_exit;
1934 }
1935
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001936 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001937 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
1939 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001940 spin_lock(&d_inode(direntry)->i_lock);
1941 i_size_write(d_inode(direntry), 0);
1942 clear_nlink(d_inode(direntry));
1943 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 }
1945
David Howells2b0143b2015-03-17 22:25:59 +00001946 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001947 /* force revalidate to go get info when needed */
1948 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001949
1950 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001951 /*
1952 * Force revalidate to get parent dir info when needed since cached
1953 * attributes are invalid now.
1954 */
1955 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001956
David Howells2b0143b2015-03-17 22:25:59 +00001957 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001958 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959
Jeff Layton7ffec372010-09-29 19:51:11 -04001960rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001962 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 return rc;
1964}
1965
Steve Frenchee2fd962008-09-23 18:23:33 +00001966static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001967cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1968 const char *from_path, struct dentry *to_dentry,
1969 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001970{
1971 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001972 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001973 struct cifs_tcon *tcon;
1974 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001975 struct cifs_fid fid;
1976 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001977 int oplock, rc;
1978
Jeff Layton7ffec372010-09-29 19:51:11 -04001979 tlink = cifs_sb_tlink(cifs_sb);
1980 if (IS_ERR(tlink))
1981 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001982 tcon = tlink_tcon(tlink);
1983 server = tcon->ses->server;
1984
1985 if (!server->ops->rename)
1986 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001987
Steve Frenchee2fd962008-09-23 18:23:33 +00001988 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001989 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001990
1991 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001992 * Don't bother with rename by filehandle unless file is busy and
1993 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001994 * rename by filehandle to various Windows servers.
1995 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001996 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001997 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001998
Frank Sorenson652727b2019-04-16 08:37:27 -05001999 /* Don't fall back to using SMB on SMB 2+ mount */
2000 if (server->vals->protocol_id != 0)
2001 goto do_rename_exit;
2002
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04002003 /* open-file renames don't work across directories */
2004 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04002005 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04002006
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002007 oparms.tcon = tcon;
2008 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00002009 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002010 oparms.desired_access = DELETE;
Amir Goldstein0f060932020-02-03 21:46:43 +02002011 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002012 oparms.disposition = FILE_OPEN;
2013 oparms.path = from_path;
2014 oparms.fid = &fid;
2015 oparms.reconnect = false;
2016
2017 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00002018 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002019 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00002020 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05002021 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002022 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00002023 }
Jeff Layton7ffec372010-09-29 19:51:11 -04002024do_rename_exit:
Steve Frenchc7e9f782020-02-25 18:08:54 -06002025 if (rc == 0)
2026 d_move(from_dentry, to_dentry);
Jeff Layton7ffec372010-09-29 19:51:11 -04002027 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00002028 return rc;
2029}
2030
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002031int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002032cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
2033 struct inode *target_dir, struct dentry *target_dentry,
2034 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002036 char *from_name = NULL;
2037 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04002038 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04002039 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002040 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00002041 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
2042 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002043 unsigned int xid;
2044 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002046 if (flags & ~RENAME_NOREPLACE)
2047 return -EINVAL;
2048
Jeff Layton639e7a92010-09-03 11:50:09 -04002049 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002050 tlink = cifs_sb_tlink(cifs_sb);
2051 if (IS_ERR(tlink))
2052 return PTR_ERR(tlink);
2053 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002055 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00002056
2057 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00002058 * we already have the rename sem so we do not need to
2059 * grab it again here to protect the path integrity
2060 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002061 from_name = build_path_from_dentry(source_dentry);
2062 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 rc = -ENOMEM;
2064 goto cifs_rename_exit;
2065 }
2066
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002067 to_name = build_path_from_dentry(target_dentry);
2068 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00002069 rc = -ENOMEM;
2070 goto cifs_rename_exit;
2071 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002073 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
2074 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00002075
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002076 /*
2077 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
2078 */
2079 if (flags & RENAME_NOREPLACE)
2080 goto cifs_rename_exit;
2081
Jeff Layton14121bd2008-10-20 14:45:22 -04002082 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00002083 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002084 * Are src and dst hardlinks of same inode? We can only tell
2085 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00002086 */
Jeff Layton14121bd2008-10-20 14:45:22 -04002087 info_buf_source =
Kees Cook6da2ec52018-06-12 13:55:00 -07002088 kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
Jeff Layton14121bd2008-10-20 14:45:22 -04002089 GFP_KERNEL);
2090 if (info_buf_source == NULL) {
2091 rc = -ENOMEM;
2092 goto cifs_rename_exit;
2093 }
2094
2095 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002096 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
2097 info_buf_source,
2098 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002099 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04002100 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04002101 goto unlink_target;
2102
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002103 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
2104 info_buf_target,
2105 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002106 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04002107
Jeff Layton8d281ef2008-10-22 13:57:01 -04002108 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05002109 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04002110 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05002111 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04002112 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05002113 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002114 }
2115 /*
2116 * else ... BB we could add the same check for Windows by
2117 * checking the UniqueId via FILE_INTERNAL_INFO
2118 */
Jeff Layton14121bd2008-10-20 14:45:22 -04002119
Jeff Layton14121bd2008-10-20 14:45:22 -04002120unlink_target:
Steve French0e670512020-07-23 14:41:29 -05002121 /* Try unlinking the target dentry if it's not negative */
2122 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04002123 if (d_is_dir(target_dentry))
2124 tmprc = cifs_rmdir(target_dir, target_dentry);
2125 else
2126 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04002127 if (tmprc)
2128 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002129 rc = cifs_do_rename(xid, source_dentry, from_name,
2130 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 }
2132
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04002133 /* force revalidate to go get info when needed */
2134 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
2135
2136 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07002137 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04002138
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00002140 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002141 kfree(from_name);
2142 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002143 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04002144 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 return rc;
2146}
2147
Jeff Laytondf2cf172010-02-12 07:44:16 -05002148static bool
2149cifs_inode_needs_reval(struct inode *inode)
2150{
2151 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302152 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002153
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002154 if (cifs_i->time == 0)
2155 return true;
2156
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002157 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05002158 return false;
2159
2160 if (!lookupCacheEnabled)
2161 return true;
2162
Jeff Laytona87c9ad2014-03-26 07:24:23 -07002163 if (!cifs_sb->actimeo)
2164 return true;
2165
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302166 if (!time_in_range(jiffies, cifs_i->time,
2167 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05002168 return true;
2169
Jeff Laytondb192722010-05-17 14:51:49 -04002170 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302171 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04002172 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
2173 return true;
2174
Jeff Laytondf2cf172010-02-12 07:44:16 -05002175 return false;
2176}
2177
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05302178/*
2179 * Zap the cache. Called when invalid_mapping flag is set.
2180 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002181int
Jeff Laytondf2cf172010-02-12 07:44:16 -05002182cifs_invalidate_mapping(struct inode *inode)
2183{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002184 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002185
Jeff Laytondf2cf172010-02-12 07:44:16 -05002186 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002187 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002188 if (rc)
Joe Perchesa0a30362020-04-14 22:42:53 -07002189 cifs_dbg(VFS, "%s: Could not invalidate inode %p\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05002190 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002191 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002192
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05302193 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002194 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002195}
2196
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002197/**
2198 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
2199 * @word: long word containing the bit lock
2200 */
2201static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002202cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002203{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002204 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002205 if (signal_pending_state(mode, current))
2206 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002207 return 0;
2208}
2209
Jeff Laytone284e532014-04-30 09:31:46 -04002210int
2211cifs_revalidate_mapping(struct inode *inode)
2212{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002213 int rc;
2214 unsigned long *flags = &CIFS_I(inode)->flags;
2215
Steve French4e8aea32020-04-09 21:42:18 -05002216 /* swapfiles are not supposed to be shared */
2217 if (IS_SWAPFILE(inode))
2218 return 0;
2219
NeilBrown74316202014-07-07 15:16:04 +10002220 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
2221 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002222 if (rc)
2223 return rc;
2224
2225 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
2226 rc = cifs_invalidate_mapping(inode);
2227 if (rc)
2228 set_bit(CIFS_INO_INVALID_MAPPING, flags);
2229 }
2230
2231 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07002232 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002233 wake_up_bit(flags, CIFS_INO_LOCK);
2234
2235 return rc;
2236}
2237
2238int
2239cifs_zap_mapping(struct inode *inode)
2240{
2241 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
2242 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04002243}
2244
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002245int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05002246{
2247 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05002248 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba642010-09-20 16:01:31 -07002249 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05002250
2251 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002252 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05002253
Jeff Layton13cfb732010-09-29 19:51:11 -04002254 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05002255 rc = cifs_get_file_info_unix(filp);
2256 else
2257 rc = cifs_get_file_info(filp);
2258
Jeff Laytonabab0952010-02-12 07:44:18 -05002259 return rc;
2260}
2261
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002262int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002264 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002265 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00002266 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002267 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002268 char *full_path = NULL;
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002269 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Jeff Laytondf2cf172010-02-12 07:44:16 -05002271 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 return -ENOENT;
2273
Jeff Laytondf2cf172010-02-12 07:44:16 -05002274 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002275 return rc;
2276
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002277 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
2279 /* can not safely grab the rename sem here if rename calls revalidate
2280 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05002281 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302283 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002284 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05002286
Joe Perchesf96637b2013-05-04 22:12:25 -05002287 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
2288 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02002289 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002291again:
Steve French6a5f6592020-06-11 19:25:47 -05002292 if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
2293 rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
2294 else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05002295 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
2296 else
2297 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
2298 xid, NULL);
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002299 if (rc == -EAGAIN && count++ < 10)
2300 goto again;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002301out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002303 free_xid(xid);
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002304
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 return rc;
2306}
2307
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002308int cifs_revalidate_file(struct file *filp)
2309{
2310 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002311 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002312
2313 rc = cifs_revalidate_file_attr(filp);
2314 if (rc)
2315 return rc;
2316
Jeff Laytone284e532014-04-30 09:31:46 -04002317 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002318}
2319
2320/* revalidate a dentry's inode attributes */
2321int cifs_revalidate_dentry(struct dentry *dentry)
2322{
2323 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002324 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002325
2326 rc = cifs_revalidate_dentry_attr(dentry);
2327 if (rc)
2328 return rc;
2329
Jeff Laytone284e532014-04-30 09:31:46 -04002330 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002331}
2332
David Howellsa528d352017-01-31 16:46:22 +00002333int cifs_getattr(const struct path *path, struct kstat *stat,
2334 u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335{
David Howellsa528d352017-01-31 16:46:22 +00002336 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002337 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002338 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002339 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002340 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002341
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002342 /*
2343 * We need to be sure that all dirty pages are written and the server
2344 * has actual ctime, mtime and file length.
2345 */
Steve Frenchffdec8d2020-02-18 18:07:57 -06002346 if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE)) &&
2347 !CIFS_CACHE_READ(CIFS_I(inode)) &&
2348 inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002349 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002350 if (rc) {
2351 mapping_set_error(inode->i_mapping, rc);
2352 return rc;
2353 }
Steve French5fe14c82006-11-07 19:26:33 +00002354 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002355
Steve Frenchffdec8d2020-02-18 18:07:57 -06002356 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC)
2357 CIFS_I(inode)->time = 0; /* force revalidate */
2358
2359 /*
2360 * If the caller doesn't require syncing, only sync if
2361 * necessary (e.g. due to earlier truncate or setattr
2362 * invalidating the cached metadata)
2363 */
2364 if (((flags & AT_STATX_SYNC_TYPE) != AT_STATX_DONT_SYNC) ||
2365 (CIFS_I(inode)->time == 0)) {
2366 rc = cifs_revalidate_dentry_attr(dentry);
2367 if (rc)
2368 return rc;
2369 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002370
2371 generic_fillattr(inode, stat);
Steve Frenche8506d22019-02-28 21:32:15 -06002372 stat->blksize = cifs_sb->bsize;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002373 stat->ino = CIFS_I(inode)->uniqueid;
2374
Steve French6e70e262017-09-21 21:32:29 -05002375 /* old CIFS Unix Extensions doesn't return create time */
2376 if (CIFS_I(inode)->createtime) {
2377 stat->result_mask |= STATX_BTIME;
Arnd Bergmann95390202018-06-19 17:27:58 +02002378 stat->btime =
2379 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
Steve French6e70e262017-09-21 21:32:29 -05002380 }
2381
2382 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2383 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2384 stat->attributes |= STATX_ATTR_COMPRESSED;
2385 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2386 stat->attributes |= STATX_ATTR_ENCRYPTED;
2387
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002388 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002389 * If on a multiuser mount without unix extensions or cifsacl being
2390 * enabled, and the admin hasn't overridden them, set the ownership
2391 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002392 */
2393 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002394 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002395 !tcon->unix_ext) {
2396 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2397 stat->uid = current_fsuid();
2398 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2399 stat->gid = current_fsgid();
2400 }
Dan Carpenter39946882020-02-28 12:22:59 +03002401 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402}
2403
Ronnie Sahlberg2f3ebab2019-04-25 16:45:29 +10002404int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
2405 u64 len)
2406{
2407 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2408 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->vfs_inode.i_sb);
2409 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2410 struct TCP_Server_Info *server = tcon->ses->server;
2411 struct cifsFileInfo *cfile;
2412 int rc;
2413
2414 /*
2415 * We need to be sure that all dirty pages are written as they
2416 * might fill holes on the server.
2417 */
2418 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
2419 inode->i_mapping->nrpages != 0) {
2420 rc = filemap_fdatawait(inode->i_mapping);
2421 if (rc) {
2422 mapping_set_error(inode->i_mapping, rc);
2423 return rc;
2424 }
2425 }
2426
2427 cfile = find_readable_file(cifs_i, false);
2428 if (cfile == NULL)
2429 return -EINVAL;
2430
2431 if (server->ops->fiemap) {
2432 rc = server->ops->fiemap(tcon, cfile, fei, start, len);
2433 cifsFileInfo_put(cfile);
2434 return rc;
2435 }
2436
2437 cifsFileInfo_put(cfile);
2438 return -ENOTSUPP;
2439}
2440
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002441int cifs_truncate_page(struct address_space *mapping, loff_t from)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002443 pgoff_t index = from >> PAGE_SHIFT;
2444 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 int rc = 0;
2447
2448 page = grab_cache_page(mapping, index);
2449 if (!page)
2450 return -ENOMEM;
2451
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002452 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002454 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 return rc;
2456}
2457
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002458void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002459{
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002460 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2461
Steve Frenchba6a46a2007-02-26 20:06:29 +00002462 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002463 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002464 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002465
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002466 /* Cached inode must be refreshed on truncate */
2467 cifs_i->time = 0;
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002468 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002469}
2470
Jeff Layton8efdbde2008-07-23 21:28:12 +00002471static int
2472cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002473 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002474{
2475 int rc;
2476 struct cifsFileInfo *open_file;
2477 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2478 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002479 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002480 struct cifs_tcon *tcon = NULL;
2481 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002482
2483 /*
2484 * To avoid spurious oplock breaks from server, in the case of
2485 * inodes that we already have open, avoid doing path based
2486 * setting of file size if we can do it by handle.
2487 * This keeps our caching token (oplock) and avoids timeouts
2488 * when the local oplock break takes longer to flush
2489 * writebehind data than the SMB timeout for the SetPathInfo
2490 * request would allow
2491 */
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002492 open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002493 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002494 tcon = tlink_tcon(open_file->tlink);
2495 server = tcon->ses->server;
2496 if (server->ops->set_file_size)
2497 rc = server->ops->set_file_size(xid, tcon, open_file,
2498 attrs->ia_size, false);
2499 else
2500 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002501 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002502 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002503 } else
2504 rc = -EINVAL;
2505
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002506 if (!rc)
2507 goto set_size_out;
Jeff Laytonba00ba642010-09-20 16:01:31 -07002508
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002509 if (tcon == NULL) {
2510 tlink = cifs_sb_tlink(cifs_sb);
2511 if (IS_ERR(tlink))
2512 return PTR_ERR(tlink);
2513 tcon = tlink_tcon(tlink);
2514 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002515 }
2516
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002517 /*
2518 * Set file size by pathname rather than by handle either because no
2519 * valid, writeable file handle for it was found or because there was
2520 * an error setting it by handle.
2521 */
2522 if (server->ops->set_path_size)
2523 rc = server->ops->set_path_size(xid, tcon, full_path,
2524 attrs->ia_size, cifs_sb, false);
2525 else
2526 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002527 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002528
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002529 if (tlink)
2530 cifs_put_tlink(tlink);
2531
2532set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002533 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002534 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002535 cifs_setsize(inode, attrs->ia_size);
Zhang Xiaoxu56183032020-06-19 22:51:29 -04002536
2537 /*
2538 * The man page of truncate says if the size changed,
2539 * then the st_ctime and st_mtime fields for the file
2540 * are updated.
2541 */
2542 attrs->ia_ctime = attrs->ia_mtime = current_time(inode);
2543 attrs->ia_valid |= ATTR_CTIME | ATTR_MTIME;
2544
Jeff Layton8efdbde2008-07-23 21:28:12 +00002545 cifs_truncate_page(inode->i_mapping, inode->i_size);
2546 }
2547
2548 return rc;
2549}
2550
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002551static int
2552cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2553{
2554 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002555 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002556 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002557 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002558 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2559 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002560 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002561 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002562 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002563 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002564
Al Viro35c265e2014-08-19 20:25:34 -04002565 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2566 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002567
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002568 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002569
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002570 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2571 attrs->ia_valid |= ATTR_FORCE;
2572
Jan Kara31051c82016-05-26 16:55:18 +02002573 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002574 if (rc < 0)
2575 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002576
2577 full_path = build_path_from_dentry(direntry);
2578 if (full_path == NULL) {
2579 rc = -ENOMEM;
2580 goto out;
2581 }
2582
Jeff Layton0f4d6342009-03-26 13:35:37 -04002583 /*
2584 * Attempt to flush data before changing attributes. We need to do
2585 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2586 * ownership or mode then we may also need to do this. Here, we take
2587 * the safe way out and just do the flush on all setattr requests. If
2588 * the flush returns error, store it to report later and continue.
2589 *
2590 * BB: This should be smarter. Why bother flushing pages that
2591 * will be truncated anyway? Also, should we error out here if
2592 * the flush returns error?
2593 */
2594 rc = filemap_write_and_wait(inode->i_mapping);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002595 if (is_interrupt_error(rc)) {
2596 rc = -ERESTARTSYS;
2597 goto out;
2598 }
2599
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002600 mapping_set_error(inode->i_mapping, rc);
2601 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002602
2603 if (attrs->ia_valid & ATTR_SIZE) {
2604 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2605 if (rc != 0)
2606 goto out;
2607 }
2608
2609 /* skip mode change if it's just for clearing setuid/setgid */
2610 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2611 attrs->ia_valid &= ~ATTR_MODE;
2612
2613 args = kmalloc(sizeof(*args), GFP_KERNEL);
2614 if (args == NULL) {
2615 rc = -ENOMEM;
2616 goto out;
2617 }
2618
2619 /* set up the struct */
2620 if (attrs->ia_valid & ATTR_MODE)
2621 args->mode = attrs->ia_mode;
2622 else
2623 args->mode = NO_CHANGE_64;
2624
2625 if (attrs->ia_valid & ATTR_UID)
2626 args->uid = attrs->ia_uid;
2627 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002628 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002629
2630 if (attrs->ia_valid & ATTR_GID)
2631 args->gid = attrs->ia_gid;
2632 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002633 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002634
2635 if (attrs->ia_valid & ATTR_ATIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002636 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002637 else
2638 args->atime = NO_CHANGE_64;
2639
2640 if (attrs->ia_valid & ATTR_MTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002641 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002642 else
2643 args->mtime = NO_CHANGE_64;
2644
2645 if (attrs->ia_valid & ATTR_CTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002646 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002647 else
2648 args->ctime = NO_CHANGE_64;
2649
2650 args->device = 0;
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002651 open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002652 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002653 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002654 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002655 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002656 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002657 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002658 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002659 tlink = cifs_sb_tlink(cifs_sb);
2660 if (IS_ERR(tlink)) {
2661 rc = PTR_ERR(tlink);
2662 goto out;
2663 }
2664 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002665 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002666 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002667 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002668 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002669 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002670
Christoph Hellwig10257742010-06-04 11:30:02 +02002671 if (rc)
2672 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002673
Christoph Hellwig10257742010-06-04 11:30:02 +02002674 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002675 attrs->ia_size != i_size_read(inode))
2676 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002677
2678 setattr_copy(inode, attrs);
2679 mark_inode_dirty(inode);
2680
2681 /* force revalidate when any of these times are set since some
2682 of the fs types (eg ext3, fat) do not have fine enough
2683 time granularity to match protocol, and we do not have a
2684 a way (yet) to query the server fs's time granularity (and
2685 whether it rounds times down).
2686 */
2687 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2688 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002689out:
2690 kfree(args);
2691 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002692 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002693 return rc;
2694}
2695
Jeff Layton0510eeb2008-08-02 07:26:12 -04002696static int
2697cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002699 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002700 kuid_t uid = INVALID_UID;
2701 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002702 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002703 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002704 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002705 struct cifsFileInfo *wfile;
2706 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 char *full_path = NULL;
2708 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002709 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002710 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002711
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002712 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713
Colin Ian King63d614a2019-06-24 17:39:43 +01002714 cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
Al Viro35c265e2014-08-19 20:25:34 -04002715 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002716
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002717 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2718 attrs->ia_valid |= ATTR_FORCE;
2719
Jan Kara31051c82016-05-26 16:55:18 +02002720 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002721 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002722 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002723 return rc;
Steve French6473a552005-11-29 20:20:10 -08002724 }
Steve French50c2f752007-07-13 00:33:32 +00002725
Steve French7f573562005-08-30 11:32:14 -07002726 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302728 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002729 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302730 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732
Jeff Layton0f4d6342009-03-26 13:35:37 -04002733 /*
2734 * Attempt to flush data before changing attributes. We need to do
Steve Frenchcf5371a2020-02-24 17:37:39 -06002735 * this for ATTR_SIZE and ATTR_MTIME. If the flush of the data
2736 * returns error, store it to report later and continue.
Jeff Layton0f4d6342009-03-26 13:35:37 -04002737 *
2738 * BB: This should be smarter. Why bother flushing pages that
2739 * will be truncated anyway? Also, should we error out here if
Steve Frenchcf5371a2020-02-24 17:37:39 -06002740 * the flush returns error? Do we need to check for ATTR_MTIME_SET flag?
Jeff Layton0f4d6342009-03-26 13:35:37 -04002741 */
Steve Frenchcf5371a2020-02-24 17:37:39 -06002742 if (attrs->ia_valid & (ATTR_MTIME | ATTR_SIZE | ATTR_CTIME)) {
2743 rc = filemap_write_and_wait(inode->i_mapping);
2744 if (is_interrupt_error(rc)) {
2745 rc = -ERESTARTSYS;
2746 goto cifs_setattr_exit;
2747 }
2748 mapping_set_error(inode->i_mapping, rc);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002749 }
2750
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002751 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002752
Steve Frenchcf5371a2020-02-24 17:37:39 -06002753 if ((attrs->ia_valid & ATTR_MTIME) &&
2754 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002755 rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002756 if (!rc) {
2757 tcon = tlink_tcon(wfile->tlink);
2758 rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
2759 cifsFileInfo_put(wfile);
2760 if (rc)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002761 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002762 } else if (rc != -EBADF)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002763 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002764 else
2765 rc = 0;
2766 }
2767
Steve French50531442008-03-14 19:21:31 +00002768 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002769 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2770 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002771 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002773
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002774 if (attrs->ia_valid & ATTR_UID)
2775 uid = attrs->ia_uid;
2776
2777 if (attrs->ia_valid & ATTR_GID)
2778 gid = attrs->ia_gid;
2779
Steve French22442172019-07-19 08:15:55 +00002780 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2781 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002782 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002783 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2784 uid, gid);
2785 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002786 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2787 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002788 goto cifs_setattr_exit;
2789 }
2790 }
2791 } else
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002792 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002793 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794
Jeff Laytond32c4f22007-10-18 03:05:22 -07002795 /* skip mode change if it's just for clearing setuid/setgid */
2796 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2797 attrs->ia_valid &= ~ATTR_MODE;
2798
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 mode = attrs->ia_mode;
Steve Frenchcdbce9c82005-11-19 21:04:52 -08002801 rc = 0;
Steve French22442172019-07-19 08:15:55 +00002802 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2803 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002804 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002805 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002806 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002807 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2808 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002809 goto cifs_setattr_exit;
2810 }
2811 } else
Jeff Layton51328612008-05-22 09:33:34 -04002812 if (((mode & S_IWUGO) == 0) &&
2813 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002814
2815 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2816
Jeff Layton51328612008-05-22 09:33:34 -04002817 /* fix up mode if we're not using dynperm */
2818 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2819 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2820 } else if ((mode & S_IWUGO) &&
2821 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002822
2823 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2824 /* Attributes of 0 are ignored */
2825 if (dosattr == 0)
2826 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002827
2828 /* reset local inode permissions to normal */
2829 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2830 attrs->ia_mode &= ~(S_IALLUGO);
2831 if (S_ISDIR(inode->i_mode))
2832 attrs->ia_mode |=
2833 cifs_sb->mnt_dir_mode;
2834 else
2835 attrs->ia_mode |=
2836 cifs_sb->mnt_file_mode;
2837 }
2838 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2839 /* ignore mode change - ATTR_READONLY hasn't changed */
2840 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 }
2843
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002844 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2845 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2846 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2847 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848
Steve Frenche30dcf32005-09-20 20:49:16 -07002849 /* Even if error on time set, no sense failing the call if
2850 the server would set the time to a reasonable value anyway,
2851 and this check ensures that we are not being called from
2852 sys_utimes in which case we ought to fail the call back to
2853 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002854 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002855 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002856 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857 }
2858
2859 /* do not need local check to inode_check_ok since the server does
2860 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002861 if (rc)
2862 goto cifs_setattr_exit;
2863
2864 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002865 attrs->ia_size != i_size_read(inode))
2866 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002867
2868 setattr_copy(inode, attrs);
2869 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002870
Steve Frenche30dcf32005-09-20 20:49:16 -07002871cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002873 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 return rc;
2875}
2876
Jeff Layton0510eeb2008-08-02 07:26:12 -04002877int
2878cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2879{
Al Virofc640052016-04-10 01:33:30 -04002880 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002881 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002882
2883 if (pTcon->unix_ext)
2884 return cifs_setattr_unix(direntry, attrs);
2885
2886 return cifs_setattr_nounix(direntry, attrs);
2887
2888 /* BB: add cifs_setattr_legacy for really old servers */
2889}
2890
Steve French99ee4db2007-02-27 05:35:17 +00002891#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892void cifs_delete_inode(struct inode *inode)
2893{
Joe Perchesf96637b2013-05-04 22:12:25 -05002894 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895 /* may have to add back in if and when safe distributed caching of
2896 directories added e.g. via FindNotify */
2897}
Steve French99ee4db2007-02-27 05:35:17 +00002898#endif