blob: 0945d40030eb9e5e37069afe8884a5bcab387b18 [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>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <asm/div64.h>
30#include "cifsfs.h"
31#include "cifspdu.h"
32#include "cifsglob.h"
33#include "cifsproto.h"
34#include "cifs_debug.h"
35#include "cifs_fs_sb.h"
Steve French2baa2682014-09-27 02:19:01 -050036#include "cifs_unicode.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053037#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
Christoph Hellwig70eff552008-02-15 20:55:05 +000039
David Howells01c64fe2011-01-14 18:45:47 +000040static void cifs_set_ops(struct inode *inode)
Christoph Hellwig70eff552008-02-15 20:55:05 +000041{
42 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
43
44 switch (inode->i_mode & S_IFMT) {
45 case S_IFREG:
46 inode->i_op = &cifs_file_inode_ops;
47 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
48 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
49 inode->i_fop = &cifs_file_direct_nobrl_ops;
50 else
51 inode->i_fop = &cifs_file_direct_ops;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +030052 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
53 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
54 inode->i_fop = &cifs_file_strict_nobrl_ops;
55 else
56 inode->i_fop = &cifs_file_strict_ops;
Christoph Hellwig70eff552008-02-15 20:55:05 +000057 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
58 inode->i_fop = &cifs_file_nobrl_ops;
59 else { /* not direct, send byte range locks */
60 inode->i_fop = &cifs_file_ops;
61 }
62
Christoph Hellwig70eff552008-02-15 20:55:05 +000063 /* check if server can support readpages */
Jeff Layton0d424ad2010-09-20 16:01:35 -070064 if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +030065 PAGE_SIZE + MAX_CIFS_HDR_SIZE)
Christoph Hellwig70eff552008-02-15 20:55:05 +000066 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
67 else
68 inode->i_data.a_ops = &cifs_addr_ops;
69 break;
70 case S_IFDIR:
Steve Frenchbc5b6e22008-03-11 21:07:48 +000071#ifdef CONFIG_CIFS_DFS_UPCALL
David Howells01c64fe2011-01-14 18:45:47 +000072 if (IS_AUTOMOUNT(inode)) {
Igor Mammedov79626702008-03-09 03:44:18 +000073 inode->i_op = &cifs_dfs_referral_inode_operations;
74 } else {
Steve Frenchbc5b6e22008-03-11 21:07:48 +000075#else /* NO DFS support, treat as a directory */
76 {
77#endif
Igor Mammedov79626702008-03-09 03:44:18 +000078 inode->i_op = &cifs_dir_inode_ops;
79 inode->i_fop = &cifs_dir_ops;
80 }
Christoph Hellwig70eff552008-02-15 20:55:05 +000081 break;
82 case S_IFLNK:
83 inode->i_op = &cifs_symlink_inode_ops;
84 break;
85 default:
86 init_special_inode(inode, inode->i_mode, inode->i_rdev);
87 break;
88 }
89}
90
Jeff Laytondf2cf172010-02-12 07:44:16 -050091/* check inode attributes against fattr. If they don't match, tag the
92 * inode for cache invalidation
93 */
94static void
95cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
96{
97 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
98
Joe Perchesf96637b2013-05-04 22:12:25 -050099 cifs_dbg(FYI, "%s: revalidating inode %llu\n",
100 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500101
102 if (inode->i_state & I_NEW) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500103 cifs_dbg(FYI, "%s: inode %llu is new\n",
104 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500105 return;
106 }
107
108 /* don't bother with revalidation if we have an oplock */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400109 if (CIFS_CACHE_READ(cifs_i)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500110 cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
111 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500112 return;
113 }
114
115 /* revalidate if mtime or size have changed */
Arnd Bergmann95390202018-06-19 17:27:58 +0200116 if (timespec64_equal(&inode->i_mtime, &fattr->cf_mtime) &&
Jeff Laytondf2cf172010-02-12 07:44:16 -0500117 cifs_i->server_eof == fattr->cf_eof) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500118 cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
119 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500120 return;
121 }
122
Joe Perchesf96637b2013-05-04 22:12:25 -0500123 cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
124 __func__, cifs_i->uniqueid);
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400125 set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500126}
127
Jim McDonough74d290d2013-09-21 10:36:10 -0500128/*
129 * copy nlink to the inode, unless it wasn't provided. Provide
130 * sane values if we don't have an existing one and none was provided
131 */
132static void
133cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
134{
135 /*
136 * if we're in a situation where we can't trust what we
137 * got from the server (readdir, some non-unix cases)
138 * fake reasonable values
139 */
140 if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
141 /* only provide fake values on a new inode */
142 if (inode->i_state & I_NEW) {
143 if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
144 set_nlink(inode, 2);
145 else
146 set_nlink(inode, 1);
147 }
148 return;
149 }
150
151 /* we trust the server, so update it */
152 set_nlink(inode, fattr->cf_nlink);
153}
154
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400155/* populate an inode with info from a cifs_fattr struct */
156void
157cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
Christoph Hellwig75f12982008-02-25 20:25:21 +0000158{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400159 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400160 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000161
Jeff Laytondf2cf172010-02-12 07:44:16 -0500162 cifs_revalidate_cache(inode, fattr);
163
Steve Frenchb7ca6922012-08-03 08:43:01 -0500164 spin_lock(&inode->i_lock);
Steve French9b9c5be2018-09-22 12:07:06 -0500165 /* we do not want atime to be less than mtime, it broke some apps */
166 if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime))
167 inode->i_atime = fattr->cf_mtime;
168 else
169 inode->i_atime = fattr->cf_atime;
Arnd Bergmann95390202018-06-19 17:27:58 +0200170 inode->i_mtime = fattr->cf_mtime;
171 inode->i_ctime = fattr->cf_ctime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400172 inode->i_rdev = fattr->cf_rdev;
Jim McDonough74d290d2013-09-21 10:36:10 -0500173 cifs_nlink_fattr_to_inode(inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400174 inode->i_uid = fattr->cf_uid;
175 inode->i_gid = fattr->cf_gid;
176
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400177 /* if dynperm is set, don't clobber existing mode */
178 if (inode->i_state & I_NEW ||
179 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
180 inode->i_mode = fattr->cf_mode;
181
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400182 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400183
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400184 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
185 cifs_i->time = 0;
186 else
187 cifs_i->time = jiffies;
188
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400189 if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
190 set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
191 else
192 clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000193
Jeff Layton835a36c2010-02-10 16:21:33 -0500194 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000195 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400196 * Can't safely change the file size here if the client is writing to
197 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000198 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400199 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
200 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000201
202 /*
203 * i_blocks is not related to (i_size / i_blksize),
204 * but instead 512 byte (2**9) size is required for
205 * calculating num blocks.
206 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400207 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000208 }
209 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400210
David Howells01c64fe2011-01-14 18:45:47 +0000211 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
212 inode->i_flags |= S_AUTOMOUNT;
Jeff Laytonc2b93e02013-05-07 11:28:31 -0400213 if (inode->i_state & I_NEW)
214 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000215}
216
Jeff Layton4065c802010-05-17 07:18:58 -0400217void
218cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
219{
220 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
221
222 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
223 return;
224
225 fattr->cf_uniqueid = iunique(sb, ROOT_I);
226}
227
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400228/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
229void
230cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
231 struct cifs_sb_info *cifs_sb)
232{
233 memset(fattr, 0, sizeof(*fattr));
234 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
235 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
236 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
237
238 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
239 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
240 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
Steve French6e70e262017-09-21 21:32:29 -0500241 /* old POSIX extensions don't get create time */
242
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400243 fattr->cf_mode = le64_to_cpu(info->Permissions);
244
245 /*
246 * Since we set the inode type below we need to mask off
247 * to avoid strange results if bits set above.
248 */
249 fattr->cf_mode &= ~S_IFMT;
250 switch (le32_to_cpu(info->Type)) {
251 case UNIX_FILE:
252 fattr->cf_mode |= S_IFREG;
253 fattr->cf_dtype = DT_REG;
254 break;
255 case UNIX_SYMLINK:
256 fattr->cf_mode |= S_IFLNK;
257 fattr->cf_dtype = DT_LNK;
258 break;
259 case UNIX_DIR:
260 fattr->cf_mode |= S_IFDIR;
261 fattr->cf_dtype = DT_DIR;
262 break;
263 case UNIX_CHARDEV:
264 fattr->cf_mode |= S_IFCHR;
265 fattr->cf_dtype = DT_CHR;
266 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
267 le64_to_cpu(info->DevMinor) & MINORMASK);
268 break;
269 case UNIX_BLOCKDEV:
270 fattr->cf_mode |= S_IFBLK;
271 fattr->cf_dtype = DT_BLK;
272 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
273 le64_to_cpu(info->DevMinor) & MINORMASK);
274 break;
275 case UNIX_FIFO:
276 fattr->cf_mode |= S_IFIFO;
277 fattr->cf_dtype = DT_FIFO;
278 break;
279 case UNIX_SOCKET:
280 fattr->cf_mode |= S_IFSOCK;
281 fattr->cf_dtype = DT_SOCK;
282 break;
283 default:
284 /* safest to call it a file if we do not know */
285 fattr->cf_mode |= S_IFREG;
286 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500287 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400288 break;
289 }
290
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800291 fattr->cf_uid = cifs_sb->mnt_uid;
292 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
293 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800294 if (id < ((uid_t)-1)) {
295 kuid_t uid = make_kuid(&init_user_ns, id);
296 if (uid_valid(uid))
297 fattr->cf_uid = uid;
298 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800299 }
300
301 fattr->cf_gid = cifs_sb->mnt_gid;
302 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
303 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800304 if (id < ((gid_t)-1)) {
305 kgid_t gid = make_kgid(&init_user_ns, id);
306 if (gid_valid(gid))
307 fattr->cf_gid = gid;
308 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800309 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400310
311 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
312}
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000313
314/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400315 * Fill a cifs_fattr struct with fake inode info.
316 *
317 * Needed to setup cifs_fattr data for the directory which is the
318 * junction to the new submount (ie to setup the fake directory
319 * which represents a DFS referral).
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000320 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000321static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400322cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000323{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400324 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000325
Joe Perchesf96637b2013-05-04 22:12:25 -0500326 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000327
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400328 memset(fattr, 0, sizeof(*fattr));
329 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
330 fattr->cf_uid = cifs_sb->mnt_uid;
331 fattr->cf_gid = cifs_sb->mnt_gid;
Arnd Bergmann95390202018-06-19 17:27:58 +0200332 ktime_get_real_ts64(&fattr->cf_mtime);
333 fattr->cf_mtime = timespec64_trunc(fattr->cf_mtime, sb->s_time_gran);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700334 fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400335 fattr->cf_nlink = 2;
336 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000337}
338
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700339static int
340cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500341{
342 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400343 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500344 FILE_UNIX_BASIC_INFO find_data;
345 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500346 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500347 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700348 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000349 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500350
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400351 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700352 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500353 if (!rc) {
354 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
355 } else if (rc == -EREMOTE) {
356 cifs_create_dfs_fattr(&fattr, inode->i_sb);
357 rc = 0;
358 }
359
360 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400361 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500362 return rc;
363}
364
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400366 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400367 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400369 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000370 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400371 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000372 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400373 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
Joe Perchesf96637b2013-05-04 22:12:25 -0500376 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000377
Jeff Layton7ffec372010-09-29 19:51:11 -0400378 tlink = cifs_sb_tlink(cifs_sb);
379 if (IS_ERR(tlink))
380 return PTR_ERR(tlink);
381 tcon = tlink_tcon(tlink);
382
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400384 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +0900385 cifs_sb->local_nls, cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -0400386 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400387
388 if (!rc) {
389 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
390 } else if (rc == -EREMOTE) {
391 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700392 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400393 } else {
394 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000395 }
396
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200397 /* check for Minshall+French symlinks */
398 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000399 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
400 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200401 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000402 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200403 }
404
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400405 if (*pinode == NULL) {
406 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400407 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400408 *pinode = cifs_iget(sb, &fattr);
409 if (!*pinode)
410 rc = -ENOMEM;
411 } else {
412 /* we already have inode, update it */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900413
414 /* if uniqueid is different, return error */
415 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
416 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
417 rc = -ESTALE;
418 goto cgiiu_exit;
419 }
420
421 /* if filetype is different, return error */
422 if (unlikely(((*pinode)->i_mode & S_IFMT) !=
423 (fattr.cf_mode & S_IFMT))) {
424 rc = -ESTALE;
425 goto cgiiu_exit;
426 }
427
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400428 cifs_fattr_to_inode(*pinode, &fattr);
429 }
Steve French0e4bbde2008-05-20 19:50:46 +0000430
Nakajima Akira7196ac12015-04-22 15:24:44 +0900431cgiiu_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 return rc;
433}
434
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400435static int
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400436cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400437 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800438{
439 int rc;
Steve Frenchdb8b6312014-09-22 05:13:55 -0500440 __u32 oplock;
Jeff Layton7ffec372010-09-29 19:51:11 -0400441 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000442 struct cifs_tcon *tcon;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400443 struct cifs_fid fid;
444 struct cifs_open_parms oparms;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000445 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800446 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800447 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000448 char *pbuf;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400449 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800450
451 pbuf = buf;
452
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400453 fattr->cf_mode &= ~S_IFMT;
454
455 if (fattr->cf_eof == 0) {
456 fattr->cf_mode |= S_IFIFO;
457 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800458 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400459 } else if (fattr->cf_eof < 8) {
460 fattr->cf_mode |= S_IFREG;
461 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800462 return -EINVAL; /* EOPNOTSUPP? */
463 }
Steve French50c2f752007-07-13 00:33:32 +0000464
Jeff Layton7ffec372010-09-29 19:51:11 -0400465 tlink = cifs_sb_tlink(cifs_sb);
466 if (IS_ERR(tlink))
467 return PTR_ERR(tlink);
468 tcon = tlink_tcon(tlink);
469
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400470 oparms.tcon = tcon;
471 oparms.cifs_sb = cifs_sb;
472 oparms.desired_access = GENERIC_READ;
473 oparms.create_options = CREATE_NOT_DIR;
Steve French5e196972018-08-27 17:04:13 -0500474 if (backup_cred(cifs_sb))
475 oparms.create_options |= CREATE_OPEN_BACKUP_INTENT;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400476 oparms.disposition = FILE_OPEN;
477 oparms.path = path;
478 oparms.fid = &fid;
479 oparms.reconnect = false;
480
Steve Frenchdb8b6312014-09-22 05:13:55 -0500481 if (tcon->ses->server->oplocks)
482 oplock = REQ_OPLOCK;
483 else
484 oplock = 0;
485 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400486 if (rc) {
Steve Frenchdb8b6312014-09-22 05:13:55 -0500487 cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400488 cifs_put_tlink(tlink);
489 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800490 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400491
492 /* Read header */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400493 io_parms.netfid = fid.netfid;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400494 io_parms.pid = current->tgid;
495 io_parms.tcon = tcon;
496 io_parms.offset = 0;
497 io_parms.length = 24;
498
Steve Frenchdb8b6312014-09-22 05:13:55 -0500499 rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
500 &bytes_read, &pbuf, &buf_type);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400501 if ((rc == 0) && (bytes_read >= 8)) {
502 if (memcmp("IntxBLK", pbuf, 8) == 0) {
503 cifs_dbg(FYI, "Block device\n");
504 fattr->cf_mode |= S_IFBLK;
505 fattr->cf_dtype = DT_BLK;
506 if (bytes_read == 24) {
507 /* we have enough to decode dev num */
508 __u64 mjr; /* major */
509 __u64 mnr; /* minor */
510 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
511 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
512 fattr->cf_rdev = MKDEV(mjr, mnr);
513 }
514 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
515 cifs_dbg(FYI, "Char device\n");
516 fattr->cf_mode |= S_IFCHR;
517 fattr->cf_dtype = DT_CHR;
518 if (bytes_read == 24) {
519 /* we have enough to decode dev num */
520 __u64 mjr; /* major */
521 __u64 mnr; /* minor */
522 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
523 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
524 fattr->cf_rdev = MKDEV(mjr, mnr);
525 }
526 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
527 cifs_dbg(FYI, "Symlink\n");
528 fattr->cf_mode |= S_IFLNK;
529 fattr->cf_dtype = DT_LNK;
530 } else {
531 fattr->cf_mode |= S_IFREG; /* file? */
532 fattr->cf_dtype = DT_REG;
533 rc = -EOPNOTSUPP;
534 }
535 } else {
536 fattr->cf_mode |= S_IFREG; /* then it is a file */
537 fattr->cf_dtype = DT_REG;
538 rc = -EOPNOTSUPP; /* or some unknown SFU type */
539 }
Steve Frenchdb8b6312014-09-22 05:13:55 -0500540
541 tcon->ses->server->ops->close(xid, tcon, &fid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400542 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800543 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800544}
545
Steve French9e294f12005-11-17 16:59:21 -0800546#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
547
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400548/*
549 * Fetch mode bits as provided by SFU.
550 *
551 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
552 */
553static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400554 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800555{
Steve French3020a1f2005-11-18 11:31:10 -0800556#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800557 ssize_t rc;
558 char ea_value[4];
559 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400560 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000561 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800562
Jeff Layton7ffec372010-09-29 19:51:11 -0400563 tlink = cifs_sb_tlink(cifs_sb);
564 if (IS_ERR(tlink))
565 return PTR_ERR(tlink);
566 tcon = tlink_tcon(tlink);
567
Steve Frenchd979f3b2014-02-01 23:27:18 -0600568 if (tcon->ses->server->ops->query_all_EAs == NULL) {
569 cifs_put_tlink(tlink);
570 return -EOPNOTSUPP;
571 }
572
573 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
574 "SETFILEBITS", ea_value, 4 /* size of buf */,
Steve French67b4c882017-05-12 20:59:10 -0500575 cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400576 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000577 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800578 return (int)rc;
579 else if (rc > 3) {
580 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400581 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500582 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
583 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400584 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500585 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800586 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400587
588 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800589#else
590 return -EOPNOTSUPP;
591#endif
Steve French9e294f12005-11-17 16:59:21 -0800592}
593
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400594/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000595static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400596cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700597 struct super_block *sb, bool adjust_tz,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400598 bool symlink)
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000599{
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700600 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French96daf2b2011-05-27 04:34:02 +0000601 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700602
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400603 memset(fattr, 0, sizeof(*fattr));
604 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
605 if (info->DeletePending)
606 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000607
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400608 if (info->LastAccessTime)
609 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700610 else {
Arnd Bergmann95390202018-06-19 17:27:58 +0200611 ktime_get_real_ts64(&fattr->cf_atime);
612 fattr->cf_atime = timespec64_trunc(fattr->cf_atime, sb->s_time_gran);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700613 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400614
615 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
616 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
617
618 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700619 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
620 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400621 }
622
623 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
624 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500625 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400626
Jim McDonough74d290d2013-09-21 10:36:10 -0500627 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400628
629 if (symlink) {
630 fattr->cf_mode = S_IFLNK;
631 fattr->cf_dtype = DT_LNK;
632 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400633 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
634 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300635 /*
636 * Server can return wrong NumberOfLinks value for directories
637 * when Unix extensions are disabled - fake it.
638 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500639 if (!tcon->unix_ext)
640 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400641 } else {
642 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
643 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400644
Jeff Laytond0c280d2009-07-09 01:46:44 -0400645 /* clear write bits if ATTR_READONLY is set */
646 if (fattr->cf_cifsattrs & ATTR_READONLY)
647 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400648
Jim McDonough74d290d2013-09-21 10:36:10 -0500649 /*
650 * Don't accept zero nlink from non-unix servers unless
651 * delete is pending. Instead mark it as unknown.
652 */
653 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
654 !info->DeletePending) {
655 cifs_dbg(1, "bogus file nlink value %u\n",
Steve French6658b9f2013-07-04 14:38:48 -0500656 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500657 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500658 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300659 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400660
661 fattr->cf_uid = cifs_sb->mnt_uid;
662 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000663}
664
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700665static int
666cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500667{
668 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400669 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500670 FILE_ALL_INFO find_data;
671 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500672 struct inode *inode = file_inode(filp);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700673 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000674 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700675 struct TCP_Server_Info *server = tcon->ses->server;
676
677 if (!server->ops->query_file_info)
678 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500679
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400680 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700681 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400682 switch (rc) {
683 case 0:
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700684 cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400685 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400686 break;
687 case -EREMOTE:
688 cifs_create_dfs_fattr(&fattr, inode->i_sb);
689 rc = 0;
690 break;
691 case -EOPNOTSUPP:
692 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500693 /*
694 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000695 * for now, just skip revalidating and mark inode for
696 * immediate reval.
697 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500698 rc = 0;
699 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400700 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500701 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400702 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500703
704 /*
705 * don't bother with SFU junk here -- just mark inode as needing
706 * revalidation.
707 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500708 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
709 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
710 cifs_fattr_to_inode(inode, &fattr);
711cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400712 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500713 return rc;
714}
715
Steve French7ea884c2018-03-31 18:13:38 -0500716/* Simple function to return a 64 bit hash of string. Rarely called */
717static __u64 simple_hashstr(const char *str)
718{
Geert Uytterhoeven3995bbf2018-04-05 14:57:11 +0200719 const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
Steve French7ea884c2018-03-31 18:13:38 -0500720 __u64 hash = 0;
721
722 while (*str)
723 hash = (hash + (__u64) *str++) * hash_mult;
724
725 return hash;
726}
727
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400728int
729cifs_get_inode_info(struct inode **inode, const char *full_path,
730 FILE_ALL_INFO *data, struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600731 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500733 bool validinum = false;
734 __u16 srchflgs;
735 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400736 struct cifs_tcon *tcon;
737 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400738 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400741 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400742 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500743 struct cifs_search_info *srchinf = NULL;
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400744 bool symlink = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
Jeff Layton7ffec372010-09-29 19:51:11 -0400746 tlink = cifs_sb_tlink(cifs_sb);
747 if (IS_ERR(tlink))
748 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400749 tcon = tlink_tcon(tlink);
750 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400751
Joe Perchesf96637b2013-05-04 22:12:25 -0500752 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400754 if ((data == NULL) && (*inode != NULL)) {
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +1000755 if (CIFS_CACHE_READ(CIFS_I(*inode)) &&
756 CIFS_I(*inode)->time != 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500757 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400758 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 }
760 }
761
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400762 /* if inode info is not passed, get it from server */
763 if (data == NULL) {
764 if (!server->ops->query_path_info) {
765 rc = -ENOSYS;
766 goto cgii_exit;
767 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400769 if (buf == NULL) {
770 rc = -ENOMEM;
771 goto cgii_exit;
772 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400773 data = (FILE_ALL_INFO *)buf;
774 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400775 data, &adjust_tz, &symlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400777
778 if (!rc) {
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700779 cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400780 symlink);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400781 } else if (rc == -EREMOTE) {
782 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000783 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500784 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
785 srchinf = kzalloc(sizeof(struct cifs_search_info),
786 GFP_KERNEL);
787 if (srchinf == NULL) {
788 rc = -ENOMEM;
789 goto cgii_exit;
790 }
791
792 srchinf->endOfSearch = false;
793 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
794
795 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
796 CIFS_SEARCH_CLOSE_AT_END |
797 CIFS_SEARCH_BACKUP_SEARCH;
798
799 rc = CIFSFindFirst(xid, tcon, full_path,
800 cifs_sb, NULL, srchflgs, srchinf, false);
801 if (!rc) {
802 data =
803 (FILE_ALL_INFO *)srchinf->srch_entries_start;
804
805 cifs_dir_info_to_fattr(&fattr,
806 (FILE_DIRECTORY_INFO *)data, cifs_sb);
807 fattr.cf_uniqueid = le64_to_cpu(
808 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
809 validinum = true;
810
811 cifs_buf_release(srchinf->ntwrk_buf_start);
812 }
813 kfree(srchinf);
Steve French4c5930e2015-03-30 22:03:06 -0500814 if (rc)
815 goto cgii_exit;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500816 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000817 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400819 /*
820 * If an inode wasn't passed in, then get the inode number
821 *
822 * Is an i_ino of zero legal? Can we use that to check if the server
823 * supports returning inode numbers? Are there other sanity checks we
824 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400825 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400826 if (*inode == NULL) {
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000827 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500828 if (validinum == false) {
829 if (server->ops->get_srv_inum)
830 tmprc = server->ops->get_srv_inum(xid,
831 tcon, cifs_sb, full_path,
832 &fattr.cf_uniqueid, data);
833 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500834 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
835 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500836 fattr.cf_uniqueid = iunique(sb, ROOT_I);
837 cifs_autodisable_serverino(cifs_sb);
Steve French7ea884c2018-03-31 18:13:38 -0500838 } else if ((fattr.cf_uniqueid == 0) &&
839 strlen(full_path) == 0) {
840 /* some servers ret bad root ino ie 0 */
841 cifs_dbg(FYI, "Invalid (0) inodenum\n");
842 fattr.cf_flags |=
843 CIFS_FATTR_FAKE_ROOT_INO;
844 fattr.cf_uniqueid =
845 simple_hashstr(tcon->treeName);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500846 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500847 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500848 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400849 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000850 } else {
851 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
852 validinum == false && server->ops->get_srv_inum) {
853 /*
854 * Pass a NULL tcon to ensure we don't make a round
855 * trip to the server. This only works for SMB2+.
856 */
857 tmprc = server->ops->get_srv_inum(xid,
858 NULL, cifs_sb, full_path,
859 &fattr.cf_uniqueid, data);
860 if (tmprc)
861 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve French7ea884c2018-03-31 18:13:38 -0500862 else if ((fattr.cf_uniqueid == 0) &&
863 strlen(full_path) == 0) {
864 /*
865 * Reuse existing root inode num since
866 * inum zero for root causes ls of . and .. to
867 * not be returned
868 */
869 cifs_dbg(FYI, "Srv ret 0 inode num for root\n");
870 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
871 }
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000872 } else
873 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
874 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000875
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400876 /* query for SFU type info if supported and needed */
877 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
878 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
879 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
880 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500881 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000882 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000883
Jeff Layton79df1ba2010-12-06 12:52:08 -0500884#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000885 /* fill in 0777 bits from ACL */
886 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400887 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600888 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500889 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
890 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600891 goto cgii_exit;
892 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000893 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500894#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400895
896 /* fill in remaining high mode bits e.g. SUID, VTX */
897 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
898 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
899
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200900 /* check for Minshall+French symlinks */
901 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000902 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
903 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200904 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000905 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200906 }
907
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400908 if (!*inode) {
909 *inode = cifs_iget(sb, &fattr);
910 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400911 rc = -ENOMEM;
912 } else {
Nakajima Akira7196ac12015-04-22 15:24:44 +0900913 /* we already have inode, update it */
914
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000915 /* if uniqueid is different, return error */
916 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
917 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
918 rc = -ESTALE;
919 goto cgii_exit;
920 }
921
Nakajima Akira7196ac12015-04-22 15:24:44 +0900922 /* if filetype is different, return error */
923 if (unlikely(((*inode)->i_mode & S_IFMT) !=
924 (fattr.cf_mode & S_IFMT))) {
925 rc = -ESTALE;
926 goto cgii_exit;
927 }
928
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400929 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000930 }
931
Igor Mammedov79626702008-03-09 03:44:18 +0000932cgii_exit:
Steve French7ea884c2018-03-31 18:13:38 -0500933 if ((*inode) && ((*inode)->i_ino == 0))
934 cifs_dbg(FYI, "inode number of zero returned\n");
935
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400937 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 return rc;
939}
940
Steve French7f8ed422007-09-28 22:28:55 +0000941static const struct inode_operations cifs_ipc_inode_ops = {
942 .lookup = cifs_lookup,
943};
944
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400945static int
946cifs_find_inode(struct inode *inode, void *opaque)
947{
948 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
949
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400950 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400951 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
952 return 0;
953
Jeff Layton20054bd2011-01-07 11:30:27 -0500954 /* use createtime like an i_generation field */
955 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
956 return 0;
957
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400958 /* don't match inode of different type */
959 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
960 return 0;
961
Jeff Layton5acfec22010-08-02 17:43:54 -0400962 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400963 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400964 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400965
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400966 return 1;
967}
968
969static int
970cifs_init_inode(struct inode *inode, void *opaque)
971{
972 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
973
974 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500975 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400976 return 0;
977}
978
Jeff Layton5acfec22010-08-02 17:43:54 -0400979/*
980 * walk dentry list for an inode and report whether it has aliases that
981 * are hashed. We use this to determine if a directory inode can actually
982 * be used.
983 */
984static bool
985inode_has_hashed_dentries(struct inode *inode)
986{
987 struct dentry *dentry;
988
Nick Piggin873feea2011-01-07 17:50:06 +1100989 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -0400990 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400991 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100992 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400993 return true;
994 }
995 }
Nick Piggin873feea2011-01-07 17:50:06 +1100996 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400997 return false;
998}
999
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001000/* Given fattrs, get a corresponding inode */
1001struct inode *
1002cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
1003{
1004 unsigned long hash;
1005 struct inode *inode;
1006
Jeff Layton3d694382010-05-11 14:59:55 -04001007retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -05001008 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001009
1010 /* hash down to 32-bits on 32-bit arch */
1011 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
1012
1013 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001014 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001015 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -04001016 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -04001017 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -04001018
1019 if (inode_has_hashed_dentries(inode)) {
1020 cifs_autodisable_serverino(CIFS_SB(sb));
1021 iput(inode);
1022 fattr->cf_uniqueid = iunique(sb, ROOT_I);
1023 goto retry_iget5_locked;
1024 }
Jeff Layton3d694382010-05-11 14:59:55 -04001025 }
1026
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001027 cifs_fattr_to_inode(inode, fattr);
Linus Torvalds1751e8a2017-11-27 13:05:09 -08001028 if (sb->s_flags & SB_NOATIME)
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001029 inode->i_flags |= S_NOATIME | S_NOCMTIME;
1030 if (inode->i_state & I_NEW) {
1031 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +00001032#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301033 /* initialize per-inode cache cookie pointer */
1034 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +00001035#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001036 unlock_new_inode(inode);
1037 }
1038 }
1039
1040 return inode;
1041}
1042
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001044struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001046 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001047 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001048 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001049 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001050 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001051 char *path = NULL;
1052 int len;
1053
1054 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1055 && cifs_sb->prepath) {
1056 len = strlen(cifs_sb->prepath);
1057 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1058 if (path == NULL)
1059 return ERR_PTR(-ENOMEM);
1060 path[0] = '/';
1061 memcpy(path+1, cifs_sb->prepath, len);
1062 } else {
1063 path = kstrdup("", GFP_KERNEL);
1064 if (path == NULL)
1065 return ERR_PTR(-ENOMEM);
1066 }
David Howellsce634ab2008-02-07 00:15:33 -08001067
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001068 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001069 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001070 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001071 /* some servers mistakenly claim POSIX support */
1072 if (rc != -EOPNOTSUPP)
1073 goto iget_no_retry;
1074 cifs_dbg(VFS, "server does not support POSIX extensions");
1075 tcon->unix_ext = false;
1076 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001077
Aurelien Aptela6b50582016-05-25 19:59:09 +02001078 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
1079 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001080
1081iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001082 if (!inode) {
1083 inode = ERR_PTR(rc);
1084 goto out;
1085 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001086
Steve French0ccd4802010-07-16 04:31:02 +00001087#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301088 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001089 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001090#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301091
Aurelien Aptelb327a712018-01-24 13:46:10 +01001092 if (rc && tcon->pipe) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001093 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001094 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001095 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001096 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001097 inode->i_op = &cifs_ipc_inode_ops;
1098 inode->i_fop = &simple_dir_operations;
1099 inode->i_uid = cifs_sb->mnt_uid;
1100 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001101 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001102 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001103 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001104 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001105 }
1106
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001107out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001108 kfree(path);
Phillip Potter31cd1062018-03-17 21:06:56 +00001109 free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001110 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111}
1112
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001113int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001114cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001115 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001116{
Steve French388e57b2008-09-16 23:50:58 +00001117 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001118 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001119 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001120 FILE_BASIC_INFO info_buf;
1121
Steve French1adcb712009-02-25 14:19:56 +00001122 if (attrs == NULL)
1123 return -EINVAL;
1124
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001125 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1126 if (!server->ops->set_file_info)
1127 return -ENOSYS;
1128
Steve Frenchfd09b7d2018-08-02 20:28:18 -05001129 info_buf.Pad = 0;
1130
Steve French388e57b2008-09-16 23:50:58 +00001131 if (attrs->ia_valid & ATTR_ATIME) {
1132 set_time = true;
1133 info_buf.LastAccessTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001134 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
Steve French388e57b2008-09-16 23:50:58 +00001135 } else
1136 info_buf.LastAccessTime = 0;
1137
1138 if (attrs->ia_valid & ATTR_MTIME) {
1139 set_time = true;
1140 info_buf.LastWriteTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001141 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
Steve French388e57b2008-09-16 23:50:58 +00001142 } else
1143 info_buf.LastWriteTime = 0;
1144
1145 /*
1146 * Samba throws this field away, but windows may actually use it.
1147 * Do not set ctime unless other time stamps are changed explicitly
1148 * (i.e. by utimes()) since we would then have a mix of client and
1149 * server times.
1150 */
1151 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001152 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001153 info_buf.ChangeTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001154 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
Steve French388e57b2008-09-16 23:50:58 +00001155 } else
1156 info_buf.ChangeTime = 0;
1157
1158 info_buf.CreationTime = 0; /* don't change */
1159 info_buf.Attributes = cpu_to_le32(dosattr);
1160
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001161 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001162}
1163
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001164/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001165 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001166 * and rename it to a random name that hopefully won't conflict with
1167 * anything else.
1168 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001169int
1170cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1171 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001172{
1173 int oplock = 0;
1174 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001175 struct cifs_fid fid;
1176 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001177 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001178 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1179 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001180 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001181 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001182 __u32 dosattr, origattr;
1183 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001184
Jeff Layton7ffec372010-09-29 19:51:11 -04001185 tlink = cifs_sb_tlink(cifs_sb);
1186 if (IS_ERR(tlink))
1187 return PTR_ERR(tlink);
1188 tcon = tlink_tcon(tlink);
1189
Sachin Prabhuc483a982013-03-05 19:25:56 +00001190 /*
1191 * We cannot rename the file if the server doesn't support
1192 * CAP_INFOLEVEL_PASSTHRU
1193 */
1194 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1195 rc = -EBUSY;
1196 goto out;
1197 }
1198
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001199 oparms.tcon = tcon;
1200 oparms.cifs_sb = cifs_sb;
1201 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1202 oparms.create_options = CREATE_NOT_DIR;
1203 oparms.disposition = FILE_OPEN;
1204 oparms.path = full_path;
1205 oparms.fid = &fid;
1206 oparms.reconnect = false;
1207
1208 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001209 if (rc != 0)
1210 goto out;
1211
Steve French32709582008-10-20 00:44:19 +00001212 origattr = cifsInode->cifsAttrs;
1213 if (origattr == 0)
1214 origattr |= ATTR_NORMAL;
1215
1216 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001217 if (dosattr == 0)
1218 dosattr |= ATTR_NORMAL;
1219 dosattr |= ATTR_HIDDEN;
1220
Steve French32709582008-10-20 00:44:19 +00001221 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1222 if (dosattr != origattr) {
1223 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1224 if (info_buf == NULL) {
1225 rc = -ENOMEM;
1226 goto out_close;
1227 }
1228 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001229 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001230 current->tgid);
1231 /* although we would like to mark the file hidden
1232 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001233 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001234 cifsInode->cifsAttrs = dosattr;
1235 else
1236 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001237 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001238
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001239 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001240 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1241 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001242 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001243 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001244 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001245 goto undo_setattr;
1246 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001247
Steve French32709582008-10-20 00:44:19 +00001248 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001249 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001250 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001251 current->tgid);
1252 /*
1253 * some samba versions return -ENOENT when we try to set the
1254 * file disposition here. Likely a samba bug, but work around
1255 * it for now. This means that some cifsXXX files may hang
1256 * around after they shouldn't.
1257 *
1258 * BB: remove this hack after more servers have the fix
1259 */
1260 if (rc == -ENOENT)
1261 rc = 0;
1262 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001263 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001264 goto undo_rename;
1265 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001266 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001267 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001268
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001269out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001270 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001271out:
Steve French32709582008-10-20 00:44:19 +00001272 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001273 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001274 return rc;
Steve French32709582008-10-20 00:44:19 +00001275
1276 /*
1277 * reset everything back to the original state. Don't bother
1278 * dealing with errors here since we can't do anything about
1279 * them anyway.
1280 */
1281undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001282 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001283 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001284undo_setattr:
1285 if (dosattr != origattr) {
1286 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001287 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001288 current->tgid))
1289 cifsInode->cifsAttrs = origattr;
1290 }
1291
1292 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001293}
1294
Steve Frenchb7ca6922012-08-03 08:43:01 -05001295/* copied from fs/nfs/dir.c with small changes */
1296static void
1297cifs_drop_nlink(struct inode *inode)
1298{
1299 spin_lock(&inode->i_lock);
1300 if (inode->i_nlink > 0)
1301 drop_nlink(inode);
1302 spin_unlock(&inode->i_lock);
1303}
Steve Frenchff694522009-04-20 19:45:13 +00001304
1305/*
David Howells2b0143b2015-03-17 22:25:59 +00001306 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001307 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001308 * if that fails we can not attempt the fall back mechanisms on EACCESS
1309 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001310 * unlink on negative dentries currently.
1311 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001312int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313{
1314 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001315 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001317 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001318 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001319 struct super_block *sb = dir->i_sb;
1320 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001321 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001322 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001323 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001324 struct iattr *attrs = NULL;
1325 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
Joe Perchesf96637b2013-05-04 22:12:25 -05001327 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
Jeff Layton7ffec372010-09-29 19:51:11 -04001329 tlink = cifs_sb_tlink(cifs_sb);
1330 if (IS_ERR(tlink))
1331 return PTR_ERR(tlink);
1332 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001333 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001334
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001335 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
Jeff Layton5f0319a2008-09-16 14:05:16 -04001337 /* Unlink can be called from rename so we can not take the
1338 * sb->s_vfs_rename_mutex here */
1339 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301341 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001342 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 }
Steve French2d785a52007-07-15 01:48:57 +00001344
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001345 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1346 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001347 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001348 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001349 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001350 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001351 if ((rc == 0) || (rc == -ENOENT))
1352 goto psx_del_no_retry;
1353 }
1354
Steve French60502472008-10-07 18:42:52 +00001355retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001356 if (!server->ops->unlink) {
1357 rc = -ENOSYS;
1358 goto psx_del_no_retry;
1359 }
1360
1361 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001362
Steve French2d785a52007-07-15 01:48:57 +00001363psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001365 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001366 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001368 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001369 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001370 if (server->ops->rename_pending_delete) {
1371 rc = server->ops->rename_pending_delete(full_path,
1372 dentry, xid);
1373 if (rc == 0)
1374 cifs_drop_nlink(inode);
1375 }
Steve Frenchff694522009-04-20 19:45:13 +00001376 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001377 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1378 if (attrs == NULL) {
1379 rc = -ENOMEM;
1380 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 }
Steve French388e57b2008-09-16 23:50:58 +00001382
1383 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001384 cifs_inode = CIFS_I(inode);
1385 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001386 if (origattr == 0)
1387 origattr |= ATTR_NORMAL;
1388 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001389 if (dosattr == 0)
1390 dosattr |= ATTR_NORMAL;
1391 dosattr |= ATTR_HIDDEN;
1392
1393 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001394 if (rc != 0)
1395 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001396
1397 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 }
Steve French60502472008-10-07 18:42:52 +00001399
1400 /* undo the setattr if we errored out and it's needed */
1401 if (rc != 0 && dosattr != 0)
1402 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1403
Steve French388e57b2008-09-16 23:50:58 +00001404out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001405 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001406 cifs_inode = CIFS_I(inode);
1407 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001408 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001409 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001410 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001411 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001412 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001413 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001414unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001416 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001417 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001418 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 return rc;
1420}
1421
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001422static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001423cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001424 const char *full_path, struct cifs_sb_info *cifs_sb,
1425 struct cifs_tcon *tcon, const unsigned int xid)
1426{
1427 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001428 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001429
1430 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001431 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001432 xid);
1433 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001434 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1435 xid, NULL);
1436
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001437 if (rc)
1438 return rc;
1439
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001440 /*
1441 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001442 * from the server or was set bogus. Also, since this is a brand new
1443 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001444 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001445 if (inode->i_nlink < 2)
1446 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001447 mode &= ~current_umask();
1448 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001449 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001450 mode |= S_ISGID;
1451
1452 if (tcon->unix_ext) {
1453 struct cifs_unix_set_info_args args = {
1454 .mode = mode,
1455 .ctime = NO_CHANGE_64,
1456 .atime = NO_CHANGE_64,
1457 .mtime = NO_CHANGE_64,
1458 .device = 0,
1459 };
1460 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001461 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001462 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001463 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001464 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001465 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001466 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001467 args.uid = INVALID_UID; /* no change */
1468 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001469 }
1470 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1471 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001472 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001473 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001474 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001475 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001476 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001477 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001478 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001479 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1480 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001481
Jeff Layton101b92d2012-09-19 06:22:45 -07001482 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1483 inode->i_uid = current_fsuid();
1484 if (inode->i_mode & S_ISGID)
1485 inode->i_gid = parent->i_gid;
1486 else
1487 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001488 }
1489 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001490 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001491 return rc;
1492}
1493
1494static int
1495cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1496 const char *full_path, struct cifs_sb_info *cifs_sb,
1497 struct cifs_tcon *tcon, const unsigned int xid)
1498{
1499 int rc = 0;
1500 u32 oplock = 0;
1501 FILE_UNIX_BASIC_INFO *info = NULL;
1502 struct inode *newinode = NULL;
1503 struct cifs_fattr fattr;
1504
1505 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1506 if (info == NULL) {
1507 rc = -ENOMEM;
1508 goto posix_mkdir_out;
1509 }
1510
1511 mode &= ~current_umask();
1512 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1513 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001514 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001515 if (rc == -EOPNOTSUPP)
1516 goto posix_mkdir_out;
1517 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001518 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001519 d_drop(dentry);
1520 goto posix_mkdir_out;
1521 }
1522
1523 if (info->Type == cpu_to_le32(-1))
1524 /* no return info, go query for it */
1525 goto posix_mkdir_get_info;
1526 /*
1527 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1528 * need to set uid/gid.
1529 */
1530
1531 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1532 cifs_fill_uniqueid(inode->i_sb, &fattr);
1533 newinode = cifs_iget(inode->i_sb, &fattr);
1534 if (!newinode)
1535 goto posix_mkdir_get_info;
1536
1537 d_instantiate(dentry, newinode);
1538
1539#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001540 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1541 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001542
1543 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001544 cifs_dbg(FYI, "unexpected number of links %d\n",
1545 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001546#endif
1547
1548posix_mkdir_out:
1549 kfree(info);
1550 return rc;
1551posix_mkdir_get_info:
1552 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1553 xid);
1554 goto posix_mkdir_out;
1555}
1556
Al Viro18bb1db2011-07-26 01:41:39 -04001557int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001559 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001560 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001562 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001563 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001564 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001565 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
Joe Perchesf96637b2013-05-04 22:12:25 -05001567 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1568 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001571 tlink = cifs_sb_tlink(cifs_sb);
1572 if (IS_ERR(tlink))
1573 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001574 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001575
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001576 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
Steve French7f573562005-08-30 11:32:14 -07001578 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301580 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001581 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 }
Steve French50c2f752007-07-13 00:33:32 +00001583
Steve Frenchbea851b2018-06-14 21:56:32 -05001584 server = tcon->ses->server;
1585
Steve Frenchbea851b2018-06-14 21:56:32 -05001586 if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
1587 rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
1588 cifs_sb);
1589 d_drop(direntry); /* for time being always refresh inode info */
1590 goto mkdir_out;
1591 }
Steve Frenchbea851b2018-06-14 21:56:32 -05001592
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001593 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1594 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001595 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1596 tcon, xid);
1597 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001598 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001599 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001600
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001601 if (!server->ops->mkdir) {
1602 rc = -ENOSYS;
1603 goto mkdir_out;
1604 }
1605
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001607 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001609 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001611 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001613
1614 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1615 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001616mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001617 /*
1618 * Force revalidate to get parent dir info when needed since cached
1619 * attributes are invalid now.
1620 */
1621 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001623 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001624 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 return rc;
1626}
1627
1628int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1629{
1630 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001631 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001633 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001634 struct cifs_tcon *tcon;
1635 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 char *full_path = NULL;
1637 struct cifsInodeInfo *cifsInode;
1638
Joe Perchesf96637b2013-05-04 22:12:25 -05001639 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001641 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
Steve French7f573562005-08-30 11:32:14 -07001643 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301645 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001646 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 }
1648
Jeff Layton7ffec372010-09-29 19:51:11 -04001649 cifs_sb = CIFS_SB(inode->i_sb);
1650 tlink = cifs_sb_tlink(cifs_sb);
1651 if (IS_ERR(tlink)) {
1652 rc = PTR_ERR(tlink);
1653 goto rmdir_exit;
1654 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001655 tcon = tlink_tcon(tlink);
1656 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001657
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001658 if (!server->ops->rmdir) {
1659 rc = -ENOSYS;
1660 cifs_put_tlink(tlink);
1661 goto rmdir_exit;
1662 }
1663
1664 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001665 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
1667 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001668 spin_lock(&d_inode(direntry)->i_lock);
1669 i_size_write(d_inode(direntry), 0);
1670 clear_nlink(d_inode(direntry));
1671 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 }
1673
David Howells2b0143b2015-03-17 22:25:59 +00001674 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001675 /* force revalidate to go get info when needed */
1676 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001677
1678 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001679 /*
1680 * Force revalidate to get parent dir info when needed since cached
1681 * attributes are invalid now.
1682 */
1683 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001684
David Howells2b0143b2015-03-17 22:25:59 +00001685 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001686 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
Jeff Layton7ffec372010-09-29 19:51:11 -04001688rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001690 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 return rc;
1692}
1693
Steve Frenchee2fd962008-09-23 18:23:33 +00001694static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001695cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1696 const char *from_path, struct dentry *to_dentry,
1697 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001698{
1699 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001700 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001701 struct cifs_tcon *tcon;
1702 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001703 struct cifs_fid fid;
1704 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001705 int oplock, rc;
1706
Jeff Layton7ffec372010-09-29 19:51:11 -04001707 tlink = cifs_sb_tlink(cifs_sb);
1708 if (IS_ERR(tlink))
1709 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001710 tcon = tlink_tcon(tlink);
1711 server = tcon->ses->server;
1712
1713 if (!server->ops->rename)
1714 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001715
Steve Frenchee2fd962008-09-23 18:23:33 +00001716 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001717 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001718
1719 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001720 * Don't bother with rename by filehandle unless file is busy and
1721 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001722 * rename by filehandle to various Windows servers.
1723 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001724 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001725 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001726
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001727 /* open-file renames don't work across directories */
1728 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001729 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001730
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001731 oparms.tcon = tcon;
1732 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00001733 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001734 oparms.desired_access = DELETE;
1735 oparms.create_options = CREATE_NOT_DIR;
1736 oparms.disposition = FILE_OPEN;
1737 oparms.path = from_path;
1738 oparms.fid = &fid;
1739 oparms.reconnect = false;
1740
1741 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00001742 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001743 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001744 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001745 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001746 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001747 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001748do_rename_exit:
1749 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001750 return rc;
1751}
1752
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001753int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001754cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
1755 struct inode *target_dir, struct dentry *target_dentry,
1756 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001758 char *from_name = NULL;
1759 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001760 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001761 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001762 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001763 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1764 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001765 unsigned int xid;
1766 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001768 if (flags & ~RENAME_NOREPLACE)
1769 return -EINVAL;
1770
Jeff Layton639e7a92010-09-03 11:50:09 -04001771 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001772 tlink = cifs_sb_tlink(cifs_sb);
1773 if (IS_ERR(tlink))
1774 return PTR_ERR(tlink);
1775 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001777 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001778
1779 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001780 * we already have the rename sem so we do not need to
1781 * grab it again here to protect the path integrity
1782 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001783 from_name = build_path_from_dentry(source_dentry);
1784 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 rc = -ENOMEM;
1786 goto cifs_rename_exit;
1787 }
1788
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001789 to_name = build_path_from_dentry(target_dentry);
1790 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001791 rc = -ENOMEM;
1792 goto cifs_rename_exit;
1793 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001795 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1796 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001797
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001798 /*
1799 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
1800 */
1801 if (flags & RENAME_NOREPLACE)
1802 goto cifs_rename_exit;
1803
Jeff Layton14121bd2008-10-20 14:45:22 -04001804 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001805 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001806 * Are src and dst hardlinks of same inode? We can only tell
1807 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001808 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001809 info_buf_source =
Kees Cook6da2ec52018-06-12 13:55:00 -07001810 kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
Jeff Layton14121bd2008-10-20 14:45:22 -04001811 GFP_KERNEL);
1812 if (info_buf_source == NULL) {
1813 rc = -ENOMEM;
1814 goto cifs_rename_exit;
1815 }
1816
1817 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001818 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1819 info_buf_source,
1820 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001821 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04001822 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001823 goto unlink_target;
1824
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001825 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1826 info_buf_target,
1827 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001828 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04001829
Jeff Layton8d281ef2008-10-22 13:57:01 -04001830 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001831 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001832 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001833 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001834 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001835 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001836 }
1837 /*
1838 * else ... BB we could add the same check for Windows by
1839 * checking the UniqueId via FILE_INTERNAL_INFO
1840 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001841
Jeff Layton14121bd2008-10-20 14:45:22 -04001842unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001843 /* Try unlinking the target dentry if it's not negative */
David Howells2b0143b2015-03-17 22:25:59 +00001844 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04001845 if (d_is_dir(target_dentry))
1846 tmprc = cifs_rmdir(target_dir, target_dentry);
1847 else
1848 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001849 if (tmprc)
1850 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001851 rc = cifs_do_rename(xid, source_dentry, from_name,
1852 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 }
1854
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001855 /* force revalidate to go get info when needed */
1856 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1857
1858 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001859 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001860
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001862 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001863 kfree(from_name);
1864 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001865 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001866 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 return rc;
1868}
1869
Jeff Laytondf2cf172010-02-12 07:44:16 -05001870static bool
1871cifs_inode_needs_reval(struct inode *inode)
1872{
1873 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301874 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001875
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10001876 if (cifs_i->time == 0)
1877 return true;
1878
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001879 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001880 return false;
1881
1882 if (!lookupCacheEnabled)
1883 return true;
1884
Jeff Laytona87c9ad2014-03-26 07:24:23 -07001885 if (!cifs_sb->actimeo)
1886 return true;
1887
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301888 if (!time_in_range(jiffies, cifs_i->time,
1889 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001890 return true;
1891
Jeff Laytondb192722010-05-17 14:51:49 -04001892 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301893 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001894 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1895 return true;
1896
Jeff Laytondf2cf172010-02-12 07:44:16 -05001897 return false;
1898}
1899
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301900/*
1901 * Zap the cache. Called when invalid_mapping flag is set.
1902 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001903int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001904cifs_invalidate_mapping(struct inode *inode)
1905{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001906 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001907
Jeff Laytondf2cf172010-02-12 07:44:16 -05001908 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001909 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001910 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001911 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1912 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001913 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001914
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301915 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001916 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001917}
1918
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001919/**
1920 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
1921 * @word: long word containing the bit lock
1922 */
1923static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01001924cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001925{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001926 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01001927 if (signal_pending_state(mode, current))
1928 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001929 return 0;
1930}
1931
Jeff Laytone284e532014-04-30 09:31:46 -04001932int
1933cifs_revalidate_mapping(struct inode *inode)
1934{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001935 int rc;
1936 unsigned long *flags = &CIFS_I(inode)->flags;
1937
NeilBrown74316202014-07-07 15:16:04 +10001938 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
1939 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001940 if (rc)
1941 return rc;
1942
1943 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
1944 rc = cifs_invalidate_mapping(inode);
1945 if (rc)
1946 set_bit(CIFS_INO_INVALID_MAPPING, flags);
1947 }
1948
1949 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07001950 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001951 wake_up_bit(flags, CIFS_INO_LOCK);
1952
1953 return rc;
1954}
1955
1956int
1957cifs_zap_mapping(struct inode *inode)
1958{
1959 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
1960 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04001961}
1962
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001963int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001964{
1965 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001966 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba642010-09-20 16:01:31 -07001967 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001968
1969 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001970 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001971
Jeff Layton13cfb732010-09-29 19:51:11 -04001972 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001973 rc = cifs_get_file_info_unix(filp);
1974 else
1975 rc = cifs_get_file_info(filp);
1976
Jeff Laytonabab0952010-02-12 07:44:18 -05001977 return rc;
1978}
1979
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001980int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001982 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001983 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00001984 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001985 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001986 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
Jeff Laytondf2cf172010-02-12 07:44:16 -05001988 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 return -ENOENT;
1990
Jeff Laytondf2cf172010-02-12 07:44:16 -05001991 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001992 return rc;
1993
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001994 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995
1996 /* can not safely grab the rename sem here if rename calls revalidate
1997 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001998 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302000 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002001 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05002003
Joe Perchesf96637b2013-05-04 22:12:25 -05002004 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
2005 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02002006 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
Jeff Layton0d424ad2010-09-20 16:01:35 -07002008 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05002009 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
2010 else
2011 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
2012 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002014out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002016 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 return rc;
2018}
2019
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002020int cifs_revalidate_file(struct file *filp)
2021{
2022 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002023 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002024
2025 rc = cifs_revalidate_file_attr(filp);
2026 if (rc)
2027 return rc;
2028
Jeff Laytone284e532014-04-30 09:31:46 -04002029 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002030}
2031
2032/* revalidate a dentry's inode attributes */
2033int cifs_revalidate_dentry(struct dentry *dentry)
2034{
2035 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002036 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002037
2038 rc = cifs_revalidate_dentry_attr(dentry);
2039 if (rc)
2040 return rc;
2041
Jeff Laytone284e532014-04-30 09:31:46 -04002042 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002043}
2044
David Howellsa528d352017-01-31 16:46:22 +00002045int cifs_getattr(const struct path *path, struct kstat *stat,
2046 u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047{
David Howellsa528d352017-01-31 16:46:22 +00002048 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002049 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002050 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002051 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002052 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002053
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002054 /*
2055 * We need to be sure that all dirty pages are written and the server
2056 * has actual ctime, mtime and file length.
2057 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002058 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002059 inode->i_mapping->nrpages != 0) {
2060 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002061 if (rc) {
2062 mapping_set_error(inode->i_mapping, rc);
2063 return rc;
2064 }
Steve French5fe14c82006-11-07 19:26:33 +00002065 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002066
2067 rc = cifs_revalidate_dentry_attr(dentry);
2068 if (rc)
2069 return rc;
2070
2071 generic_fillattr(inode, stat);
2072 stat->blksize = CIFS_MAX_MSGSIZE;
2073 stat->ino = CIFS_I(inode)->uniqueid;
2074
Steve French6e70e262017-09-21 21:32:29 -05002075 /* old CIFS Unix Extensions doesn't return create time */
2076 if (CIFS_I(inode)->createtime) {
2077 stat->result_mask |= STATX_BTIME;
Arnd Bergmann95390202018-06-19 17:27:58 +02002078 stat->btime =
2079 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
Steve French6e70e262017-09-21 21:32:29 -05002080 }
2081
2082 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2083 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2084 stat->attributes |= STATX_ATTR_COMPRESSED;
2085 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2086 stat->attributes |= STATX_ATTR_ENCRYPTED;
2087
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002088 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002089 * If on a multiuser mount without unix extensions or cifsacl being
2090 * enabled, and the admin hasn't overridden them, set the ownership
2091 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002092 */
2093 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002094 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002095 !tcon->unix_ext) {
2096 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2097 stat->uid = current_fsuid();
2098 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2099 stat->gid = current_fsgid();
2100 }
2101 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102}
2103
2104static int cifs_truncate_page(struct address_space *mapping, loff_t from)
2105{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002106 pgoff_t index = from >> PAGE_SHIFT;
2107 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 int rc = 0;
2110
2111 page = grab_cache_page(mapping, index);
2112 if (!page)
2113 return -ENOMEM;
2114
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002115 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002117 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 return rc;
2119}
2120
Christoph Hellwig1b947462010-07-18 17:51:21 -04002121static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002122{
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002123 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2124
Steve Frenchba6a46a2007-02-26 20:06:29 +00002125 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002126 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002127 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002128
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002129 /* Cached inode must be refreshed on truncate */
2130 cifs_i->time = 0;
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002131 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002132}
2133
Jeff Layton8efdbde2008-07-23 21:28:12 +00002134static int
2135cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002136 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002137{
2138 int rc;
2139 struct cifsFileInfo *open_file;
2140 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2141 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002142 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002143 struct cifs_tcon *tcon = NULL;
2144 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002145
2146 /*
2147 * To avoid spurious oplock breaks from server, in the case of
2148 * inodes that we already have open, avoid doing path based
2149 * setting of file size if we can do it by handle.
2150 * This keeps our caching token (oplock) and avoids timeouts
2151 * when the local oplock break takes longer to flush
2152 * writebehind data than the SMB timeout for the SetPathInfo
2153 * request would allow
2154 */
Jeff Layton6508d902010-09-29 19:51:11 -04002155 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002156 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002157 tcon = tlink_tcon(open_file->tlink);
2158 server = tcon->ses->server;
2159 if (server->ops->set_file_size)
2160 rc = server->ops->set_file_size(xid, tcon, open_file,
2161 attrs->ia_size, false);
2162 else
2163 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002164 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002165 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002166 } else
2167 rc = -EINVAL;
2168
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002169 if (!rc)
2170 goto set_size_out;
Jeff Laytonba00ba642010-09-20 16:01:31 -07002171
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002172 if (tcon == NULL) {
2173 tlink = cifs_sb_tlink(cifs_sb);
2174 if (IS_ERR(tlink))
2175 return PTR_ERR(tlink);
2176 tcon = tlink_tcon(tlink);
2177 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002178 }
2179
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002180 /*
2181 * Set file size by pathname rather than by handle either because no
2182 * valid, writeable file handle for it was found or because there was
2183 * an error setting it by handle.
2184 */
2185 if (server->ops->set_path_size)
2186 rc = server->ops->set_path_size(xid, tcon, full_path,
2187 attrs->ia_size, cifs_sb, false);
2188 else
2189 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002190 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002191
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002192 if (tlink)
2193 cifs_put_tlink(tlink);
2194
2195set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002196 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002197 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002198 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002199 cifs_truncate_page(inode->i_mapping, inode->i_size);
2200 }
2201
2202 return rc;
2203}
2204
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002205static int
2206cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2207{
2208 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002209 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002210 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002211 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002212 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2213 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002214 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002215 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002216 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002217 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002218
Al Viro35c265e2014-08-19 20:25:34 -04002219 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2220 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002221
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002222 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002223
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002224 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2225 attrs->ia_valid |= ATTR_FORCE;
2226
Jan Kara31051c82016-05-26 16:55:18 +02002227 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002228 if (rc < 0)
2229 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002230
2231 full_path = build_path_from_dentry(direntry);
2232 if (full_path == NULL) {
2233 rc = -ENOMEM;
2234 goto out;
2235 }
2236
Jeff Layton0f4d6342009-03-26 13:35:37 -04002237 /*
2238 * Attempt to flush data before changing attributes. We need to do
2239 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2240 * ownership or mode then we may also need to do this. Here, we take
2241 * the safe way out and just do the flush on all setattr requests. If
2242 * the flush returns error, store it to report later and continue.
2243 *
2244 * BB: This should be smarter. Why bother flushing pages that
2245 * will be truncated anyway? Also, should we error out here if
2246 * the flush returns error?
2247 */
2248 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002249 mapping_set_error(inode->i_mapping, rc);
2250 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002251
2252 if (attrs->ia_valid & ATTR_SIZE) {
2253 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2254 if (rc != 0)
2255 goto out;
2256 }
2257
2258 /* skip mode change if it's just for clearing setuid/setgid */
2259 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2260 attrs->ia_valid &= ~ATTR_MODE;
2261
2262 args = kmalloc(sizeof(*args), GFP_KERNEL);
2263 if (args == NULL) {
2264 rc = -ENOMEM;
2265 goto out;
2266 }
2267
2268 /* set up the struct */
2269 if (attrs->ia_valid & ATTR_MODE)
2270 args->mode = attrs->ia_mode;
2271 else
2272 args->mode = NO_CHANGE_64;
2273
2274 if (attrs->ia_valid & ATTR_UID)
2275 args->uid = attrs->ia_uid;
2276 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002277 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002278
2279 if (attrs->ia_valid & ATTR_GID)
2280 args->gid = attrs->ia_gid;
2281 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002282 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002283
2284 if (attrs->ia_valid & ATTR_ATIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002285 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002286 else
2287 args->atime = NO_CHANGE_64;
2288
2289 if (attrs->ia_valid & ATTR_MTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002290 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002291 else
2292 args->mtime = NO_CHANGE_64;
2293
2294 if (attrs->ia_valid & ATTR_CTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002295 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002296 else
2297 args->ctime = NO_CHANGE_64;
2298
2299 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002300 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002301 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002302 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002303 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002304 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002305 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002306 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002307 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002308 tlink = cifs_sb_tlink(cifs_sb);
2309 if (IS_ERR(tlink)) {
2310 rc = PTR_ERR(tlink);
2311 goto out;
2312 }
2313 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002314 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002315 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002316 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002317 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002318 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002319
Christoph Hellwig10257742010-06-04 11:30:02 +02002320 if (rc)
2321 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002322
Christoph Hellwig10257742010-06-04 11:30:02 +02002323 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002324 attrs->ia_size != i_size_read(inode))
2325 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002326
2327 setattr_copy(inode, attrs);
2328 mark_inode_dirty(inode);
2329
2330 /* force revalidate when any of these times are set since some
2331 of the fs types (eg ext3, fat) do not have fine enough
2332 time granularity to match protocol, and we do not have a
2333 a way (yet) to query the server fs's time granularity (and
2334 whether it rounds times down).
2335 */
2336 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2337 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002338out:
2339 kfree(args);
2340 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002341 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002342 return rc;
2343}
2344
Jeff Layton0510eeb2008-08-02 07:26:12 -04002345static int
2346cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002348 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002349 kuid_t uid = INVALID_UID;
2350 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002351 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002352 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002353 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 char *full_path = NULL;
2355 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002356 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002357 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002358
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002359 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360
Al Viro35c265e2014-08-19 20:25:34 -04002361 cifs_dbg(FYI, "setattr on file %pd attrs->iavalid 0x%x\n",
2362 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002363
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002364 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2365 attrs->ia_valid |= ATTR_FORCE;
2366
Jan Kara31051c82016-05-26 16:55:18 +02002367 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002368 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002369 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002370 return rc;
Steve French6473a552005-11-29 20:20:10 -08002371 }
Steve French50c2f752007-07-13 00:33:32 +00002372
Steve French7f573562005-08-30 11:32:14 -07002373 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302375 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002376 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302377 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379
Jeff Layton0f4d6342009-03-26 13:35:37 -04002380 /*
2381 * Attempt to flush data before changing attributes. We need to do
2382 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2383 * ownership or mode then we may also need to do this. Here, we take
2384 * the safe way out and just do the flush on all setattr requests. If
2385 * the flush returns error, store it to report later and continue.
2386 *
2387 * BB: This should be smarter. Why bother flushing pages that
2388 * will be truncated anyway? Also, should we error out here if
2389 * the flush returns error?
2390 */
2391 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002392 mapping_set_error(inode->i_mapping, rc);
2393 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002394
Steve French50531442008-03-14 19:21:31 +00002395 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002396 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2397 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002398 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002400
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002401 if (attrs->ia_valid & ATTR_UID)
2402 uid = attrs->ia_uid;
2403
2404 if (attrs->ia_valid & ATTR_GID)
2405 gid = attrs->ia_gid;
2406
2407#ifdef CONFIG_CIFS_ACL
2408 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002409 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002410 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2411 uid, gid);
2412 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002413 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2414 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002415 goto cifs_setattr_exit;
2416 }
2417 }
2418 } else
2419#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002420 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002421 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
Jeff Laytond32c4f22007-10-18 03:05:22 -07002423 /* skip mode change if it's just for clearing setuid/setgid */
2424 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2425 attrs->ia_valid &= ~ATTR_MODE;
2426
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 mode = attrs->ia_mode;
Steve Frenchcdbce9c82005-11-19 21:04:52 -08002429 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002430#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002431 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002432 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002433 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002434 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002435 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2436 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002437 goto cifs_setattr_exit;
2438 }
2439 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002440#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002441 if (((mode & S_IWUGO) == 0) &&
2442 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002443
2444 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2445
Jeff Layton51328612008-05-22 09:33:34 -04002446 /* fix up mode if we're not using dynperm */
2447 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2448 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2449 } else if ((mode & S_IWUGO) &&
2450 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002451
2452 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2453 /* Attributes of 0 are ignored */
2454 if (dosattr == 0)
2455 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002456
2457 /* reset local inode permissions to normal */
2458 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2459 attrs->ia_mode &= ~(S_IALLUGO);
2460 if (S_ISDIR(inode->i_mode))
2461 attrs->ia_mode |=
2462 cifs_sb->mnt_dir_mode;
2463 else
2464 attrs->ia_mode |=
2465 cifs_sb->mnt_file_mode;
2466 }
2467 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2468 /* ignore mode change - ATTR_READONLY hasn't changed */
2469 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 }
2472
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002473 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2474 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2475 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2476 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477
Steve Frenche30dcf32005-09-20 20:49:16 -07002478 /* Even if error on time set, no sense failing the call if
2479 the server would set the time to a reasonable value anyway,
2480 and this check ensures that we are not being called from
2481 sys_utimes in which case we ought to fail the call back to
2482 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002483 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002484 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002485 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 }
2487
2488 /* do not need local check to inode_check_ok since the server does
2489 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002490 if (rc)
2491 goto cifs_setattr_exit;
2492
2493 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002494 attrs->ia_size != i_size_read(inode))
2495 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002496
2497 setattr_copy(inode, attrs);
2498 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002499
Steve Frenche30dcf32005-09-20 20:49:16 -07002500cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002502 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 return rc;
2504}
2505
Jeff Layton0510eeb2008-08-02 07:26:12 -04002506int
2507cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2508{
Al Virofc640052016-04-10 01:33:30 -04002509 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002510 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002511
2512 if (pTcon->unix_ext)
2513 return cifs_setattr_unix(direntry, attrs);
2514
2515 return cifs_setattr_nounix(direntry, attrs);
2516
2517 /* BB: add cifs_setattr_legacy for really old servers */
2518}
2519
Steve French99ee4db2007-02-27 05:35:17 +00002520#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521void cifs_delete_inode(struct inode *inode)
2522{
Joe Perchesf96637b2013-05-04 22:12:25 -05002523 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 /* may have to add back in if and when safe distributed caching of
2525 directories added e.g. via FindNotify */
2526}
Steve French99ee4db2007-02-27 05:35:17 +00002527#endif