blob: 583f5e4008c2238efc1960003c07939882a48fa3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/inode.c
3 *
Steve Frenchf19159d2010-04-21 04:12:10 +00004 * Copyright (C) International Business Machines Corp., 2002,2010
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/stat.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/pagemap.h>
Jeff Layton4f73c7d2014-04-30 09:31:47 -040025#include <linux/freezer.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010026#include <linux/sched/signal.h>
Ingo Molnar5dd43ce2017-06-20 12:19:09 +020027#include <linux/wait_bit.h>
Christoph Hellwig10c5db22020-05-23 09:30:11 +020028#include <linux/fiemap.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010029
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <asm/div64.h>
31#include "cifsfs.h"
32#include "cifspdu.h"
33#include "cifsglob.h"
34#include "cifsproto.h"
Steve French6a5f6592020-06-11 19:25:47 -050035#include "smb2proto.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include "cifs_debug.h"
37#include "cifs_fs_sb.h"
Steve French2baa2682014-09-27 02:19:01 -050038#include "cifs_unicode.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053039#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Christoph Hellwig70eff552008-02-15 20:55:05 +000041
David Howells01c64fe2011-01-14 18:45:47 +000042static void cifs_set_ops(struct inode *inode)
Christoph Hellwig70eff552008-02-15 20:55:05 +000043{
44 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
45
46 switch (inode->i_mode & S_IFMT) {
47 case S_IFREG:
48 inode->i_op = &cifs_file_inode_ops;
49 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
50 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
51 inode->i_fop = &cifs_file_direct_nobrl_ops;
52 else
53 inode->i_fop = &cifs_file_direct_ops;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +030054 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
55 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
56 inode->i_fop = &cifs_file_strict_nobrl_ops;
57 else
58 inode->i_fop = &cifs_file_strict_ops;
Christoph Hellwig70eff552008-02-15 20:55:05 +000059 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
60 inode->i_fop = &cifs_file_nobrl_ops;
61 else { /* not direct, send byte range locks */
62 inode->i_fop = &cifs_file_ops;
63 }
64
Christoph Hellwig70eff552008-02-15 20:55:05 +000065 /* check if server can support readpages */
Jones Syue1f641d92020-04-13 09:37:23 +080066 if (cifs_sb_master_tcon(cifs_sb)->ses->server->max_read <
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +030067 PAGE_SIZE + MAX_CIFS_HDR_SIZE)
Christoph Hellwig70eff552008-02-15 20:55:05 +000068 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
69 else
70 inode->i_data.a_ops = &cifs_addr_ops;
71 break;
72 case S_IFDIR:
Steve Frenchbc5b6e22008-03-11 21:07:48 +000073#ifdef CONFIG_CIFS_DFS_UPCALL
David Howells01c64fe2011-01-14 18:45:47 +000074 if (IS_AUTOMOUNT(inode)) {
Igor Mammedov79626702008-03-09 03:44:18 +000075 inode->i_op = &cifs_dfs_referral_inode_operations;
76 } else {
Steve Frenchbc5b6e22008-03-11 21:07:48 +000077#else /* NO DFS support, treat as a directory */
78 {
79#endif
Igor Mammedov79626702008-03-09 03:44:18 +000080 inode->i_op = &cifs_dir_inode_ops;
81 inode->i_fop = &cifs_dir_ops;
82 }
Christoph Hellwig70eff552008-02-15 20:55:05 +000083 break;
84 case S_IFLNK:
85 inode->i_op = &cifs_symlink_inode_ops;
86 break;
87 default:
88 init_special_inode(inode, inode->i_mode, inode->i_rdev);
89 break;
90 }
91}
92
Jeff Laytondf2cf172010-02-12 07:44:16 -050093/* check inode attributes against fattr. If they don't match, tag the
94 * inode for cache invalidation
95 */
96static void
97cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
98{
99 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
100
Joe Perchesf96637b2013-05-04 22:12:25 -0500101 cifs_dbg(FYI, "%s: revalidating inode %llu\n",
102 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500103
104 if (inode->i_state & I_NEW) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500105 cifs_dbg(FYI, "%s: inode %llu is new\n",
106 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500107 return;
108 }
109
110 /* don't bother with revalidation if we have an oplock */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400111 if (CIFS_CACHE_READ(cifs_i)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500112 cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
113 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500114 return;
115 }
116
117 /* revalidate if mtime or size have changed */
Deepa Dinamani918c9002019-12-02 21:19:41 -0800118 fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
Arnd Bergmann95390202018-06-19 17:27:58 +0200119 if (timespec64_equal(&inode->i_mtime, &fattr->cf_mtime) &&
Jeff Laytondf2cf172010-02-12 07:44:16 -0500120 cifs_i->server_eof == fattr->cf_eof) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500121 cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
122 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500123 return;
124 }
125
Joe Perchesf96637b2013-05-04 22:12:25 -0500126 cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
127 __func__, cifs_i->uniqueid);
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400128 set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500129}
130
Jim McDonough74d290d2013-09-21 10:36:10 -0500131/*
132 * copy nlink to the inode, unless it wasn't provided. Provide
133 * sane values if we don't have an existing one and none was provided
134 */
135static void
136cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
137{
138 /*
139 * if we're in a situation where we can't trust what we
140 * got from the server (readdir, some non-unix cases)
141 * fake reasonable values
142 */
143 if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
144 /* only provide fake values on a new inode */
145 if (inode->i_state & I_NEW) {
146 if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
147 set_nlink(inode, 2);
148 else
149 set_nlink(inode, 1);
150 }
151 return;
152 }
153
154 /* we trust the server, so update it */
155 set_nlink(inode, fattr->cf_nlink);
156}
157
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400158/* populate an inode with info from a cifs_fattr struct */
159void
160cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
Christoph Hellwig75f12982008-02-25 20:25:21 +0000161{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400162 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400163 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000164
Jeff Laytondf2cf172010-02-12 07:44:16 -0500165 cifs_revalidate_cache(inode, fattr);
166
Steve Frenchb7ca6922012-08-03 08:43:01 -0500167 spin_lock(&inode->i_lock);
Deepa Dinamani918c9002019-12-02 21:19:41 -0800168 fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode);
169 fattr->cf_atime = timestamp_truncate(fattr->cf_atime, inode);
170 fattr->cf_ctime = timestamp_truncate(fattr->cf_ctime, inode);
Steve French9b9c5be2018-09-22 12:07:06 -0500171 /* we do not want atime to be less than mtime, it broke some apps */
Deepa Dinamani69738cf2019-11-29 21:30:25 -0800172 if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime) < 0)
Steve French9b9c5be2018-09-22 12:07:06 -0500173 inode->i_atime = fattr->cf_mtime;
174 else
175 inode->i_atime = fattr->cf_atime;
Arnd Bergmann95390202018-06-19 17:27:58 +0200176 inode->i_mtime = fattr->cf_mtime;
177 inode->i_ctime = fattr->cf_ctime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400178 inode->i_rdev = fattr->cf_rdev;
Jim McDonough74d290d2013-09-21 10:36:10 -0500179 cifs_nlink_fattr_to_inode(inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400180 inode->i_uid = fattr->cf_uid;
181 inode->i_gid = fattr->cf_gid;
182
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400183 /* if dynperm is set, don't clobber existing mode */
184 if (inode->i_state & I_NEW ||
185 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
186 inode->i_mode = fattr->cf_mode;
187
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400188 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400189
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400190 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
191 cifs_i->time = 0;
192 else
193 cifs_i->time = jiffies;
194
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400195 if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
196 set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
197 else
198 clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000199
Jeff Layton835a36c2010-02-10 16:21:33 -0500200 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000201 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400202 * Can't safely change the file size here if the client is writing to
203 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000204 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400205 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
206 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000207
208 /*
209 * i_blocks is not related to (i_size / i_blksize),
210 * but instead 512 byte (2**9) size is required for
211 * calculating num blocks.
212 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400213 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000214 }
215 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400216
David Howells01c64fe2011-01-14 18:45:47 +0000217 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
218 inode->i_flags |= S_AUTOMOUNT;
Jeff Laytonc2b93e02013-05-07 11:28:31 -0400219 if (inode->i_state & I_NEW)
220 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000221}
222
Jeff Layton4065c802010-05-17 07:18:58 -0400223void
224cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
225{
226 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
227
228 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
229 return;
230
231 fattr->cf_uniqueid = iunique(sb, ROOT_I);
232}
233
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400234/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
235void
236cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
237 struct cifs_sb_info *cifs_sb)
238{
239 memset(fattr, 0, sizeof(*fattr));
240 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
241 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
242 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
243
244 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
245 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
246 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
Steve French6e70e262017-09-21 21:32:29 -0500247 /* old POSIX extensions don't get create time */
248
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400249 fattr->cf_mode = le64_to_cpu(info->Permissions);
250
251 /*
252 * Since we set the inode type below we need to mask off
253 * to avoid strange results if bits set above.
254 */
255 fattr->cf_mode &= ~S_IFMT;
256 switch (le32_to_cpu(info->Type)) {
257 case UNIX_FILE:
258 fattr->cf_mode |= S_IFREG;
259 fattr->cf_dtype = DT_REG;
260 break;
261 case UNIX_SYMLINK:
262 fattr->cf_mode |= S_IFLNK;
263 fattr->cf_dtype = DT_LNK;
264 break;
265 case UNIX_DIR:
266 fattr->cf_mode |= S_IFDIR;
267 fattr->cf_dtype = DT_DIR;
268 break;
269 case UNIX_CHARDEV:
270 fattr->cf_mode |= S_IFCHR;
271 fattr->cf_dtype = DT_CHR;
272 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
273 le64_to_cpu(info->DevMinor) & MINORMASK);
274 break;
275 case UNIX_BLOCKDEV:
276 fattr->cf_mode |= S_IFBLK;
277 fattr->cf_dtype = DT_BLK;
278 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
279 le64_to_cpu(info->DevMinor) & MINORMASK);
280 break;
281 case UNIX_FIFO:
282 fattr->cf_mode |= S_IFIFO;
283 fattr->cf_dtype = DT_FIFO;
284 break;
285 case UNIX_SOCKET:
286 fattr->cf_mode |= S_IFSOCK;
287 fattr->cf_dtype = DT_SOCK;
288 break;
289 default:
290 /* safest to call it a file if we do not know */
291 fattr->cf_mode |= S_IFREG;
292 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500293 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400294 break;
295 }
296
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800297 fattr->cf_uid = cifs_sb->mnt_uid;
298 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
299 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800300 if (id < ((uid_t)-1)) {
301 kuid_t uid = make_kuid(&init_user_ns, id);
302 if (uid_valid(uid))
303 fattr->cf_uid = uid;
304 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800305 }
306
307 fattr->cf_gid = cifs_sb->mnt_gid;
308 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
309 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800310 if (id < ((gid_t)-1)) {
311 kgid_t gid = make_kgid(&init_user_ns, id);
312 if (gid_valid(gid))
313 fattr->cf_gid = gid;
314 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800315 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400316
317 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
318}
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000319
320/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400321 * Fill a cifs_fattr struct with fake inode info.
322 *
323 * Needed to setup cifs_fattr data for the directory which is the
324 * junction to the new submount (ie to setup the fake directory
325 * which represents a DFS referral).
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000326 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000327static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400328cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000329{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400330 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000331
Joe Perchesf96637b2013-05-04 22:12:25 -0500332 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000333
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400334 memset(fattr, 0, sizeof(*fattr));
335 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
336 fattr->cf_uid = cifs_sb->mnt_uid;
337 fattr->cf_gid = cifs_sb->mnt_gid;
Deepa Dinamani918c9002019-12-02 21:19:41 -0800338 ktime_get_coarse_real_ts64(&fattr->cf_mtime);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700339 fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400340 fattr->cf_nlink = 2;
Steve French97aa4952018-11-15 00:33:05 -0600341 fattr->cf_flags = CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000342}
343
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700344static int
345cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500346{
347 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400348 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500349 FILE_UNIX_BASIC_INFO find_data;
350 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500351 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500352 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700353 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000354 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500355
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400356 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700357 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500358 if (!rc) {
359 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
360 } else if (rc == -EREMOTE) {
361 cifs_create_dfs_fattr(&fattr, inode->i_sb);
362 rc = 0;
363 }
364
365 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400366 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500367 return rc;
368}
369
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400371 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400372 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400374 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000375 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400376 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000377 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400378 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Joe Perchesf96637b2013-05-04 22:12:25 -0500381 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000382
Jeff Layton7ffec372010-09-29 19:51:11 -0400383 tlink = cifs_sb_tlink(cifs_sb);
384 if (IS_ERR(tlink))
385 return PTR_ERR(tlink);
386 tcon = tlink_tcon(tlink);
387
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400389 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +0900390 cifs_sb->local_nls, cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -0400391 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400392
393 if (!rc) {
394 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
395 } else if (rc == -EREMOTE) {
396 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700397 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400398 } else {
399 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000400 }
401
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200402 /* check for Minshall+French symlinks */
403 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000404 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
405 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200406 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000407 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200408 }
409
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400410 if (*pinode == NULL) {
411 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400412 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400413 *pinode = cifs_iget(sb, &fattr);
414 if (!*pinode)
415 rc = -ENOMEM;
416 } else {
417 /* we already have inode, update it */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900418
419 /* if uniqueid is different, return error */
420 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
421 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -0700422 CIFS_I(*pinode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900423 rc = -ESTALE;
424 goto cgiiu_exit;
425 }
426
427 /* if filetype is different, return error */
428 if (unlikely(((*pinode)->i_mode & S_IFMT) !=
429 (fattr.cf_mode & S_IFMT))) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -0700430 CIFS_I(*pinode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900431 rc = -ESTALE;
432 goto cgiiu_exit;
433 }
434
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400435 cifs_fattr_to_inode(*pinode, &fattr);
436 }
Steve French0e4bbde2008-05-20 19:50:46 +0000437
Nakajima Akira7196ac12015-04-22 15:24:44 +0900438cgiiu_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 return rc;
440}
441
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400442static int
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400443cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400444 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800445{
446 int rc;
Steve Frenchdb8b6312014-09-22 05:13:55 -0500447 __u32 oplock;
Jeff Layton7ffec372010-09-29 19:51:11 -0400448 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000449 struct cifs_tcon *tcon;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400450 struct cifs_fid fid;
451 struct cifs_open_parms oparms;
Aurelien Aptel7c065142020-06-04 17:23:55 +0200452 struct cifs_io_parms io_parms = {0};
Steve French86c96b42005-11-18 20:25:31 -0800453 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800454 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000455 char *pbuf;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400456 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800457
458 pbuf = buf;
459
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400460 fattr->cf_mode &= ~S_IFMT;
461
462 if (fattr->cf_eof == 0) {
463 fattr->cf_mode |= S_IFIFO;
464 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800465 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400466 } else if (fattr->cf_eof < 8) {
467 fattr->cf_mode |= S_IFREG;
468 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800469 return -EINVAL; /* EOPNOTSUPP? */
470 }
Steve French50c2f752007-07-13 00:33:32 +0000471
Jeff Layton7ffec372010-09-29 19:51:11 -0400472 tlink = cifs_sb_tlink(cifs_sb);
473 if (IS_ERR(tlink))
474 return PTR_ERR(tlink);
475 tcon = tlink_tcon(tlink);
476
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400477 oparms.tcon = tcon;
478 oparms.cifs_sb = cifs_sb;
479 oparms.desired_access = GENERIC_READ;
Amir Goldstein0f060932020-02-03 21:46:43 +0200480 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400481 oparms.disposition = FILE_OPEN;
482 oparms.path = path;
483 oparms.fid = &fid;
484 oparms.reconnect = false;
485
Steve Frenchdb8b6312014-09-22 05:13:55 -0500486 if (tcon->ses->server->oplocks)
487 oplock = REQ_OPLOCK;
488 else
489 oplock = 0;
490 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400491 if (rc) {
Steve Frenchdb8b6312014-09-22 05:13:55 -0500492 cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400493 cifs_put_tlink(tlink);
494 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800495 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400496
497 /* Read header */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400498 io_parms.netfid = fid.netfid;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400499 io_parms.pid = current->tgid;
500 io_parms.tcon = tcon;
501 io_parms.offset = 0;
502 io_parms.length = 24;
503
Steve Frenchdb8b6312014-09-22 05:13:55 -0500504 rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
505 &bytes_read, &pbuf, &buf_type);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400506 if ((rc == 0) && (bytes_read >= 8)) {
507 if (memcmp("IntxBLK", pbuf, 8) == 0) {
508 cifs_dbg(FYI, "Block device\n");
509 fattr->cf_mode |= S_IFBLK;
510 fattr->cf_dtype = DT_BLK;
511 if (bytes_read == 24) {
512 /* we have enough to decode dev num */
513 __u64 mjr; /* major */
514 __u64 mnr; /* minor */
515 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
516 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
517 fattr->cf_rdev = MKDEV(mjr, mnr);
518 }
519 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
520 cifs_dbg(FYI, "Char device\n");
521 fattr->cf_mode |= S_IFCHR;
522 fattr->cf_dtype = DT_CHR;
523 if (bytes_read == 24) {
524 /* we have enough to decode dev num */
525 __u64 mjr; /* major */
526 __u64 mnr; /* minor */
527 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
528 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
529 fattr->cf_rdev = MKDEV(mjr, mnr);
530 }
531 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
532 cifs_dbg(FYI, "Symlink\n");
533 fattr->cf_mode |= S_IFLNK;
534 fattr->cf_dtype = DT_LNK;
535 } else {
536 fattr->cf_mode |= S_IFREG; /* file? */
537 fattr->cf_dtype = DT_REG;
538 rc = -EOPNOTSUPP;
539 }
540 } else {
541 fattr->cf_mode |= S_IFREG; /* then it is a file */
542 fattr->cf_dtype = DT_REG;
543 rc = -EOPNOTSUPP; /* or some unknown SFU type */
544 }
Steve Frenchdb8b6312014-09-22 05:13:55 -0500545
546 tcon->ses->server->ops->close(xid, tcon, &fid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400547 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800548 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800549}
550
Steve French9e294f12005-11-17 16:59:21 -0800551#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
552
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400553/*
554 * Fetch mode bits as provided by SFU.
555 *
556 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
557 */
558static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400559 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800560{
Steve French3020a1f2005-11-18 11:31:10 -0800561#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800562 ssize_t rc;
563 char ea_value[4];
564 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400565 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000566 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800567
Jeff Layton7ffec372010-09-29 19:51:11 -0400568 tlink = cifs_sb_tlink(cifs_sb);
569 if (IS_ERR(tlink))
570 return PTR_ERR(tlink);
571 tcon = tlink_tcon(tlink);
572
Steve Frenchd979f3b2014-02-01 23:27:18 -0600573 if (tcon->ses->server->ops->query_all_EAs == NULL) {
574 cifs_put_tlink(tlink);
575 return -EOPNOTSUPP;
576 }
577
578 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
579 "SETFILEBITS", ea_value, 4 /* size of buf */,
Steve French67b4c882017-05-12 20:59:10 -0500580 cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400581 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000582 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800583 return (int)rc;
584 else if (rc > 3) {
585 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400586 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500587 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
588 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400589 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500590 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800591 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400592
593 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800594#else
595 return -EOPNOTSUPP;
596#endif
Steve French9e294f12005-11-17 16:59:21 -0800597}
598
Steve French6a5f6592020-06-11 19:25:47 -0500599/* Fill a cifs_fattr struct with info from POSIX info struct */
600static void
601smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct smb311_posix_qinfo *info,
602 struct super_block *sb, bool adjust_tz, bool symlink)
603{
604 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
605 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
606
607 memset(fattr, 0, sizeof(*fattr));
608
609 /* no fattr->flags to set */
610 fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
611 fattr->cf_uniqueid = le64_to_cpu(info->Inode);
612
613 if (info->LastAccessTime)
614 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
615 else
616 ktime_get_coarse_real_ts64(&fattr->cf_atime);
617
618 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
619 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
620
621 if (adjust_tz) {
622 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
623 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
624 }
625
626 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
627 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
628 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
629
630 fattr->cf_nlink = le32_to_cpu(info->HardLinks);
631 fattr->cf_mode = (umode_t) le32_to_cpu(info->Mode);
632 /* The srv fs device id is overridden on network mount so setting rdev isn't needed here */
633 /* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */
634
635 if (symlink) {
636 fattr->cf_mode |= S_IFLNK;
637 fattr->cf_dtype = DT_LNK;
638 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
639 fattr->cf_mode |= S_IFDIR;
640 fattr->cf_dtype = DT_DIR;
641 } else { /* file */
642 fattr->cf_mode |= S_IFREG;
643 fattr->cf_dtype = DT_REG;
644 }
645 /* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */
646
647 fattr->cf_uid = cifs_sb->mnt_uid; /* TODO: map uid and gid from SID */
648 fattr->cf_gid = cifs_sb->mnt_gid;
649
650 cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
651 fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
652}
653
654
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400655/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000656static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400657cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700658 struct super_block *sb, bool adjust_tz,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400659 bool symlink)
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000660{
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700661 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French96daf2b2011-05-27 04:34:02 +0000662 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700663
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400664 memset(fattr, 0, sizeof(*fattr));
665 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
666 if (info->DeletePending)
667 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000668
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400669 if (info->LastAccessTime)
670 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
Deepa Dinamani918c9002019-12-02 21:19:41 -0800671 else
672 ktime_get_coarse_real_ts64(&fattr->cf_atime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400673
674 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
675 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
676
677 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700678 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
679 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400680 }
681
682 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
683 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500684 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400685
Jim McDonough74d290d2013-09-21 10:36:10 -0500686 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400687
688 if (symlink) {
689 fattr->cf_mode = S_IFLNK;
690 fattr->cf_dtype = DT_LNK;
691 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400692 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
693 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300694 /*
695 * Server can return wrong NumberOfLinks value for directories
696 * when Unix extensions are disabled - fake it.
697 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500698 if (!tcon->unix_ext)
699 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400700 } else {
701 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
702 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400703
Jeff Laytond0c280d2009-07-09 01:46:44 -0400704 /* clear write bits if ATTR_READONLY is set */
705 if (fattr->cf_cifsattrs & ATTR_READONLY)
706 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400707
Jim McDonough74d290d2013-09-21 10:36:10 -0500708 /*
709 * Don't accept zero nlink from non-unix servers unless
710 * delete is pending. Instead mark it as unknown.
711 */
712 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
713 !info->DeletePending) {
Joe Perchesfb4b5f12020-02-21 05:20:45 -0800714 cifs_dbg(VFS, "bogus file nlink value %u\n",
715 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500716 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500717 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300718 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400719
720 fattr->cf_uid = cifs_sb->mnt_uid;
721 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000722}
723
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700724static int
725cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500726{
727 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400728 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500729 FILE_ALL_INFO find_data;
730 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500731 struct inode *inode = file_inode(filp);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700732 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000733 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700734 struct TCP_Server_Info *server = tcon->ses->server;
735
736 if (!server->ops->query_file_info)
737 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500738
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400739 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700740 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400741 switch (rc) {
742 case 0:
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700743 cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400744 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400745 break;
746 case -EREMOTE:
747 cifs_create_dfs_fattr(&fattr, inode->i_sb);
748 rc = 0;
749 break;
750 case -EOPNOTSUPP:
751 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500752 /*
753 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000754 * for now, just skip revalidating and mark inode for
755 * immediate reval.
756 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500757 rc = 0;
758 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400759 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500760 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400761 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500762
763 /*
764 * don't bother with SFU junk here -- just mark inode as needing
765 * revalidation.
766 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500767 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
768 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
769 cifs_fattr_to_inode(inode, &fattr);
770cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400771 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500772 return rc;
773}
774
Steve French7ea884c2018-03-31 18:13:38 -0500775/* Simple function to return a 64 bit hash of string. Rarely called */
776static __u64 simple_hashstr(const char *str)
777{
Geert Uytterhoeven3995bbf2018-04-05 14:57:11 +0200778 const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
Steve French7ea884c2018-03-31 18:13:38 -0500779 __u64 hash = 0;
780
781 while (*str)
782 hash = (hash + (__u64) *str++) * hash_mult;
783
784 return hash;
785}
786
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100787/**
788 * cifs_backup_query_path_info - SMB1 fallback code to get ino
789 *
790 * Fallback code to get file metadata when we don't have access to
Geert Uytterhoeven3dc58df2020-05-05 15:43:35 +0200791 * @full_path (EACCES) and have backup creds.
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100792 *
793 * @data will be set to search info result buffer
794 * @resp_buf will be set to cifs resp buf and needs to be freed with
795 * cifs_buf_release() when done with @data.
796 */
797static int
798cifs_backup_query_path_info(int xid,
799 struct cifs_tcon *tcon,
800 struct super_block *sb,
801 const char *full_path,
802 void **resp_buf,
803 FILE_ALL_INFO **data)
804{
805 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
806 struct cifs_search_info info = {0};
807 u16 flags;
808 int rc;
809
810 *resp_buf = NULL;
811 info.endOfSearch = false;
812 if (tcon->unix_ext)
813 info.info_level = SMB_FIND_FILE_UNIX;
814 else if ((tcon->ses->capabilities &
815 tcon->ses->server->vals->cap_nt_find) == 0)
816 info.info_level = SMB_FIND_FILE_INFO_STANDARD;
817 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
818 info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
819 else /* no srvino useful for fallback to some netapp */
820 info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
821
822 flags = CIFS_SEARCH_CLOSE_ALWAYS |
823 CIFS_SEARCH_CLOSE_AT_END |
824 CIFS_SEARCH_BACKUP_SEARCH;
825
826 rc = CIFSFindFirst(xid, tcon, full_path,
827 cifs_sb, NULL, flags, &info, false);
828 if (rc)
829 return rc;
830
831 *resp_buf = (void *)info.ntwrk_buf_start;
832 *data = (FILE_ALL_INFO *)info.srch_entries_start;
833 return 0;
834}
835
836static void
837cifs_set_fattr_ino(int xid,
838 struct cifs_tcon *tcon,
839 struct super_block *sb,
840 struct inode **inode,
841 const char *full_path,
842 FILE_ALL_INFO *data,
843 struct cifs_fattr *fattr)
844{
845 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
846 struct TCP_Server_Info *server = tcon->ses->server;
847 int rc;
848
849 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
850 if (*inode)
851 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
852 else
853 fattr->cf_uniqueid = iunique(sb, ROOT_I);
854 return;
855 }
856
857 /*
858 * If we have an inode pass a NULL tcon to ensure we don't
859 * make a round trip to the server. This only works for SMB2+.
860 */
861 rc = server->ops->get_srv_inum(xid,
862 *inode ? NULL : tcon,
863 cifs_sb, full_path,
864 &fattr->cf_uniqueid,
865 data);
866 if (rc) {
867 /*
868 * If that fails reuse existing ino or generate one
869 * and disable server ones
870 */
871 if (*inode)
872 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
873 else {
874 fattr->cf_uniqueid = iunique(sb, ROOT_I);
875 cifs_autodisable_serverino(cifs_sb);
876 }
877 return;
878 }
879
880 /* If no errors, check for zero root inode (invalid) */
881 if (fattr->cf_uniqueid == 0 && strlen(full_path) == 0) {
882 cifs_dbg(FYI, "Invalid (0) inodenum\n");
883 if (*inode) {
884 /* reuse */
885 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
886 } else {
887 /* make an ino by hashing the UNC */
888 fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
889 fattr->cf_uniqueid = simple_hashstr(tcon->treeName);
890 }
891 }
892}
893
894static inline bool is_inode_cache_good(struct inode *ino)
895{
896 return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;
897}
898
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400899int
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100900cifs_get_inode_info(struct inode **inode,
901 const char *full_path,
902 FILE_ALL_INFO *in_data,
903 struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600904 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905{
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100906
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400907 struct cifs_tcon *tcon;
908 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400909 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400911 bool adjust_tz = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100912 struct cifs_fattr fattr = {0};
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400913 bool symlink = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100914 FILE_ALL_INFO *data = in_data;
915 FILE_ALL_INFO *tmp_data = NULL;
916 void *smb1_backup_rsp_buf = NULL;
917 int rc = 0;
918 int tmprc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Jeff Layton7ffec372010-09-29 19:51:11 -0400920 tlink = cifs_sb_tlink(cifs_sb);
921 if (IS_ERR(tlink))
922 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400923 tcon = tlink_tcon(tlink);
924 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400925
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100926 /*
927 * 1. Fetch file metadata if not provided (data)
928 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100930 if (!data) {
931 if (is_inode_cache_good(*inode)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500932 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100933 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100935 tmp_data = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
936 if (!tmp_data) {
Jeff Layton7ffec372010-09-29 19:51:11 -0400937 rc = -ENOMEM;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100938 goto out;
Jeff Layton7ffec372010-09-29 19:51:11 -0400939 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100940 rc = server->ops->query_path_info(xid, tcon, cifs_sb,
941 full_path, tmp_data,
942 &adjust_tz, &symlink);
943 data = tmp_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400945
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400946 /*
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100947 * 2. Convert it to internal cifs metadata (fattr)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400948 */
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100949
950 switch (rc) {
951 case 0:
952 cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
953 break;
954 case -EREMOTE:
955 /* DFS link, no metadata available on this server */
956 cifs_create_dfs_fattr(&fattr, sb);
957 rc = 0;
958 break;
959 case -EACCES:
960 /*
961 * perm errors, try again with backup flags if possible
962 *
963 * For SMB2 and later the backup intent flag
964 * is already sent if needed on open and there
965 * is no path based FindFirst operation to use
966 * to retry with
967 */
968 if (backup_cred(cifs_sb) && is_smb1_server(server)) {
969 /* for easier reading */
970 FILE_DIRECTORY_INFO *fdi;
971 SEARCH_ID_FULL_DIR_INFO *si;
972
973 rc = cifs_backup_query_path_info(xid, tcon, sb,
974 full_path,
975 &smb1_backup_rsp_buf,
976 &data);
977 if (rc)
978 goto out;
979
980 fdi = (FILE_DIRECTORY_INFO *)data;
981 si = (SEARCH_ID_FULL_DIR_INFO *)data;
982
983 cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb);
984 fattr.cf_uniqueid = le64_to_cpu(si->UniqueId);
985 /* uniqueid set, skip get inum step */
986 goto handle_mnt_opt;
987 } else {
988 /* nothing we can do, bail out */
989 goto out;
990 }
991 break;
992 default:
993 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
994 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000995 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000996
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100997 /*
998 * 3. Get or update inode number (fattr.cf_uniqueid)
999 */
1000
1001 cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);
1002
1003 /*
1004 * 4. Tweak fattr based on mount options
1005 */
1006
1007handle_mnt_opt:
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001008 /* query for SFU type info if supported and needed */
1009 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
1010 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
1011 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
1012 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001013 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001014 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001015
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001016 /* fill in 0777 bits from ACL */
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001017 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
1018 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
1019 full_path, fid);
1020 if (rc) {
1021 cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001022 __func__, rc);
1023 goto out;
Steve Frenche2f8fbf2019-07-19 06:30:07 +00001024 }
1025 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
1026 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
Dan Carpenter via samba-technical68464b82019-11-26 15:11:15 +03001027 full_path, fid);
1028 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001029 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
1030 __func__, rc);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001031 goto out;
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06001032 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001033 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001034
1035 /* fill in remaining high mode bits e.g. SUID, VTX */
1036 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
1037 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
1038
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001039 /* check for Minshall+French symlinks */
1040 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +00001041 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
1042 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001043 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +00001044 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +02001045 }
1046
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001047 /*
1048 * 5. Update inode with final fattr data
1049 */
1050
Pavel Shilovsky1208ef12012-05-27 17:34:43 +04001051 if (!*inode) {
1052 *inode = cifs_iget(sb, &fattr);
1053 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001054 rc = -ENOMEM;
1055 } else {
Nakajima Akira7196ac12015-04-22 15:24:44 +09001056 /* we already have inode, update it */
1057
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001058 /* if uniqueid is different, return error */
1059 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1060 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001061 CIFS_I(*inode)->time = 0; /* force reval */
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001062 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001063 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001064 }
1065
Nakajima Akira7196ac12015-04-22 15:24:44 +09001066 /* if filetype is different, return error */
1067 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1068 (fattr.cf_mode & S_IFMT))) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001069 CIFS_I(*inode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +09001070 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001071 goto out;
Nakajima Akira7196ac12015-04-22 15:24:44 +09001072 }
1073
Pavel Shilovsky1208ef12012-05-27 17:34:43 +04001074 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001075 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001076out:
1077 cifs_buf_release(smb1_backup_rsp_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001078 cifs_put_tlink(tlink);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001079 kfree(tmp_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 return rc;
1081}
1082
Steve French6a5f6592020-06-11 19:25:47 -05001083int
1084smb311_posix_get_inode_info(struct inode **inode,
1085 const char *full_path,
1086 struct super_block *sb, unsigned int xid)
1087{
1088 struct cifs_tcon *tcon;
1089 struct TCP_Server_Info *server;
1090 struct tcon_link *tlink;
1091 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1092 bool adjust_tz = false;
1093 struct cifs_fattr fattr = {0};
1094 bool symlink = false;
1095 struct smb311_posix_qinfo *data = NULL;
1096 int rc = 0;
1097 int tmprc = 0;
1098
1099 tlink = cifs_sb_tlink(cifs_sb);
1100 if (IS_ERR(tlink))
1101 return PTR_ERR(tlink);
1102 tcon = tlink_tcon(tlink);
1103 server = tcon->ses->server;
1104
1105 /*
1106 * 1. Fetch file metadata
1107 */
1108
1109 if (is_inode_cache_good(*inode)) {
1110 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
1111 goto out;
1112 }
1113 data = kmalloc(sizeof(struct smb311_posix_qinfo), GFP_KERNEL);
1114 if (!data) {
1115 rc = -ENOMEM;
1116 goto out;
1117 }
1118
1119 rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
1120 full_path, data,
1121 &adjust_tz, &symlink);
1122
1123 /*
1124 * 2. Convert it to internal cifs metadata (fattr)
1125 */
1126
1127 switch (rc) {
1128 case 0:
1129 smb311_posix_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
1130 break;
1131 case -EREMOTE:
1132 /* DFS link, no metadata available on this server */
1133 cifs_create_dfs_fattr(&fattr, sb);
1134 rc = 0;
1135 break;
1136 case -EACCES:
1137 /*
1138 * For SMB2 and later the backup intent flag
1139 * is already sent if needed on open and there
1140 * is no path based FindFirst operation to use
1141 * to retry with so nothing we can do, bail out
1142 */
1143 goto out;
1144 default:
1145 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
1146 goto out;
1147 }
1148
1149
1150 /*
Steve Frencha7a519a2020-06-12 14:49:47 -05001151 * 3. Tweak fattr based on mount options
Steve French6a5f6592020-06-11 19:25:47 -05001152 */
1153
1154 /* check for Minshall+French symlinks */
1155 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
1156 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
1157 full_path);
1158 if (tmprc)
1159 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
1160 }
1161
1162 /*
Steve Frencha7a519a2020-06-12 14:49:47 -05001163 * 4. Update inode with final fattr data
Steve French6a5f6592020-06-11 19:25:47 -05001164 */
1165
1166 if (!*inode) {
1167 *inode = cifs_iget(sb, &fattr);
1168 if (!*inode)
1169 rc = -ENOMEM;
1170 } else {
1171 /* we already have inode, update it */
1172
1173 /* if uniqueid is different, return error */
1174 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1175 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
1176 CIFS_I(*inode)->time = 0; /* force reval */
1177 rc = -ESTALE;
1178 goto out;
1179 }
1180
1181 /* if filetype is different, return error */
1182 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1183 (fattr.cf_mode & S_IFMT))) {
1184 CIFS_I(*inode)->time = 0; /* force reval */
1185 rc = -ESTALE;
1186 goto out;
1187 }
1188
1189 cifs_fattr_to_inode(*inode, &fattr);
1190 }
1191out:
1192 cifs_put_tlink(tlink);
1193 kfree(data);
1194 return rc;
1195}
1196
1197
Steve French7f8ed422007-09-28 22:28:55 +00001198static const struct inode_operations cifs_ipc_inode_ops = {
1199 .lookup = cifs_lookup,
1200};
1201
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001202static int
1203cifs_find_inode(struct inode *inode, void *opaque)
1204{
1205 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1206
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001207 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001208 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
1209 return 0;
1210
Jeff Layton20054bd2011-01-07 11:30:27 -05001211 /* use createtime like an i_generation field */
1212 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
1213 return 0;
1214
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001215 /* don't match inode of different type */
1216 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
1217 return 0;
1218
Jeff Layton5acfec22010-08-02 17:43:54 -04001219 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -04001220 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -04001221 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -04001222
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001223 return 1;
1224}
1225
1226static int
1227cifs_init_inode(struct inode *inode, void *opaque)
1228{
1229 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1230
1231 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -05001232 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001233 return 0;
1234}
1235
Jeff Layton5acfec22010-08-02 17:43:54 -04001236/*
1237 * walk dentry list for an inode and report whether it has aliases that
1238 * are hashed. We use this to determine if a directory inode can actually
1239 * be used.
1240 */
1241static bool
1242inode_has_hashed_dentries(struct inode *inode)
1243{
1244 struct dentry *dentry;
1245
Nick Piggin873feea2011-01-07 17:50:06 +11001246 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -04001247 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001248 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +11001249 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001250 return true;
1251 }
1252 }
Nick Piggin873feea2011-01-07 17:50:06 +11001253 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001254 return false;
1255}
1256
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001257/* Given fattrs, get a corresponding inode */
1258struct inode *
1259cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
1260{
1261 unsigned long hash;
1262 struct inode *inode;
1263
Jeff Layton3d694382010-05-11 14:59:55 -04001264retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -05001265 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001266
1267 /* hash down to 32-bits on 32-bit arch */
1268 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
1269
1270 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001271 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001272 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -04001273 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -04001274 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -04001275
1276 if (inode_has_hashed_dentries(inode)) {
1277 cifs_autodisable_serverino(CIFS_SB(sb));
1278 iput(inode);
1279 fattr->cf_uniqueid = iunique(sb, ROOT_I);
1280 goto retry_iget5_locked;
1281 }
Jeff Layton3d694382010-05-11 14:59:55 -04001282 }
1283
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001284 cifs_fattr_to_inode(inode, fattr);
Linus Torvalds1751e8a2017-11-27 13:05:09 -08001285 if (sb->s_flags & SB_NOATIME)
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001286 inode->i_flags |= S_NOATIME | S_NOCMTIME;
1287 if (inode->i_state & I_NEW) {
1288 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +00001289#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301290 /* initialize per-inode cache cookie pointer */
1291 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +00001292#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001293 unlock_new_inode(inode);
1294 }
1295 }
1296
1297 return inode;
1298}
1299
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001301struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001303 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001304 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001305 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001306 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001307 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001308 char *path = NULL;
1309 int len;
1310
1311 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1312 && cifs_sb->prepath) {
1313 len = strlen(cifs_sb->prepath);
1314 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1315 if (path == NULL)
1316 return ERR_PTR(-ENOMEM);
1317 path[0] = '/';
1318 memcpy(path+1, cifs_sb->prepath, len);
1319 } else {
1320 path = kstrdup("", GFP_KERNEL);
1321 if (path == NULL)
1322 return ERR_PTR(-ENOMEM);
1323 }
David Howellsce634ab2008-02-07 00:15:33 -08001324
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001325 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001326 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001327 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001328 /* some servers mistakenly claim POSIX support */
1329 if (rc != -EOPNOTSUPP)
1330 goto iget_no_retry;
Joe Perchesa0a30362020-04-14 22:42:53 -07001331 cifs_dbg(VFS, "server does not support POSIX extensions\n");
Steve Frenchb5b374e2014-10-06 01:01:03 -05001332 tcon->unix_ext = false;
1333 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001334
Aurelien Aptela6b50582016-05-25 19:59:09 +02001335 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
Steve Frenchd3138522020-06-11 22:43:01 -05001336 if (tcon->posix_extensions)
1337 rc = smb311_posix_get_inode_info(&inode, path, sb, xid);
1338 else
1339 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001340
1341iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001342 if (!inode) {
1343 inode = ERR_PTR(rc);
1344 goto out;
1345 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001346
Steve French0ccd4802010-07-16 04:31:02 +00001347#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301348 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001349 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001350#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301351
Aurelien Aptelb327a712018-01-24 13:46:10 +01001352 if (rc && tcon->pipe) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001353 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001354 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001355 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001356 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001357 inode->i_op = &cifs_ipc_inode_ops;
1358 inode->i_fop = &simple_dir_operations;
1359 inode->i_uid = cifs_sb->mnt_uid;
1360 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001361 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001362 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001363 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001364 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001365 }
1366
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001367out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001368 kfree(path);
Phillip Potter31cd1062018-03-17 21:06:56 +00001369 free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001370 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371}
1372
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001373int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001374cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001375 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001376{
Steve French388e57b2008-09-16 23:50:58 +00001377 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001378 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001379 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001380 FILE_BASIC_INFO info_buf;
1381
Steve French1adcb712009-02-25 14:19:56 +00001382 if (attrs == NULL)
1383 return -EINVAL;
1384
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001385 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1386 if (!server->ops->set_file_info)
1387 return -ENOSYS;
1388
Steve Frenchfd09b7d2018-08-02 20:28:18 -05001389 info_buf.Pad = 0;
1390
Steve French388e57b2008-09-16 23:50:58 +00001391 if (attrs->ia_valid & ATTR_ATIME) {
1392 set_time = true;
1393 info_buf.LastAccessTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001394 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
Steve French388e57b2008-09-16 23:50:58 +00001395 } else
1396 info_buf.LastAccessTime = 0;
1397
1398 if (attrs->ia_valid & ATTR_MTIME) {
1399 set_time = true;
1400 info_buf.LastWriteTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001401 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
Steve French388e57b2008-09-16 23:50:58 +00001402 } else
1403 info_buf.LastWriteTime = 0;
1404
1405 /*
1406 * Samba throws this field away, but windows may actually use it.
1407 * Do not set ctime unless other time stamps are changed explicitly
1408 * (i.e. by utimes()) since we would then have a mix of client and
1409 * server times.
1410 */
1411 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001412 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001413 info_buf.ChangeTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001414 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
Steve French388e57b2008-09-16 23:50:58 +00001415 } else
1416 info_buf.ChangeTime = 0;
1417
1418 info_buf.CreationTime = 0; /* don't change */
1419 info_buf.Attributes = cpu_to_le32(dosattr);
1420
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001421 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001422}
1423
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001424/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001425 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001426 * and rename it to a random name that hopefully won't conflict with
1427 * anything else.
1428 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001429int
1430cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1431 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001432{
1433 int oplock = 0;
1434 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001435 struct cifs_fid fid;
1436 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001437 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001438 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1439 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001440 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001441 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001442 __u32 dosattr, origattr;
1443 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001444
Jeff Layton7ffec372010-09-29 19:51:11 -04001445 tlink = cifs_sb_tlink(cifs_sb);
1446 if (IS_ERR(tlink))
1447 return PTR_ERR(tlink);
1448 tcon = tlink_tcon(tlink);
1449
Sachin Prabhuc483a982013-03-05 19:25:56 +00001450 /*
1451 * We cannot rename the file if the server doesn't support
1452 * CAP_INFOLEVEL_PASSTHRU
1453 */
1454 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1455 rc = -EBUSY;
1456 goto out;
1457 }
1458
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001459 oparms.tcon = tcon;
1460 oparms.cifs_sb = cifs_sb;
1461 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
Amir Goldstein0f060932020-02-03 21:46:43 +02001462 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001463 oparms.disposition = FILE_OPEN;
1464 oparms.path = full_path;
1465 oparms.fid = &fid;
1466 oparms.reconnect = false;
1467
1468 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001469 if (rc != 0)
1470 goto out;
1471
Steve French32709582008-10-20 00:44:19 +00001472 origattr = cifsInode->cifsAttrs;
1473 if (origattr == 0)
1474 origattr |= ATTR_NORMAL;
1475
1476 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001477 if (dosattr == 0)
1478 dosattr |= ATTR_NORMAL;
1479 dosattr |= ATTR_HIDDEN;
1480
Steve French32709582008-10-20 00:44:19 +00001481 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1482 if (dosattr != origattr) {
1483 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1484 if (info_buf == NULL) {
1485 rc = -ENOMEM;
1486 goto out_close;
1487 }
1488 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001489 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001490 current->tgid);
1491 /* although we would like to mark the file hidden
1492 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001493 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001494 cifsInode->cifsAttrs = dosattr;
1495 else
1496 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001497 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001498
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001499 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001500 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1501 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001502 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001503 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001504 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001505 goto undo_setattr;
1506 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001507
Steve French32709582008-10-20 00:44:19 +00001508 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001509 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001510 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001511 current->tgid);
1512 /*
1513 * some samba versions return -ENOENT when we try to set the
1514 * file disposition here. Likely a samba bug, but work around
1515 * it for now. This means that some cifsXXX files may hang
1516 * around after they shouldn't.
1517 *
1518 * BB: remove this hack after more servers have the fix
1519 */
1520 if (rc == -ENOENT)
1521 rc = 0;
1522 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001523 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001524 goto undo_rename;
1525 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001526 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001527 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001528
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001529out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001530 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001531out:
Steve French32709582008-10-20 00:44:19 +00001532 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001533 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001534 return rc;
Steve French32709582008-10-20 00:44:19 +00001535
1536 /*
1537 * reset everything back to the original state. Don't bother
1538 * dealing with errors here since we can't do anything about
1539 * them anyway.
1540 */
1541undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001542 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001543 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001544undo_setattr:
1545 if (dosattr != origattr) {
1546 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001547 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001548 current->tgid))
1549 cifsInode->cifsAttrs = origattr;
1550 }
1551
1552 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001553}
1554
Steve Frenchb7ca6922012-08-03 08:43:01 -05001555/* copied from fs/nfs/dir.c with small changes */
1556static void
1557cifs_drop_nlink(struct inode *inode)
1558{
1559 spin_lock(&inode->i_lock);
1560 if (inode->i_nlink > 0)
1561 drop_nlink(inode);
1562 spin_unlock(&inode->i_lock);
1563}
Steve Frenchff694522009-04-20 19:45:13 +00001564
1565/*
David Howells2b0143b2015-03-17 22:25:59 +00001566 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001567 * is a negative dentry) then we would attempt a standard SMB delete, but
Colin Ian King413d6102018-10-26 19:07:21 +01001568 * if that fails we can not attempt the fall back mechanisms on EACCES
1569 * but will return the EACCES to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001570 * unlink on negative dentries currently.
1571 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001572int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573{
1574 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001575 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001577 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001578 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001579 struct super_block *sb = dir->i_sb;
1580 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001581 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001582 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001583 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001584 struct iattr *attrs = NULL;
1585 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
Joe Perchesf96637b2013-05-04 22:12:25 -05001587 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588
Jeff Layton7ffec372010-09-29 19:51:11 -04001589 tlink = cifs_sb_tlink(cifs_sb);
1590 if (IS_ERR(tlink))
1591 return PTR_ERR(tlink);
1592 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001593 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001594
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001595 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
Steve French82e93672020-05-19 03:06:57 -05001597 if (tcon->nodelete) {
1598 rc = -EACCES;
1599 goto unlink_out;
1600 }
1601
Jeff Layton5f0319a2008-09-16 14:05:16 -04001602 /* Unlink can be called from rename so we can not take the
1603 * sb->s_vfs_rename_mutex here */
1604 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301606 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001607 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 }
Steve French2d785a52007-07-15 01:48:57 +00001609
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001610 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1611 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001612 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001613 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001614 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001615 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001616 if ((rc == 0) || (rc == -ENOENT))
1617 goto psx_del_no_retry;
1618 }
1619
Steve French60502472008-10-07 18:42:52 +00001620retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001621 if (!server->ops->unlink) {
1622 rc = -ENOSYS;
1623 goto psx_del_no_retry;
1624 }
1625
1626 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001627
Steve French2d785a52007-07-15 01:48:57 +00001628psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001630 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001631 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001633 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001634 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001635 if (server->ops->rename_pending_delete) {
1636 rc = server->ops->rename_pending_delete(full_path,
1637 dentry, xid);
1638 if (rc == 0)
1639 cifs_drop_nlink(inode);
1640 }
Steve Frenchff694522009-04-20 19:45:13 +00001641 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001642 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1643 if (attrs == NULL) {
1644 rc = -ENOMEM;
1645 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 }
Steve French388e57b2008-09-16 23:50:58 +00001647
1648 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001649 cifs_inode = CIFS_I(inode);
1650 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001651 if (origattr == 0)
1652 origattr |= ATTR_NORMAL;
1653 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001654 if (dosattr == 0)
1655 dosattr |= ATTR_NORMAL;
1656 dosattr |= ATTR_HIDDEN;
1657
1658 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001659 if (rc != 0)
1660 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001661
1662 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 }
Steve French60502472008-10-07 18:42:52 +00001664
1665 /* undo the setattr if we errored out and it's needed */
1666 if (rc != 0 && dosattr != 0)
1667 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1668
Steve French388e57b2008-09-16 23:50:58 +00001669out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001670 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001671 cifs_inode = CIFS_I(inode);
1672 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001673 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001674 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001675 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001676 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001677 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001678 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001679unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001681 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001682 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001683 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 return rc;
1685}
1686
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001687static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001688cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001689 const char *full_path, struct cifs_sb_info *cifs_sb,
1690 struct cifs_tcon *tcon, const unsigned int xid)
1691{
1692 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001693 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001694
Steve Frenchd3138522020-06-11 22:43:01 -05001695 if (tcon->posix_extensions)
1696 rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
1697 else if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001698 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001699 xid);
1700 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001701 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1702 xid, NULL);
1703
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001704 if (rc)
1705 return rc;
1706
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001707 /*
1708 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001709 * from the server or was set bogus. Also, since this is a brand new
1710 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001711 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001712 if (inode->i_nlink < 2)
1713 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001714 mode &= ~current_umask();
1715 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001716 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001717 mode |= S_ISGID;
1718
1719 if (tcon->unix_ext) {
1720 struct cifs_unix_set_info_args args = {
1721 .mode = mode,
1722 .ctime = NO_CHANGE_64,
1723 .atime = NO_CHANGE_64,
1724 .mtime = NO_CHANGE_64,
1725 .device = 0,
1726 };
1727 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001728 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001729 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001730 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001731 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001732 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001733 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001734 args.uid = INVALID_UID; /* no change */
1735 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001736 }
1737 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1738 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001739 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001740 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001741 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001742 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001743 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001744 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001745 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001746 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1747 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001748
Jeff Layton101b92d2012-09-19 06:22:45 -07001749 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1750 inode->i_uid = current_fsuid();
1751 if (inode->i_mode & S_ISGID)
1752 inode->i_gid = parent->i_gid;
1753 else
1754 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001755 }
1756 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001757 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001758 return rc;
1759}
1760
1761static int
1762cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1763 const char *full_path, struct cifs_sb_info *cifs_sb,
1764 struct cifs_tcon *tcon, const unsigned int xid)
1765{
1766 int rc = 0;
1767 u32 oplock = 0;
1768 FILE_UNIX_BASIC_INFO *info = NULL;
1769 struct inode *newinode = NULL;
1770 struct cifs_fattr fattr;
1771
1772 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1773 if (info == NULL) {
1774 rc = -ENOMEM;
1775 goto posix_mkdir_out;
1776 }
1777
1778 mode &= ~current_umask();
1779 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1780 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001781 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001782 if (rc == -EOPNOTSUPP)
1783 goto posix_mkdir_out;
1784 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001785 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001786 d_drop(dentry);
1787 goto posix_mkdir_out;
1788 }
1789
1790 if (info->Type == cpu_to_le32(-1))
1791 /* no return info, go query for it */
1792 goto posix_mkdir_get_info;
1793 /*
1794 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1795 * need to set uid/gid.
1796 */
1797
1798 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1799 cifs_fill_uniqueid(inode->i_sb, &fattr);
1800 newinode = cifs_iget(inode->i_sb, &fattr);
1801 if (!newinode)
1802 goto posix_mkdir_get_info;
1803
1804 d_instantiate(dentry, newinode);
1805
1806#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001807 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1808 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001809
1810 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001811 cifs_dbg(FYI, "unexpected number of links %d\n",
1812 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001813#endif
1814
1815posix_mkdir_out:
1816 kfree(info);
1817 return rc;
1818posix_mkdir_get_info:
1819 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1820 xid);
1821 goto posix_mkdir_out;
1822}
1823
Al Viro18bb1db2011-07-26 01:41:39 -04001824int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001826 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001827 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001829 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001830 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001831 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001832 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
Frank Sorensonf52aa792020-02-12 15:31:48 -06001834 cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05001835 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001838 tlink = cifs_sb_tlink(cifs_sb);
1839 if (IS_ERR(tlink))
1840 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001841 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001842
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001843 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844
Steve French7f573562005-08-30 11:32:14 -07001845 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301847 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001848 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 }
Steve French50c2f752007-07-13 00:33:32 +00001850
Steve Frenchbea851b2018-06-14 21:56:32 -05001851 server = tcon->ses->server;
1852
Steve Frenchbea851b2018-06-14 21:56:32 -05001853 if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
1854 rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
1855 cifs_sb);
1856 d_drop(direntry); /* for time being always refresh inode info */
1857 goto mkdir_out;
1858 }
Steve Frenchbea851b2018-06-14 21:56:32 -05001859
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001860 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1861 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001862 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1863 tcon, xid);
1864 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001865 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001866 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001867
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001868 if (!server->ops->mkdir) {
1869 rc = -ENOSYS;
1870 goto mkdir_out;
1871 }
1872
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001874 rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001876 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001878 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001880
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001881 /* TODO: skip this for smb2/smb3 */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001882 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1883 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001884mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001885 /*
1886 * Force revalidate to get parent dir info when needed since cached
1887 * attributes are invalid now.
1888 */
1889 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001891 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001892 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 return rc;
1894}
1895
1896int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1897{
1898 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001899 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001901 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001902 struct cifs_tcon *tcon;
1903 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 char *full_path = NULL;
1905 struct cifsInodeInfo *cifsInode;
1906
Joe Perchesf96637b2013-05-04 22:12:25 -05001907 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001909 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910
Steve French7f573562005-08-30 11:32:14 -07001911 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301913 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001914 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 }
1916
Jeff Layton7ffec372010-09-29 19:51:11 -04001917 cifs_sb = CIFS_SB(inode->i_sb);
1918 tlink = cifs_sb_tlink(cifs_sb);
1919 if (IS_ERR(tlink)) {
1920 rc = PTR_ERR(tlink);
1921 goto rmdir_exit;
1922 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001923 tcon = tlink_tcon(tlink);
1924 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001925
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001926 if (!server->ops->rmdir) {
1927 rc = -ENOSYS;
1928 cifs_put_tlink(tlink);
1929 goto rmdir_exit;
1930 }
1931
Steve French82e93672020-05-19 03:06:57 -05001932 if (tcon->nodelete) {
1933 rc = -EACCES;
1934 cifs_put_tlink(tlink);
1935 goto rmdir_exit;
1936 }
1937
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001938 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001939 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
1941 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001942 spin_lock(&d_inode(direntry)->i_lock);
1943 i_size_write(d_inode(direntry), 0);
1944 clear_nlink(d_inode(direntry));
1945 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 }
1947
David Howells2b0143b2015-03-17 22:25:59 +00001948 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001949 /* force revalidate to go get info when needed */
1950 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001951
1952 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001953 /*
1954 * Force revalidate to get parent dir info when needed since cached
1955 * attributes are invalid now.
1956 */
1957 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001958
David Howells2b0143b2015-03-17 22:25:59 +00001959 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001960 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961
Jeff Layton7ffec372010-09-29 19:51:11 -04001962rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001964 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 return rc;
1966}
1967
Steve Frenchee2fd962008-09-23 18:23:33 +00001968static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001969cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1970 const char *from_path, struct dentry *to_dentry,
1971 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001972{
1973 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001974 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001975 struct cifs_tcon *tcon;
1976 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001977 struct cifs_fid fid;
1978 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001979 int oplock, rc;
1980
Jeff Layton7ffec372010-09-29 19:51:11 -04001981 tlink = cifs_sb_tlink(cifs_sb);
1982 if (IS_ERR(tlink))
1983 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001984 tcon = tlink_tcon(tlink);
1985 server = tcon->ses->server;
1986
1987 if (!server->ops->rename)
1988 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001989
Steve Frenchee2fd962008-09-23 18:23:33 +00001990 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001991 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001992
1993 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001994 * Don't bother with rename by filehandle unless file is busy and
1995 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001996 * rename by filehandle to various Windows servers.
1997 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001998 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001999 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00002000
Frank Sorenson652727b2019-04-16 08:37:27 -05002001 /* Don't fall back to using SMB on SMB 2+ mount */
2002 if (server->vals->protocol_id != 0)
2003 goto do_rename_exit;
2004
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04002005 /* open-file renames don't work across directories */
2006 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04002007 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04002008
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002009 oparms.tcon = tcon;
2010 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00002011 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002012 oparms.desired_access = DELETE;
Amir Goldstein0f060932020-02-03 21:46:43 +02002013 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002014 oparms.disposition = FILE_OPEN;
2015 oparms.path = from_path;
2016 oparms.fid = &fid;
2017 oparms.reconnect = false;
2018
2019 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00002020 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002021 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00002022 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05002023 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04002024 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00002025 }
Jeff Layton7ffec372010-09-29 19:51:11 -04002026do_rename_exit:
Steve Frenchc7e9f782020-02-25 18:08:54 -06002027 if (rc == 0)
2028 d_move(from_dentry, to_dentry);
Jeff Layton7ffec372010-09-29 19:51:11 -04002029 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00002030 return rc;
2031}
2032
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002033int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002034cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
2035 struct inode *target_dir, struct dentry *target_dentry,
2036 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002038 char *from_name = NULL;
2039 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04002040 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04002041 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002042 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00002043 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
2044 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002045 unsigned int xid;
2046 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002048 if (flags & ~RENAME_NOREPLACE)
2049 return -EINVAL;
2050
Jeff Layton639e7a92010-09-03 11:50:09 -04002051 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002052 tlink = cifs_sb_tlink(cifs_sb);
2053 if (IS_ERR(tlink))
2054 return PTR_ERR(tlink);
2055 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002057 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00002058
2059 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00002060 * we already have the rename sem so we do not need to
2061 * grab it again here to protect the path integrity
2062 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002063 from_name = build_path_from_dentry(source_dentry);
2064 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 rc = -ENOMEM;
2066 goto cifs_rename_exit;
2067 }
2068
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002069 to_name = build_path_from_dentry(target_dentry);
2070 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00002071 rc = -ENOMEM;
2072 goto cifs_rename_exit;
2073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002075 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
2076 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00002077
Miklos Szeredi7c33d592014-07-23 15:15:36 +02002078 /*
2079 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
2080 */
2081 if (flags & RENAME_NOREPLACE)
2082 goto cifs_rename_exit;
2083
Jeff Layton14121bd2008-10-20 14:45:22 -04002084 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00002085 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002086 * Are src and dst hardlinks of same inode? We can only tell
2087 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00002088 */
Jeff Layton14121bd2008-10-20 14:45:22 -04002089 info_buf_source =
Kees Cook6da2ec52018-06-12 13:55:00 -07002090 kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
Jeff Layton14121bd2008-10-20 14:45:22 -04002091 GFP_KERNEL);
2092 if (info_buf_source == NULL) {
2093 rc = -ENOMEM;
2094 goto cifs_rename_exit;
2095 }
2096
2097 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002098 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
2099 info_buf_source,
2100 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002101 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04002102 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04002103 goto unlink_target;
2104
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002105 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
2106 info_buf_target,
2107 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002108 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04002109
Jeff Layton8d281ef2008-10-22 13:57:01 -04002110 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05002111 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04002112 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05002113 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04002114 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05002115 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002116 }
2117 /*
2118 * else ... BB we could add the same check for Windows by
2119 * checking the UniqueId via FILE_INTERNAL_INFO
2120 */
Jeff Layton14121bd2008-10-20 14:45:22 -04002121
Jeff Layton14121bd2008-10-20 14:45:22 -04002122unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04002123 /* Try unlinking the target dentry if it's not negative */
David Howells2b0143b2015-03-17 22:25:59 +00002124 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04002125 if (d_is_dir(target_dentry))
2126 tmprc = cifs_rmdir(target_dir, target_dentry);
2127 else
2128 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04002129 if (tmprc)
2130 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002131 rc = cifs_do_rename(xid, source_dentry, from_name,
2132 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 }
2134
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04002135 /* force revalidate to go get info when needed */
2136 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
2137
2138 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07002139 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04002140
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00002142 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07002143 kfree(from_name);
2144 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002145 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04002146 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 return rc;
2148}
2149
Jeff Laytondf2cf172010-02-12 07:44:16 -05002150static bool
2151cifs_inode_needs_reval(struct inode *inode)
2152{
2153 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302154 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002155
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002156 if (cifs_i->time == 0)
2157 return true;
2158
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002159 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05002160 return false;
2161
2162 if (!lookupCacheEnabled)
2163 return true;
2164
Jeff Laytona87c9ad2014-03-26 07:24:23 -07002165 if (!cifs_sb->actimeo)
2166 return true;
2167
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302168 if (!time_in_range(jiffies, cifs_i->time,
2169 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05002170 return true;
2171
Jeff Laytondb192722010-05-17 14:51:49 -04002172 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302173 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04002174 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
2175 return true;
2176
Jeff Laytondf2cf172010-02-12 07:44:16 -05002177 return false;
2178}
2179
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05302180/*
2181 * Zap the cache. Called when invalid_mapping flag is set.
2182 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002183int
Jeff Laytondf2cf172010-02-12 07:44:16 -05002184cifs_invalidate_mapping(struct inode *inode)
2185{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002186 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002187
Jeff Laytondf2cf172010-02-12 07:44:16 -05002188 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002189 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002190 if (rc)
Joe Perchesa0a30362020-04-14 22:42:53 -07002191 cifs_dbg(VFS, "%s: Could not invalidate inode %p\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05002192 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002193 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002194
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05302195 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002196 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002197}
2198
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002199/**
2200 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
2201 * @word: long word containing the bit lock
2202 */
2203static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002204cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002205{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002206 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002207 if (signal_pending_state(mode, current))
2208 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002209 return 0;
2210}
2211
Jeff Laytone284e532014-04-30 09:31:46 -04002212int
2213cifs_revalidate_mapping(struct inode *inode)
2214{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002215 int rc;
2216 unsigned long *flags = &CIFS_I(inode)->flags;
2217
Steve French4e8aea32020-04-09 21:42:18 -05002218 /* swapfiles are not supposed to be shared */
2219 if (IS_SWAPFILE(inode))
2220 return 0;
2221
NeilBrown74316202014-07-07 15:16:04 +10002222 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
2223 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002224 if (rc)
2225 return rc;
2226
2227 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
2228 rc = cifs_invalidate_mapping(inode);
2229 if (rc)
2230 set_bit(CIFS_INO_INVALID_MAPPING, flags);
2231 }
2232
2233 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07002234 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002235 wake_up_bit(flags, CIFS_INO_LOCK);
2236
2237 return rc;
2238}
2239
2240int
2241cifs_zap_mapping(struct inode *inode)
2242{
2243 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
2244 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04002245}
2246
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002247int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05002248{
2249 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05002250 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba642010-09-20 16:01:31 -07002251 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05002252
2253 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002254 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05002255
Jeff Layton13cfb732010-09-29 19:51:11 -04002256 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05002257 rc = cifs_get_file_info_unix(filp);
2258 else
2259 rc = cifs_get_file_info(filp);
2260
Jeff Laytonabab0952010-02-12 07:44:18 -05002261 return rc;
2262}
2263
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002264int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002266 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002267 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00002268 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002269 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002270 char *full_path = NULL;
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002271 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272
Jeff Laytondf2cf172010-02-12 07:44:16 -05002273 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 return -ENOENT;
2275
Jeff Laytondf2cf172010-02-12 07:44:16 -05002276 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002277 return rc;
2278
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002279 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280
2281 /* can not safely grab the rename sem here if rename calls revalidate
2282 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05002283 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302285 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002286 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05002288
Joe Perchesf96637b2013-05-04 22:12:25 -05002289 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
2290 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02002291 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002293again:
Steve French6a5f6592020-06-11 19:25:47 -05002294 if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
2295 rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
2296 else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05002297 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
2298 else
2299 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
2300 xid, NULL);
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002301 if (rc == -EAGAIN && count++ < 10)
2302 goto again;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002303out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002305 free_xid(xid);
Ronnie Sahlbergfc513fa2020-02-19 06:01:03 +10002306
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 return rc;
2308}
2309
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002310int cifs_revalidate_file(struct file *filp)
2311{
2312 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002313 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002314
2315 rc = cifs_revalidate_file_attr(filp);
2316 if (rc)
2317 return rc;
2318
Jeff Laytone284e532014-04-30 09:31:46 -04002319 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002320}
2321
2322/* revalidate a dentry's inode attributes */
2323int cifs_revalidate_dentry(struct dentry *dentry)
2324{
2325 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002326 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002327
2328 rc = cifs_revalidate_dentry_attr(dentry);
2329 if (rc)
2330 return rc;
2331
Jeff Laytone284e532014-04-30 09:31:46 -04002332 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002333}
2334
David Howellsa528d352017-01-31 16:46:22 +00002335int cifs_getattr(const struct path *path, struct kstat *stat,
2336 u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337{
David Howellsa528d352017-01-31 16:46:22 +00002338 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002339 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002340 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002341 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002342 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002343
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002344 /*
2345 * We need to be sure that all dirty pages are written and the server
2346 * has actual ctime, mtime and file length.
2347 */
Steve Frenchffdec8d2020-02-18 18:07:57 -06002348 if ((request_mask & (STATX_CTIME | STATX_MTIME | STATX_SIZE)) &&
2349 !CIFS_CACHE_READ(CIFS_I(inode)) &&
2350 inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002351 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002352 if (rc) {
2353 mapping_set_error(inode->i_mapping, rc);
2354 return rc;
2355 }
Steve French5fe14c82006-11-07 19:26:33 +00002356 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002357
Steve Frenchffdec8d2020-02-18 18:07:57 -06002358 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_FORCE_SYNC)
2359 CIFS_I(inode)->time = 0; /* force revalidate */
2360
2361 /*
2362 * If the caller doesn't require syncing, only sync if
2363 * necessary (e.g. due to earlier truncate or setattr
2364 * invalidating the cached metadata)
2365 */
2366 if (((flags & AT_STATX_SYNC_TYPE) != AT_STATX_DONT_SYNC) ||
2367 (CIFS_I(inode)->time == 0)) {
2368 rc = cifs_revalidate_dentry_attr(dentry);
2369 if (rc)
2370 return rc;
2371 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002372
2373 generic_fillattr(inode, stat);
Steve Frenche8506d22019-02-28 21:32:15 -06002374 stat->blksize = cifs_sb->bsize;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002375 stat->ino = CIFS_I(inode)->uniqueid;
2376
Steve French6e70e262017-09-21 21:32:29 -05002377 /* old CIFS Unix Extensions doesn't return create time */
2378 if (CIFS_I(inode)->createtime) {
2379 stat->result_mask |= STATX_BTIME;
Arnd Bergmann95390202018-06-19 17:27:58 +02002380 stat->btime =
2381 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
Steve French6e70e262017-09-21 21:32:29 -05002382 }
2383
2384 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2385 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2386 stat->attributes |= STATX_ATTR_COMPRESSED;
2387 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2388 stat->attributes |= STATX_ATTR_ENCRYPTED;
2389
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002390 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002391 * If on a multiuser mount without unix extensions or cifsacl being
2392 * enabled, and the admin hasn't overridden them, set the ownership
2393 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002394 */
2395 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002396 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002397 !tcon->unix_ext) {
2398 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2399 stat->uid = current_fsuid();
2400 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2401 stat->gid = current_fsgid();
2402 }
Dan Carpenter39946882020-02-28 12:22:59 +03002403 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404}
2405
Ronnie Sahlberg2f3ebab2019-04-25 16:45:29 +10002406int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
2407 u64 len)
2408{
2409 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2410 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->vfs_inode.i_sb);
2411 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2412 struct TCP_Server_Info *server = tcon->ses->server;
2413 struct cifsFileInfo *cfile;
2414 int rc;
2415
2416 /*
2417 * We need to be sure that all dirty pages are written as they
2418 * might fill holes on the server.
2419 */
2420 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
2421 inode->i_mapping->nrpages != 0) {
2422 rc = filemap_fdatawait(inode->i_mapping);
2423 if (rc) {
2424 mapping_set_error(inode->i_mapping, rc);
2425 return rc;
2426 }
2427 }
2428
2429 cfile = find_readable_file(cifs_i, false);
2430 if (cfile == NULL)
2431 return -EINVAL;
2432
2433 if (server->ops->fiemap) {
2434 rc = server->ops->fiemap(tcon, cfile, fei, start, len);
2435 cifsFileInfo_put(cfile);
2436 return rc;
2437 }
2438
2439 cifsFileInfo_put(cfile);
2440 return -ENOTSUPP;
2441}
2442
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002443int cifs_truncate_page(struct address_space *mapping, loff_t from)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002445 pgoff_t index = from >> PAGE_SHIFT;
2446 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 int rc = 0;
2449
2450 page = grab_cache_page(mapping, index);
2451 if (!page)
2452 return -ENOMEM;
2453
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002454 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002456 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 return rc;
2458}
2459
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002460void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002461{
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002462 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2463
Steve Frenchba6a46a2007-02-26 20:06:29 +00002464 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002465 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002466 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002467
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002468 /* Cached inode must be refreshed on truncate */
2469 cifs_i->time = 0;
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002470 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002471}
2472
Jeff Layton8efdbde2008-07-23 21:28:12 +00002473static int
2474cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002475 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002476{
2477 int rc;
2478 struct cifsFileInfo *open_file;
2479 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2480 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002481 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002482 struct cifs_tcon *tcon = NULL;
2483 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002484
2485 /*
2486 * To avoid spurious oplock breaks from server, in the case of
2487 * inodes that we already have open, avoid doing path based
2488 * setting of file size if we can do it by handle.
2489 * This keeps our caching token (oplock) and avoids timeouts
2490 * when the local oplock break takes longer to flush
2491 * writebehind data than the SMB timeout for the SetPathInfo
2492 * request would allow
2493 */
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002494 open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002495 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002496 tcon = tlink_tcon(open_file->tlink);
2497 server = tcon->ses->server;
2498 if (server->ops->set_file_size)
2499 rc = server->ops->set_file_size(xid, tcon, open_file,
2500 attrs->ia_size, false);
2501 else
2502 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002503 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002504 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002505 } else
2506 rc = -EINVAL;
2507
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002508 if (!rc)
2509 goto set_size_out;
Jeff Laytonba00ba642010-09-20 16:01:31 -07002510
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002511 if (tcon == NULL) {
2512 tlink = cifs_sb_tlink(cifs_sb);
2513 if (IS_ERR(tlink))
2514 return PTR_ERR(tlink);
2515 tcon = tlink_tcon(tlink);
2516 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002517 }
2518
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002519 /*
2520 * Set file size by pathname rather than by handle either because no
2521 * valid, writeable file handle for it was found or because there was
2522 * an error setting it by handle.
2523 */
2524 if (server->ops->set_path_size)
2525 rc = server->ops->set_path_size(xid, tcon, full_path,
2526 attrs->ia_size, cifs_sb, false);
2527 else
2528 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002529 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002530
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002531 if (tlink)
2532 cifs_put_tlink(tlink);
2533
2534set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002535 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002536 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002537 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002538 cifs_truncate_page(inode->i_mapping, inode->i_size);
2539 }
2540
2541 return rc;
2542}
2543
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002544static int
2545cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2546{
2547 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002548 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002549 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002550 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002551 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2552 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002553 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002554 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002555 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002556 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002557
Al Viro35c265e2014-08-19 20:25:34 -04002558 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2559 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002560
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002561 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002562
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002563 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2564 attrs->ia_valid |= ATTR_FORCE;
2565
Jan Kara31051c82016-05-26 16:55:18 +02002566 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002567 if (rc < 0)
2568 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002569
2570 full_path = build_path_from_dentry(direntry);
2571 if (full_path == NULL) {
2572 rc = -ENOMEM;
2573 goto out;
2574 }
2575
Jeff Layton0f4d6342009-03-26 13:35:37 -04002576 /*
2577 * Attempt to flush data before changing attributes. We need to do
2578 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2579 * ownership or mode then we may also need to do this. Here, we take
2580 * the safe way out and just do the flush on all setattr requests. If
2581 * the flush returns error, store it to report later and continue.
2582 *
2583 * BB: This should be smarter. Why bother flushing pages that
2584 * will be truncated anyway? Also, should we error out here if
2585 * the flush returns error?
2586 */
2587 rc = filemap_write_and_wait(inode->i_mapping);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002588 if (is_interrupt_error(rc)) {
2589 rc = -ERESTARTSYS;
2590 goto out;
2591 }
2592
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002593 mapping_set_error(inode->i_mapping, rc);
2594 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002595
2596 if (attrs->ia_valid & ATTR_SIZE) {
2597 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2598 if (rc != 0)
2599 goto out;
2600 }
2601
2602 /* skip mode change if it's just for clearing setuid/setgid */
2603 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2604 attrs->ia_valid &= ~ATTR_MODE;
2605
2606 args = kmalloc(sizeof(*args), GFP_KERNEL);
2607 if (args == NULL) {
2608 rc = -ENOMEM;
2609 goto out;
2610 }
2611
2612 /* set up the struct */
2613 if (attrs->ia_valid & ATTR_MODE)
2614 args->mode = attrs->ia_mode;
2615 else
2616 args->mode = NO_CHANGE_64;
2617
2618 if (attrs->ia_valid & ATTR_UID)
2619 args->uid = attrs->ia_uid;
2620 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002621 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002622
2623 if (attrs->ia_valid & ATTR_GID)
2624 args->gid = attrs->ia_gid;
2625 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002626 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002627
2628 if (attrs->ia_valid & ATTR_ATIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002629 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002630 else
2631 args->atime = NO_CHANGE_64;
2632
2633 if (attrs->ia_valid & ATTR_MTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002634 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002635 else
2636 args->mtime = NO_CHANGE_64;
2637
2638 if (attrs->ia_valid & ATTR_CTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002639 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002640 else
2641 args->ctime = NO_CHANGE_64;
2642
2643 args->device = 0;
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002644 open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002645 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002646 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002647 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002648 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002649 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002650 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002651 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002652 tlink = cifs_sb_tlink(cifs_sb);
2653 if (IS_ERR(tlink)) {
2654 rc = PTR_ERR(tlink);
2655 goto out;
2656 }
2657 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002658 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002659 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002660 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002661 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002662 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002663
Christoph Hellwig10257742010-06-04 11:30:02 +02002664 if (rc)
2665 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002666
Christoph Hellwig10257742010-06-04 11:30:02 +02002667 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002668 attrs->ia_size != i_size_read(inode))
2669 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002670
2671 setattr_copy(inode, attrs);
2672 mark_inode_dirty(inode);
2673
2674 /* force revalidate when any of these times are set since some
2675 of the fs types (eg ext3, fat) do not have fine enough
2676 time granularity to match protocol, and we do not have a
2677 a way (yet) to query the server fs's time granularity (and
2678 whether it rounds times down).
2679 */
2680 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2681 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002682out:
2683 kfree(args);
2684 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002685 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002686 return rc;
2687}
2688
Jeff Layton0510eeb2008-08-02 07:26:12 -04002689static int
2690cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002692 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002693 kuid_t uid = INVALID_UID;
2694 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002695 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002696 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002697 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002698 struct cifsFileInfo *wfile;
2699 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 char *full_path = NULL;
2701 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002702 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002703 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002704
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002705 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706
Colin Ian King63d614a2019-06-24 17:39:43 +01002707 cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
Al Viro35c265e2014-08-19 20:25:34 -04002708 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002709
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002710 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2711 attrs->ia_valid |= ATTR_FORCE;
2712
Jan Kara31051c82016-05-26 16:55:18 +02002713 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002714 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002715 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002716 return rc;
Steve French6473a552005-11-29 20:20:10 -08002717 }
Steve French50c2f752007-07-13 00:33:32 +00002718
Steve French7f573562005-08-30 11:32:14 -07002719 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302721 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002722 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302723 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725
Jeff Layton0f4d6342009-03-26 13:35:37 -04002726 /*
2727 * Attempt to flush data before changing attributes. We need to do
Steve Frenchcf5371a2020-02-24 17:37:39 -06002728 * this for ATTR_SIZE and ATTR_MTIME. If the flush of the data
2729 * returns error, store it to report later and continue.
Jeff Layton0f4d6342009-03-26 13:35:37 -04002730 *
2731 * BB: This should be smarter. Why bother flushing pages that
2732 * will be truncated anyway? Also, should we error out here if
Steve Frenchcf5371a2020-02-24 17:37:39 -06002733 * the flush returns error? Do we need to check for ATTR_MTIME_SET flag?
Jeff Layton0f4d6342009-03-26 13:35:37 -04002734 */
Steve Frenchcf5371a2020-02-24 17:37:39 -06002735 if (attrs->ia_valid & (ATTR_MTIME | ATTR_SIZE | ATTR_CTIME)) {
2736 rc = filemap_write_and_wait(inode->i_mapping);
2737 if (is_interrupt_error(rc)) {
2738 rc = -ERESTARTSYS;
2739 goto cifs_setattr_exit;
2740 }
2741 mapping_set_error(inode->i_mapping, rc);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002742 }
2743
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002744 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002745
Steve Frenchcf5371a2020-02-24 17:37:39 -06002746 if ((attrs->ia_valid & ATTR_MTIME) &&
2747 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
Aurelien Aptel86f740f2020-02-21 11:19:06 +01002748 rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002749 if (!rc) {
2750 tcon = tlink_tcon(wfile->tlink);
2751 rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
2752 cifsFileInfo_put(wfile);
2753 if (rc)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002754 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002755 } else if (rc != -EBADF)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002756 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002757 else
2758 rc = 0;
2759 }
2760
Steve French50531442008-03-14 19:21:31 +00002761 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002762 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2763 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002764 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002766
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002767 if (attrs->ia_valid & ATTR_UID)
2768 uid = attrs->ia_uid;
2769
2770 if (attrs->ia_valid & ATTR_GID)
2771 gid = attrs->ia_gid;
2772
Steve French22442172019-07-19 08:15:55 +00002773 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2774 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002775 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002776 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2777 uid, gid);
2778 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002779 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2780 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002781 goto cifs_setattr_exit;
2782 }
2783 }
2784 } else
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002785 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002786 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787
Jeff Laytond32c4f22007-10-18 03:05:22 -07002788 /* skip mode change if it's just for clearing setuid/setgid */
2789 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2790 attrs->ia_valid &= ~ATTR_MODE;
2791
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 mode = attrs->ia_mode;
Steve Frenchcdbce9c82005-11-19 21:04:52 -08002794 rc = 0;
Steve French22442172019-07-19 08:15:55 +00002795 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2796 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002797 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002798 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002799 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002800 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2801 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002802 goto cifs_setattr_exit;
2803 }
2804 } else
Jeff Layton51328612008-05-22 09:33:34 -04002805 if (((mode & S_IWUGO) == 0) &&
2806 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002807
2808 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2809
Jeff Layton51328612008-05-22 09:33:34 -04002810 /* fix up mode if we're not using dynperm */
2811 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2812 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2813 } else if ((mode & S_IWUGO) &&
2814 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002815
2816 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2817 /* Attributes of 0 are ignored */
2818 if (dosattr == 0)
2819 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002820
2821 /* reset local inode permissions to normal */
2822 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2823 attrs->ia_mode &= ~(S_IALLUGO);
2824 if (S_ISDIR(inode->i_mode))
2825 attrs->ia_mode |=
2826 cifs_sb->mnt_dir_mode;
2827 else
2828 attrs->ia_mode |=
2829 cifs_sb->mnt_file_mode;
2830 }
2831 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2832 /* ignore mode change - ATTR_READONLY hasn't changed */
2833 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835 }
2836
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002837 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2838 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2839 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2840 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841
Steve Frenche30dcf32005-09-20 20:49:16 -07002842 /* Even if error on time set, no sense failing the call if
2843 the server would set the time to a reasonable value anyway,
2844 and this check ensures that we are not being called from
2845 sys_utimes in which case we ought to fail the call back to
2846 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002847 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002848 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002849 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 }
2851
2852 /* do not need local check to inode_check_ok since the server does
2853 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002854 if (rc)
2855 goto cifs_setattr_exit;
2856
2857 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002858 attrs->ia_size != i_size_read(inode))
2859 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002860
2861 setattr_copy(inode, attrs);
2862 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002863
Steve Frenche30dcf32005-09-20 20:49:16 -07002864cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002866 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 return rc;
2868}
2869
Jeff Layton0510eeb2008-08-02 07:26:12 -04002870int
2871cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2872{
Al Virofc640052016-04-10 01:33:30 -04002873 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002874 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002875
2876 if (pTcon->unix_ext)
2877 return cifs_setattr_unix(direntry, attrs);
2878
2879 return cifs_setattr_nounix(direntry, attrs);
2880
2881 /* BB: add cifs_setattr_legacy for really old servers */
2882}
2883
Steve French99ee4db2007-02-27 05:35:17 +00002884#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885void cifs_delete_inode(struct inode *inode)
2886{
Joe Perchesf96637b2013-05-04 22:12:25 -05002887 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888 /* may have to add back in if and when safe distributed caching of
2889 directories added e.g. via FindNotify */
2890}
Steve French99ee4db2007-02-27 05:35:17 +00002891#endif