blob: 9b547f7f5f5d670d1d409a8e60988550fa7650e9 [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 */
Deepa Dinamani69738cf2019-11-29 21:30:25 -0800166 if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime) < 0)
Steve French9b9c5be2018-09-22 12:07:06 -0500167 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;
Steve French97aa4952018-11-15 00:33:05 -0600336 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)) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -0700417 CIFS_I(*pinode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900418 rc = -ESTALE;
419 goto cgiiu_exit;
420 }
421
422 /* if filetype is different, return error */
423 if (unlikely(((*pinode)->i_mode & S_IFMT) !=
424 (fattr.cf_mode & S_IFMT))) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -0700425 CIFS_I(*pinode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900426 rc = -ESTALE;
427 goto cgiiu_exit;
428 }
429
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400430 cifs_fattr_to_inode(*pinode, &fattr);
431 }
Steve French0e4bbde2008-05-20 19:50:46 +0000432
Nakajima Akira7196ac12015-04-22 15:24:44 +0900433cgiiu_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 return rc;
435}
436
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400437static int
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400438cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400439 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800440{
441 int rc;
Steve Frenchdb8b6312014-09-22 05:13:55 -0500442 __u32 oplock;
Jeff Layton7ffec372010-09-29 19:51:11 -0400443 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000444 struct cifs_tcon *tcon;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400445 struct cifs_fid fid;
446 struct cifs_open_parms oparms;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000447 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800448 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800449 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000450 char *pbuf;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400451 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800452
453 pbuf = buf;
454
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400455 fattr->cf_mode &= ~S_IFMT;
456
457 if (fattr->cf_eof == 0) {
458 fattr->cf_mode |= S_IFIFO;
459 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800460 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400461 } else if (fattr->cf_eof < 8) {
462 fattr->cf_mode |= S_IFREG;
463 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800464 return -EINVAL; /* EOPNOTSUPP? */
465 }
Steve French50c2f752007-07-13 00:33:32 +0000466
Jeff Layton7ffec372010-09-29 19:51:11 -0400467 tlink = cifs_sb_tlink(cifs_sb);
468 if (IS_ERR(tlink))
469 return PTR_ERR(tlink);
470 tcon = tlink_tcon(tlink);
471
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400472 oparms.tcon = tcon;
473 oparms.cifs_sb = cifs_sb;
474 oparms.desired_access = GENERIC_READ;
475 oparms.create_options = CREATE_NOT_DIR;
Steve French5e196972018-08-27 17:04:13 -0500476 if (backup_cred(cifs_sb))
477 oparms.create_options |= CREATE_OPEN_BACKUP_INTENT;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400478 oparms.disposition = FILE_OPEN;
479 oparms.path = path;
480 oparms.fid = &fid;
481 oparms.reconnect = false;
482
Steve Frenchdb8b6312014-09-22 05:13:55 -0500483 if (tcon->ses->server->oplocks)
484 oplock = REQ_OPLOCK;
485 else
486 oplock = 0;
487 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400488 if (rc) {
Steve Frenchdb8b6312014-09-22 05:13:55 -0500489 cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400490 cifs_put_tlink(tlink);
491 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800492 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400493
494 /* Read header */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400495 io_parms.netfid = fid.netfid;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400496 io_parms.pid = current->tgid;
497 io_parms.tcon = tcon;
498 io_parms.offset = 0;
499 io_parms.length = 24;
500
Steve Frenchdb8b6312014-09-22 05:13:55 -0500501 rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
502 &bytes_read, &pbuf, &buf_type);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400503 if ((rc == 0) && (bytes_read >= 8)) {
504 if (memcmp("IntxBLK", pbuf, 8) == 0) {
505 cifs_dbg(FYI, "Block device\n");
506 fattr->cf_mode |= S_IFBLK;
507 fattr->cf_dtype = DT_BLK;
508 if (bytes_read == 24) {
509 /* we have enough to decode dev num */
510 __u64 mjr; /* major */
511 __u64 mnr; /* minor */
512 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
513 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
514 fattr->cf_rdev = MKDEV(mjr, mnr);
515 }
516 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
517 cifs_dbg(FYI, "Char device\n");
518 fattr->cf_mode |= S_IFCHR;
519 fattr->cf_dtype = DT_CHR;
520 if (bytes_read == 24) {
521 /* we have enough to decode dev num */
522 __u64 mjr; /* major */
523 __u64 mnr; /* minor */
524 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
525 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
526 fattr->cf_rdev = MKDEV(mjr, mnr);
527 }
528 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
529 cifs_dbg(FYI, "Symlink\n");
530 fattr->cf_mode |= S_IFLNK;
531 fattr->cf_dtype = DT_LNK;
532 } else {
533 fattr->cf_mode |= S_IFREG; /* file? */
534 fattr->cf_dtype = DT_REG;
535 rc = -EOPNOTSUPP;
536 }
537 } else {
538 fattr->cf_mode |= S_IFREG; /* then it is a file */
539 fattr->cf_dtype = DT_REG;
540 rc = -EOPNOTSUPP; /* or some unknown SFU type */
541 }
Steve Frenchdb8b6312014-09-22 05:13:55 -0500542
543 tcon->ses->server->ops->close(xid, tcon, &fid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400544 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800545 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800546}
547
Steve French9e294f12005-11-17 16:59:21 -0800548#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
549
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400550/*
551 * Fetch mode bits as provided by SFU.
552 *
553 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
554 */
555static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400556 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800557{
Steve French3020a1f2005-11-18 11:31:10 -0800558#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800559 ssize_t rc;
560 char ea_value[4];
561 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400562 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000563 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800564
Jeff Layton7ffec372010-09-29 19:51:11 -0400565 tlink = cifs_sb_tlink(cifs_sb);
566 if (IS_ERR(tlink))
567 return PTR_ERR(tlink);
568 tcon = tlink_tcon(tlink);
569
Steve Frenchd979f3b2014-02-01 23:27:18 -0600570 if (tcon->ses->server->ops->query_all_EAs == NULL) {
571 cifs_put_tlink(tlink);
572 return -EOPNOTSUPP;
573 }
574
575 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
576 "SETFILEBITS", ea_value, 4 /* size of buf */,
Steve French67b4c882017-05-12 20:59:10 -0500577 cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400578 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000579 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800580 return (int)rc;
581 else if (rc > 3) {
582 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400583 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500584 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
585 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400586 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500587 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800588 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400589
590 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800591#else
592 return -EOPNOTSUPP;
593#endif
Steve French9e294f12005-11-17 16:59:21 -0800594}
595
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400596/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000597static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400598cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700599 struct super_block *sb, bool adjust_tz,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400600 bool symlink)
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000601{
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700602 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French96daf2b2011-05-27 04:34:02 +0000603 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700604
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400605 memset(fattr, 0, sizeof(*fattr));
606 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
607 if (info->DeletePending)
608 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000609
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400610 if (info->LastAccessTime)
611 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700612 else {
Arnd Bergmann95390202018-06-19 17:27:58 +0200613 ktime_get_real_ts64(&fattr->cf_atime);
614 fattr->cf_atime = timespec64_trunc(fattr->cf_atime, sb->s_time_gran);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700615 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400616
617 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
618 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
619
620 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700621 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
622 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400623 }
624
625 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
626 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500627 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400628
Jim McDonough74d290d2013-09-21 10:36:10 -0500629 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400630
631 if (symlink) {
632 fattr->cf_mode = S_IFLNK;
633 fattr->cf_dtype = DT_LNK;
634 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400635 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
636 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300637 /*
638 * Server can return wrong NumberOfLinks value for directories
639 * when Unix extensions are disabled - fake it.
640 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500641 if (!tcon->unix_ext)
642 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400643 } else {
644 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
645 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400646
Jeff Laytond0c280d2009-07-09 01:46:44 -0400647 /* clear write bits if ATTR_READONLY is set */
648 if (fattr->cf_cifsattrs & ATTR_READONLY)
649 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400650
Jim McDonough74d290d2013-09-21 10:36:10 -0500651 /*
652 * Don't accept zero nlink from non-unix servers unless
653 * delete is pending. Instead mark it as unknown.
654 */
655 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
656 !info->DeletePending) {
657 cifs_dbg(1, "bogus file nlink value %u\n",
Steve French6658b9f2013-07-04 14:38:48 -0500658 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500659 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500660 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300661 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400662
663 fattr->cf_uid = cifs_sb->mnt_uid;
664 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000665}
666
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700667static int
668cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500669{
670 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400671 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500672 FILE_ALL_INFO find_data;
673 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500674 struct inode *inode = file_inode(filp);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700675 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000676 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700677 struct TCP_Server_Info *server = tcon->ses->server;
678
679 if (!server->ops->query_file_info)
680 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500681
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400682 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700683 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400684 switch (rc) {
685 case 0:
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700686 cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400687 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400688 break;
689 case -EREMOTE:
690 cifs_create_dfs_fattr(&fattr, inode->i_sb);
691 rc = 0;
692 break;
693 case -EOPNOTSUPP:
694 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500695 /*
696 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000697 * for now, just skip revalidating and mark inode for
698 * immediate reval.
699 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500700 rc = 0;
701 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400702 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500703 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400704 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500705
706 /*
707 * don't bother with SFU junk here -- just mark inode as needing
708 * revalidation.
709 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500710 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
711 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
712 cifs_fattr_to_inode(inode, &fattr);
713cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400714 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500715 return rc;
716}
717
Steve French7ea884c2018-03-31 18:13:38 -0500718/* Simple function to return a 64 bit hash of string. Rarely called */
719static __u64 simple_hashstr(const char *str)
720{
Geert Uytterhoeven3995bbf2018-04-05 14:57:11 +0200721 const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
Steve French7ea884c2018-03-31 18:13:38 -0500722 __u64 hash = 0;
723
724 while (*str)
725 hash = (hash + (__u64) *str++) * hash_mult;
726
727 return hash;
728}
729
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100730/**
731 * cifs_backup_query_path_info - SMB1 fallback code to get ino
732 *
733 * Fallback code to get file metadata when we don't have access to
734 * @full_path (EACCESS) and have backup creds.
735 *
736 * @data will be set to search info result buffer
737 * @resp_buf will be set to cifs resp buf and needs to be freed with
738 * cifs_buf_release() when done with @data.
739 */
740static int
741cifs_backup_query_path_info(int xid,
742 struct cifs_tcon *tcon,
743 struct super_block *sb,
744 const char *full_path,
745 void **resp_buf,
746 FILE_ALL_INFO **data)
747{
748 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
749 struct cifs_search_info info = {0};
750 u16 flags;
751 int rc;
752
753 *resp_buf = NULL;
754 info.endOfSearch = false;
755 if (tcon->unix_ext)
756 info.info_level = SMB_FIND_FILE_UNIX;
757 else if ((tcon->ses->capabilities &
758 tcon->ses->server->vals->cap_nt_find) == 0)
759 info.info_level = SMB_FIND_FILE_INFO_STANDARD;
760 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
761 info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
762 else /* no srvino useful for fallback to some netapp */
763 info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
764
765 flags = CIFS_SEARCH_CLOSE_ALWAYS |
766 CIFS_SEARCH_CLOSE_AT_END |
767 CIFS_SEARCH_BACKUP_SEARCH;
768
769 rc = CIFSFindFirst(xid, tcon, full_path,
770 cifs_sb, NULL, flags, &info, false);
771 if (rc)
772 return rc;
773
774 *resp_buf = (void *)info.ntwrk_buf_start;
775 *data = (FILE_ALL_INFO *)info.srch_entries_start;
776 return 0;
777}
778
779static void
780cifs_set_fattr_ino(int xid,
781 struct cifs_tcon *tcon,
782 struct super_block *sb,
783 struct inode **inode,
784 const char *full_path,
785 FILE_ALL_INFO *data,
786 struct cifs_fattr *fattr)
787{
788 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
789 struct TCP_Server_Info *server = tcon->ses->server;
790 int rc;
791
792 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
793 if (*inode)
794 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
795 else
796 fattr->cf_uniqueid = iunique(sb, ROOT_I);
797 return;
798 }
799
800 /*
801 * If we have an inode pass a NULL tcon to ensure we don't
802 * make a round trip to the server. This only works for SMB2+.
803 */
804 rc = server->ops->get_srv_inum(xid,
805 *inode ? NULL : tcon,
806 cifs_sb, full_path,
807 &fattr->cf_uniqueid,
808 data);
809 if (rc) {
810 /*
811 * If that fails reuse existing ino or generate one
812 * and disable server ones
813 */
814 if (*inode)
815 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
816 else {
817 fattr->cf_uniqueid = iunique(sb, ROOT_I);
818 cifs_autodisable_serverino(cifs_sb);
819 }
820 return;
821 }
822
823 /* If no errors, check for zero root inode (invalid) */
824 if (fattr->cf_uniqueid == 0 && strlen(full_path) == 0) {
825 cifs_dbg(FYI, "Invalid (0) inodenum\n");
826 if (*inode) {
827 /* reuse */
828 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
829 } else {
830 /* make an ino by hashing the UNC */
831 fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
832 fattr->cf_uniqueid = simple_hashstr(tcon->treeName);
833 }
834 }
835}
836
837static inline bool is_inode_cache_good(struct inode *ino)
838{
839 return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;
840}
841
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400842int
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100843cifs_get_inode_info(struct inode **inode,
844 const char *full_path,
845 FILE_ALL_INFO *in_data,
846 struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600847 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848{
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100849
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400850 struct cifs_tcon *tcon;
851 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400852 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400854 bool adjust_tz = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100855 struct cifs_fattr fattr = {0};
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400856 bool symlink = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100857 FILE_ALL_INFO *data = in_data;
858 FILE_ALL_INFO *tmp_data = NULL;
859 void *smb1_backup_rsp_buf = NULL;
860 int rc = 0;
861 int tmprc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
Jeff Layton7ffec372010-09-29 19:51:11 -0400863 tlink = cifs_sb_tlink(cifs_sb);
864 if (IS_ERR(tlink))
865 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400866 tcon = tlink_tcon(tlink);
867 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400868
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100869 /*
870 * 1. Fetch file metadata if not provided (data)
871 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100873 if (!data) {
874 if (is_inode_cache_good(*inode)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500875 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100876 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100878 tmp_data = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
879 if (!tmp_data) {
Jeff Layton7ffec372010-09-29 19:51:11 -0400880 rc = -ENOMEM;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100881 goto out;
Jeff Layton7ffec372010-09-29 19:51:11 -0400882 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100883 rc = server->ops->query_path_info(xid, tcon, cifs_sb,
884 full_path, tmp_data,
885 &adjust_tz, &symlink);
886 data = tmp_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400888
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400889 /*
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100890 * 2. Convert it to internal cifs metadata (fattr)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400891 */
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100892
893 switch (rc) {
894 case 0:
895 cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
896 break;
897 case -EREMOTE:
898 /* DFS link, no metadata available on this server */
899 cifs_create_dfs_fattr(&fattr, sb);
900 rc = 0;
901 break;
902 case -EACCES:
903 /*
904 * perm errors, try again with backup flags if possible
905 *
906 * For SMB2 and later the backup intent flag
907 * is already sent if needed on open and there
908 * is no path based FindFirst operation to use
909 * to retry with
910 */
911 if (backup_cred(cifs_sb) && is_smb1_server(server)) {
912 /* for easier reading */
913 FILE_DIRECTORY_INFO *fdi;
914 SEARCH_ID_FULL_DIR_INFO *si;
915
916 rc = cifs_backup_query_path_info(xid, tcon, sb,
917 full_path,
918 &smb1_backup_rsp_buf,
919 &data);
920 if (rc)
921 goto out;
922
923 fdi = (FILE_DIRECTORY_INFO *)data;
924 si = (SEARCH_ID_FULL_DIR_INFO *)data;
925
926 cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb);
927 fattr.cf_uniqueid = le64_to_cpu(si->UniqueId);
928 /* uniqueid set, skip get inum step */
929 goto handle_mnt_opt;
930 } else {
931 /* nothing we can do, bail out */
932 goto out;
933 }
934 break;
935 default:
936 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
937 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000938 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000939
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100940 /*
941 * 3. Get or update inode number (fattr.cf_uniqueid)
942 */
943
944 cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);
945
946 /*
947 * 4. Tweak fattr based on mount options
948 */
949
950handle_mnt_opt:
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400951 /* query for SFU type info if supported and needed */
952 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
953 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
954 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
955 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500956 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000957 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000958
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000959 /* fill in 0777 bits from ACL */
Steve Frenche2f8fbf2019-07-19 06:30:07 +0000960 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
961 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
962 full_path, fid);
963 if (rc) {
964 cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100965 __func__, rc);
966 goto out;
Steve Frenche2f8fbf2019-07-19 06:30:07 +0000967 }
968 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
969 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
Dan Carpenter via samba-technical68464b82019-11-26 15:11:15 +0300970 full_path, fid);
971 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500972 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
973 __func__, rc);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100974 goto out;
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600975 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000976 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400977
978 /* fill in remaining high mode bits e.g. SUID, VTX */
979 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
980 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
981
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200982 /* check for Minshall+French symlinks */
983 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000984 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
985 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200986 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000987 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200988 }
989
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100990 /*
991 * 5. Update inode with final fattr data
992 */
993
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400994 if (!*inode) {
995 *inode = cifs_iget(sb, &fattr);
996 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400997 rc = -ENOMEM;
998 } else {
Nakajima Akira7196ac12015-04-22 15:24:44 +0900999 /* we already have inode, update it */
1000
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001001 /* if uniqueid is different, return error */
1002 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1003 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001004 CIFS_I(*inode)->time = 0; /* force reval */
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001005 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001006 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001007 }
1008
Nakajima Akira7196ac12015-04-22 15:24:44 +09001009 /* if filetype is different, return error */
1010 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1011 (fattr.cf_mode & S_IFMT))) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001012 CIFS_I(*inode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +09001013 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001014 goto out;
Nakajima Akira7196ac12015-04-22 15:24:44 +09001015 }
1016
Pavel Shilovsky1208ef12012-05-27 17:34:43 +04001017 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001018 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001019out:
1020 cifs_buf_release(smb1_backup_rsp_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001021 cifs_put_tlink(tlink);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001022 kfree(tmp_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 return rc;
1024}
1025
Steve French7f8ed422007-09-28 22:28:55 +00001026static const struct inode_operations cifs_ipc_inode_ops = {
1027 .lookup = cifs_lookup,
1028};
1029
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001030static int
1031cifs_find_inode(struct inode *inode, void *opaque)
1032{
1033 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1034
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001035 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001036 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
1037 return 0;
1038
Jeff Layton20054bd2011-01-07 11:30:27 -05001039 /* use createtime like an i_generation field */
1040 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
1041 return 0;
1042
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001043 /* don't match inode of different type */
1044 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
1045 return 0;
1046
Jeff Layton5acfec22010-08-02 17:43:54 -04001047 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -04001048 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -04001049 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -04001050
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001051 return 1;
1052}
1053
1054static int
1055cifs_init_inode(struct inode *inode, void *opaque)
1056{
1057 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1058
1059 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -05001060 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001061 return 0;
1062}
1063
Jeff Layton5acfec22010-08-02 17:43:54 -04001064/*
1065 * walk dentry list for an inode and report whether it has aliases that
1066 * are hashed. We use this to determine if a directory inode can actually
1067 * be used.
1068 */
1069static bool
1070inode_has_hashed_dentries(struct inode *inode)
1071{
1072 struct dentry *dentry;
1073
Nick Piggin873feea2011-01-07 17:50:06 +11001074 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -04001075 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001076 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +11001077 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001078 return true;
1079 }
1080 }
Nick Piggin873feea2011-01-07 17:50:06 +11001081 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001082 return false;
1083}
1084
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001085/* Given fattrs, get a corresponding inode */
1086struct inode *
1087cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
1088{
1089 unsigned long hash;
1090 struct inode *inode;
1091
Jeff Layton3d694382010-05-11 14:59:55 -04001092retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -05001093 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001094
1095 /* hash down to 32-bits on 32-bit arch */
1096 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
1097
1098 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001099 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001100 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -04001101 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -04001102 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -04001103
1104 if (inode_has_hashed_dentries(inode)) {
1105 cifs_autodisable_serverino(CIFS_SB(sb));
1106 iput(inode);
1107 fattr->cf_uniqueid = iunique(sb, ROOT_I);
1108 goto retry_iget5_locked;
1109 }
Jeff Layton3d694382010-05-11 14:59:55 -04001110 }
1111
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001112 cifs_fattr_to_inode(inode, fattr);
Linus Torvalds1751e8a2017-11-27 13:05:09 -08001113 if (sb->s_flags & SB_NOATIME)
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001114 inode->i_flags |= S_NOATIME | S_NOCMTIME;
1115 if (inode->i_state & I_NEW) {
1116 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +00001117#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301118 /* initialize per-inode cache cookie pointer */
1119 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +00001120#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001121 unlock_new_inode(inode);
1122 }
1123 }
1124
1125 return inode;
1126}
1127
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001129struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001131 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001132 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001133 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001134 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001135 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001136 char *path = NULL;
1137 int len;
1138
1139 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1140 && cifs_sb->prepath) {
1141 len = strlen(cifs_sb->prepath);
1142 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1143 if (path == NULL)
1144 return ERR_PTR(-ENOMEM);
1145 path[0] = '/';
1146 memcpy(path+1, cifs_sb->prepath, len);
1147 } else {
1148 path = kstrdup("", GFP_KERNEL);
1149 if (path == NULL)
1150 return ERR_PTR(-ENOMEM);
1151 }
David Howellsce634ab2008-02-07 00:15:33 -08001152
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001153 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001154 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001155 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001156 /* some servers mistakenly claim POSIX support */
1157 if (rc != -EOPNOTSUPP)
1158 goto iget_no_retry;
1159 cifs_dbg(VFS, "server does not support POSIX extensions");
1160 tcon->unix_ext = false;
1161 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001162
Aurelien Aptela6b50582016-05-25 19:59:09 +02001163 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
1164 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001165
1166iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001167 if (!inode) {
1168 inode = ERR_PTR(rc);
1169 goto out;
1170 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001171
Steve French0ccd4802010-07-16 04:31:02 +00001172#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301173 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001174 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001175#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301176
Aurelien Aptelb327a712018-01-24 13:46:10 +01001177 if (rc && tcon->pipe) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001178 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001179 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001180 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001181 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001182 inode->i_op = &cifs_ipc_inode_ops;
1183 inode->i_fop = &simple_dir_operations;
1184 inode->i_uid = cifs_sb->mnt_uid;
1185 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001186 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001187 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001188 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001189 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001190 }
1191
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001192out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001193 kfree(path);
Phillip Potter31cd1062018-03-17 21:06:56 +00001194 free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001195 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196}
1197
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001198int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001199cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001200 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001201{
Steve French388e57b2008-09-16 23:50:58 +00001202 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001203 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001204 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001205 FILE_BASIC_INFO info_buf;
1206
Steve French1adcb712009-02-25 14:19:56 +00001207 if (attrs == NULL)
1208 return -EINVAL;
1209
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001210 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1211 if (!server->ops->set_file_info)
1212 return -ENOSYS;
1213
Steve Frenchfd09b7d2018-08-02 20:28:18 -05001214 info_buf.Pad = 0;
1215
Steve French388e57b2008-09-16 23:50:58 +00001216 if (attrs->ia_valid & ATTR_ATIME) {
1217 set_time = true;
1218 info_buf.LastAccessTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001219 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
Steve French388e57b2008-09-16 23:50:58 +00001220 } else
1221 info_buf.LastAccessTime = 0;
1222
1223 if (attrs->ia_valid & ATTR_MTIME) {
1224 set_time = true;
1225 info_buf.LastWriteTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001226 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
Steve French388e57b2008-09-16 23:50:58 +00001227 } else
1228 info_buf.LastWriteTime = 0;
1229
1230 /*
1231 * Samba throws this field away, but windows may actually use it.
1232 * Do not set ctime unless other time stamps are changed explicitly
1233 * (i.e. by utimes()) since we would then have a mix of client and
1234 * server times.
1235 */
1236 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001237 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001238 info_buf.ChangeTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001239 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
Steve French388e57b2008-09-16 23:50:58 +00001240 } else
1241 info_buf.ChangeTime = 0;
1242
1243 info_buf.CreationTime = 0; /* don't change */
1244 info_buf.Attributes = cpu_to_le32(dosattr);
1245
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001246 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001247}
1248
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001249/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001250 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001251 * and rename it to a random name that hopefully won't conflict with
1252 * anything else.
1253 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001254int
1255cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1256 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001257{
1258 int oplock = 0;
1259 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001260 struct cifs_fid fid;
1261 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001262 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001263 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1264 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001265 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001266 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001267 __u32 dosattr, origattr;
1268 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001269
Jeff Layton7ffec372010-09-29 19:51:11 -04001270 tlink = cifs_sb_tlink(cifs_sb);
1271 if (IS_ERR(tlink))
1272 return PTR_ERR(tlink);
1273 tcon = tlink_tcon(tlink);
1274
Sachin Prabhuc483a982013-03-05 19:25:56 +00001275 /*
1276 * We cannot rename the file if the server doesn't support
1277 * CAP_INFOLEVEL_PASSTHRU
1278 */
1279 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1280 rc = -EBUSY;
1281 goto out;
1282 }
1283
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001284 oparms.tcon = tcon;
1285 oparms.cifs_sb = cifs_sb;
1286 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1287 oparms.create_options = CREATE_NOT_DIR;
1288 oparms.disposition = FILE_OPEN;
1289 oparms.path = full_path;
1290 oparms.fid = &fid;
1291 oparms.reconnect = false;
1292
1293 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001294 if (rc != 0)
1295 goto out;
1296
Steve French32709582008-10-20 00:44:19 +00001297 origattr = cifsInode->cifsAttrs;
1298 if (origattr == 0)
1299 origattr |= ATTR_NORMAL;
1300
1301 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001302 if (dosattr == 0)
1303 dosattr |= ATTR_NORMAL;
1304 dosattr |= ATTR_HIDDEN;
1305
Steve French32709582008-10-20 00:44:19 +00001306 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1307 if (dosattr != origattr) {
1308 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1309 if (info_buf == NULL) {
1310 rc = -ENOMEM;
1311 goto out_close;
1312 }
1313 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001314 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001315 current->tgid);
1316 /* although we would like to mark the file hidden
1317 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001318 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001319 cifsInode->cifsAttrs = dosattr;
1320 else
1321 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001322 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001323
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001324 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001325 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1326 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001327 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001328 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001329 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001330 goto undo_setattr;
1331 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001332
Steve French32709582008-10-20 00:44:19 +00001333 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001334 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001335 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001336 current->tgid);
1337 /*
1338 * some samba versions return -ENOENT when we try to set the
1339 * file disposition here. Likely a samba bug, but work around
1340 * it for now. This means that some cifsXXX files may hang
1341 * around after they shouldn't.
1342 *
1343 * BB: remove this hack after more servers have the fix
1344 */
1345 if (rc == -ENOENT)
1346 rc = 0;
1347 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001348 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001349 goto undo_rename;
1350 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001351 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001352 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001353
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001354out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001355 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001356out:
Steve French32709582008-10-20 00:44:19 +00001357 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001358 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001359 return rc;
Steve French32709582008-10-20 00:44:19 +00001360
1361 /*
1362 * reset everything back to the original state. Don't bother
1363 * dealing with errors here since we can't do anything about
1364 * them anyway.
1365 */
1366undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001367 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001368 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001369undo_setattr:
1370 if (dosattr != origattr) {
1371 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001372 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001373 current->tgid))
1374 cifsInode->cifsAttrs = origattr;
1375 }
1376
1377 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001378}
1379
Steve Frenchb7ca6922012-08-03 08:43:01 -05001380/* copied from fs/nfs/dir.c with small changes */
1381static void
1382cifs_drop_nlink(struct inode *inode)
1383{
1384 spin_lock(&inode->i_lock);
1385 if (inode->i_nlink > 0)
1386 drop_nlink(inode);
1387 spin_unlock(&inode->i_lock);
1388}
Steve Frenchff694522009-04-20 19:45:13 +00001389
1390/*
David Howells2b0143b2015-03-17 22:25:59 +00001391 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001392 * is a negative dentry) then we would attempt a standard SMB delete, but
Colin Ian King413d6102018-10-26 19:07:21 +01001393 * if that fails we can not attempt the fall back mechanisms on EACCES
1394 * but will return the EACCES to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001395 * unlink on negative dentries currently.
1396 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001397int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398{
1399 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001400 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001402 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001403 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001404 struct super_block *sb = dir->i_sb;
1405 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001406 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001407 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001408 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001409 struct iattr *attrs = NULL;
1410 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
Joe Perchesf96637b2013-05-04 22:12:25 -05001412 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Jeff Layton7ffec372010-09-29 19:51:11 -04001414 tlink = cifs_sb_tlink(cifs_sb);
1415 if (IS_ERR(tlink))
1416 return PTR_ERR(tlink);
1417 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001418 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001419
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001420 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421
Jeff Layton5f0319a2008-09-16 14:05:16 -04001422 /* Unlink can be called from rename so we can not take the
1423 * sb->s_vfs_rename_mutex here */
1424 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301426 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001427 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 }
Steve French2d785a52007-07-15 01:48:57 +00001429
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001430 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1431 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001432 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001433 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001434 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001435 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001436 if ((rc == 0) || (rc == -ENOENT))
1437 goto psx_del_no_retry;
1438 }
1439
Steve French60502472008-10-07 18:42:52 +00001440retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001441 if (!server->ops->unlink) {
1442 rc = -ENOSYS;
1443 goto psx_del_no_retry;
1444 }
1445
1446 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001447
Steve French2d785a52007-07-15 01:48:57 +00001448psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001450 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001451 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001453 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001454 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001455 if (server->ops->rename_pending_delete) {
1456 rc = server->ops->rename_pending_delete(full_path,
1457 dentry, xid);
1458 if (rc == 0)
1459 cifs_drop_nlink(inode);
1460 }
Steve Frenchff694522009-04-20 19:45:13 +00001461 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001462 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1463 if (attrs == NULL) {
1464 rc = -ENOMEM;
1465 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 }
Steve French388e57b2008-09-16 23:50:58 +00001467
1468 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001469 cifs_inode = CIFS_I(inode);
1470 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001471 if (origattr == 0)
1472 origattr |= ATTR_NORMAL;
1473 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001474 if (dosattr == 0)
1475 dosattr |= ATTR_NORMAL;
1476 dosattr |= ATTR_HIDDEN;
1477
1478 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001479 if (rc != 0)
1480 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001481
1482 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 }
Steve French60502472008-10-07 18:42:52 +00001484
1485 /* undo the setattr if we errored out and it's needed */
1486 if (rc != 0 && dosattr != 0)
1487 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1488
Steve French388e57b2008-09-16 23:50:58 +00001489out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001490 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001491 cifs_inode = CIFS_I(inode);
1492 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001493 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001494 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001495 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001496 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001497 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001498 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001499unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001501 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001502 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001503 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 return rc;
1505}
1506
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001507static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001508cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001509 const char *full_path, struct cifs_sb_info *cifs_sb,
1510 struct cifs_tcon *tcon, const unsigned int xid)
1511{
1512 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001513 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001514
1515 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001516 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001517 xid);
1518 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001519 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1520 xid, NULL);
1521
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001522 if (rc)
1523 return rc;
1524
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001525 /*
1526 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001527 * from the server or was set bogus. Also, since this is a brand new
1528 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001529 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001530 if (inode->i_nlink < 2)
1531 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001532 mode &= ~current_umask();
1533 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001534 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001535 mode |= S_ISGID;
1536
1537 if (tcon->unix_ext) {
1538 struct cifs_unix_set_info_args args = {
1539 .mode = mode,
1540 .ctime = NO_CHANGE_64,
1541 .atime = NO_CHANGE_64,
1542 .mtime = NO_CHANGE_64,
1543 .device = 0,
1544 };
1545 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001546 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001547 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001548 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001549 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001550 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001551 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001552 args.uid = INVALID_UID; /* no change */
1553 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001554 }
1555 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1556 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001557 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001558 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001559 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001560 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001561 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001562 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001563 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001564 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1565 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001566
Jeff Layton101b92d2012-09-19 06:22:45 -07001567 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1568 inode->i_uid = current_fsuid();
1569 if (inode->i_mode & S_ISGID)
1570 inode->i_gid = parent->i_gid;
1571 else
1572 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001573 }
1574 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001575 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001576 return rc;
1577}
1578
1579static int
1580cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1581 const char *full_path, struct cifs_sb_info *cifs_sb,
1582 struct cifs_tcon *tcon, const unsigned int xid)
1583{
1584 int rc = 0;
1585 u32 oplock = 0;
1586 FILE_UNIX_BASIC_INFO *info = NULL;
1587 struct inode *newinode = NULL;
1588 struct cifs_fattr fattr;
1589
1590 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1591 if (info == NULL) {
1592 rc = -ENOMEM;
1593 goto posix_mkdir_out;
1594 }
1595
1596 mode &= ~current_umask();
1597 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1598 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001599 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001600 if (rc == -EOPNOTSUPP)
1601 goto posix_mkdir_out;
1602 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001603 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001604 d_drop(dentry);
1605 goto posix_mkdir_out;
1606 }
1607
1608 if (info->Type == cpu_to_le32(-1))
1609 /* no return info, go query for it */
1610 goto posix_mkdir_get_info;
1611 /*
1612 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1613 * need to set uid/gid.
1614 */
1615
1616 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1617 cifs_fill_uniqueid(inode->i_sb, &fattr);
1618 newinode = cifs_iget(inode->i_sb, &fattr);
1619 if (!newinode)
1620 goto posix_mkdir_get_info;
1621
1622 d_instantiate(dentry, newinode);
1623
1624#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001625 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1626 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001627
1628 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001629 cifs_dbg(FYI, "unexpected number of links %d\n",
1630 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001631#endif
1632
1633posix_mkdir_out:
1634 kfree(info);
1635 return rc;
1636posix_mkdir_get_info:
1637 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1638 xid);
1639 goto posix_mkdir_out;
1640}
1641
Al Viro18bb1db2011-07-26 01:41:39 -04001642int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001644 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001645 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001647 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001648 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001649 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001650 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651
Joe Perchesf96637b2013-05-04 22:12:25 -05001652 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1653 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001656 tlink = cifs_sb_tlink(cifs_sb);
1657 if (IS_ERR(tlink))
1658 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001659 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001660
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001661 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662
Steve French7f573562005-08-30 11:32:14 -07001663 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301665 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001666 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 }
Steve French50c2f752007-07-13 00:33:32 +00001668
Steve Frenchbea851b2018-06-14 21:56:32 -05001669 server = tcon->ses->server;
1670
Steve Frenchbea851b2018-06-14 21:56:32 -05001671 if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
1672 rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
1673 cifs_sb);
1674 d_drop(direntry); /* for time being always refresh inode info */
1675 goto mkdir_out;
1676 }
Steve Frenchbea851b2018-06-14 21:56:32 -05001677
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001678 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1679 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001680 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1681 tcon, xid);
1682 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001683 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001684 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001685
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001686 if (!server->ops->mkdir) {
1687 rc = -ENOSYS;
1688 goto mkdir_out;
1689 }
1690
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001692 rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001694 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001696 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001698
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001699 /* TODO: skip this for smb2/smb3 */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001700 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1701 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001702mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001703 /*
1704 * Force revalidate to get parent dir info when needed since cached
1705 * attributes are invalid now.
1706 */
1707 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001709 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001710 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 return rc;
1712}
1713
1714int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1715{
1716 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001717 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001719 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001720 struct cifs_tcon *tcon;
1721 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 char *full_path = NULL;
1723 struct cifsInodeInfo *cifsInode;
1724
Joe Perchesf96637b2013-05-04 22:12:25 -05001725 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001727 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
Steve French7f573562005-08-30 11:32:14 -07001729 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301731 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001732 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 }
1734
Jeff Layton7ffec372010-09-29 19:51:11 -04001735 cifs_sb = CIFS_SB(inode->i_sb);
1736 tlink = cifs_sb_tlink(cifs_sb);
1737 if (IS_ERR(tlink)) {
1738 rc = PTR_ERR(tlink);
1739 goto rmdir_exit;
1740 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001741 tcon = tlink_tcon(tlink);
1742 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001743
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001744 if (!server->ops->rmdir) {
1745 rc = -ENOSYS;
1746 cifs_put_tlink(tlink);
1747 goto rmdir_exit;
1748 }
1749
1750 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001751 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
1753 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001754 spin_lock(&d_inode(direntry)->i_lock);
1755 i_size_write(d_inode(direntry), 0);
1756 clear_nlink(d_inode(direntry));
1757 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 }
1759
David Howells2b0143b2015-03-17 22:25:59 +00001760 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001761 /* force revalidate to go get info when needed */
1762 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001763
1764 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001765 /*
1766 * Force revalidate to get parent dir info when needed since cached
1767 * attributes are invalid now.
1768 */
1769 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001770
David Howells2b0143b2015-03-17 22:25:59 +00001771 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001772 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
Jeff Layton7ffec372010-09-29 19:51:11 -04001774rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001776 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 return rc;
1778}
1779
Steve Frenchee2fd962008-09-23 18:23:33 +00001780static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001781cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1782 const char *from_path, struct dentry *to_dentry,
1783 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001784{
1785 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001786 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001787 struct cifs_tcon *tcon;
1788 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001789 struct cifs_fid fid;
1790 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001791 int oplock, rc;
1792
Jeff Layton7ffec372010-09-29 19:51:11 -04001793 tlink = cifs_sb_tlink(cifs_sb);
1794 if (IS_ERR(tlink))
1795 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001796 tcon = tlink_tcon(tlink);
1797 server = tcon->ses->server;
1798
1799 if (!server->ops->rename)
1800 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001801
Steve Frenchee2fd962008-09-23 18:23:33 +00001802 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001803 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001804
1805 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001806 * Don't bother with rename by filehandle unless file is busy and
1807 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001808 * rename by filehandle to various Windows servers.
1809 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001810 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001811 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001812
Frank Sorenson652727b2019-04-16 08:37:27 -05001813 /* Don't fall back to using SMB on SMB 2+ mount */
1814 if (server->vals->protocol_id != 0)
1815 goto do_rename_exit;
1816
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001817 /* open-file renames don't work across directories */
1818 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001819 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001820
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001821 oparms.tcon = tcon;
1822 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00001823 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001824 oparms.desired_access = DELETE;
1825 oparms.create_options = CREATE_NOT_DIR;
1826 oparms.disposition = FILE_OPEN;
1827 oparms.path = from_path;
1828 oparms.fid = &fid;
1829 oparms.reconnect = false;
1830
1831 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00001832 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001833 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001834 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001835 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001836 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001837 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001838do_rename_exit:
1839 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001840 return rc;
1841}
1842
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001843int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001844cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
1845 struct inode *target_dir, struct dentry *target_dentry,
1846 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001848 char *from_name = NULL;
1849 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001850 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001851 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001852 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001853 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1854 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001855 unsigned int xid;
1856 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001858 if (flags & ~RENAME_NOREPLACE)
1859 return -EINVAL;
1860
Jeff Layton639e7a92010-09-03 11:50:09 -04001861 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001862 tlink = cifs_sb_tlink(cifs_sb);
1863 if (IS_ERR(tlink))
1864 return PTR_ERR(tlink);
1865 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001867 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001868
1869 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001870 * we already have the rename sem so we do not need to
1871 * grab it again here to protect the path integrity
1872 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001873 from_name = build_path_from_dentry(source_dentry);
1874 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 rc = -ENOMEM;
1876 goto cifs_rename_exit;
1877 }
1878
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001879 to_name = build_path_from_dentry(target_dentry);
1880 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001881 rc = -ENOMEM;
1882 goto cifs_rename_exit;
1883 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001885 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1886 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001887
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001888 /*
1889 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
1890 */
1891 if (flags & RENAME_NOREPLACE)
1892 goto cifs_rename_exit;
1893
Jeff Layton14121bd2008-10-20 14:45:22 -04001894 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001895 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001896 * Are src and dst hardlinks of same inode? We can only tell
1897 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001898 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001899 info_buf_source =
Kees Cook6da2ec52018-06-12 13:55:00 -07001900 kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
Jeff Layton14121bd2008-10-20 14:45:22 -04001901 GFP_KERNEL);
1902 if (info_buf_source == NULL) {
1903 rc = -ENOMEM;
1904 goto cifs_rename_exit;
1905 }
1906
1907 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001908 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1909 info_buf_source,
1910 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001911 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04001912 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001913 goto unlink_target;
1914
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001915 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1916 info_buf_target,
1917 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001918 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04001919
Jeff Layton8d281ef2008-10-22 13:57:01 -04001920 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001921 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001922 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001923 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001924 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001925 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001926 }
1927 /*
1928 * else ... BB we could add the same check for Windows by
1929 * checking the UniqueId via FILE_INTERNAL_INFO
1930 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001931
Jeff Layton14121bd2008-10-20 14:45:22 -04001932unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001933 /* Try unlinking the target dentry if it's not negative */
David Howells2b0143b2015-03-17 22:25:59 +00001934 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04001935 if (d_is_dir(target_dentry))
1936 tmprc = cifs_rmdir(target_dir, target_dentry);
1937 else
1938 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001939 if (tmprc)
1940 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001941 rc = cifs_do_rename(xid, source_dentry, from_name,
1942 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 }
1944
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001945 /* force revalidate to go get info when needed */
1946 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1947
1948 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001949 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001950
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001952 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001953 kfree(from_name);
1954 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001955 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001956 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 return rc;
1958}
1959
Jeff Laytondf2cf172010-02-12 07:44:16 -05001960static bool
1961cifs_inode_needs_reval(struct inode *inode)
1962{
1963 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301964 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001965
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10001966 if (cifs_i->time == 0)
1967 return true;
1968
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001969 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001970 return false;
1971
1972 if (!lookupCacheEnabled)
1973 return true;
1974
Jeff Laytona87c9ad2014-03-26 07:24:23 -07001975 if (!cifs_sb->actimeo)
1976 return true;
1977
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301978 if (!time_in_range(jiffies, cifs_i->time,
1979 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001980 return true;
1981
Jeff Laytondb192722010-05-17 14:51:49 -04001982 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301983 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001984 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1985 return true;
1986
Jeff Laytondf2cf172010-02-12 07:44:16 -05001987 return false;
1988}
1989
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301990/*
1991 * Zap the cache. Called when invalid_mapping flag is set.
1992 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001993int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001994cifs_invalidate_mapping(struct inode *inode)
1995{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001996 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001997
Jeff Laytondf2cf172010-02-12 07:44:16 -05001998 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001999 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002000 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05002001 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
2002 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002003 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002004
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05302005 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002006 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002007}
2008
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002009/**
2010 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
2011 * @word: long word containing the bit lock
2012 */
2013static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002014cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002015{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002016 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002017 if (signal_pending_state(mode, current))
2018 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002019 return 0;
2020}
2021
Jeff Laytone284e532014-04-30 09:31:46 -04002022int
2023cifs_revalidate_mapping(struct inode *inode)
2024{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002025 int rc;
2026 unsigned long *flags = &CIFS_I(inode)->flags;
2027
NeilBrown74316202014-07-07 15:16:04 +10002028 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
2029 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002030 if (rc)
2031 return rc;
2032
2033 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
2034 rc = cifs_invalidate_mapping(inode);
2035 if (rc)
2036 set_bit(CIFS_INO_INVALID_MAPPING, flags);
2037 }
2038
2039 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07002040 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002041 wake_up_bit(flags, CIFS_INO_LOCK);
2042
2043 return rc;
2044}
2045
2046int
2047cifs_zap_mapping(struct inode *inode)
2048{
2049 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
2050 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04002051}
2052
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002053int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05002054{
2055 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05002056 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba642010-09-20 16:01:31 -07002057 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05002058
2059 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002060 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05002061
Jeff Layton13cfb732010-09-29 19:51:11 -04002062 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05002063 rc = cifs_get_file_info_unix(filp);
2064 else
2065 rc = cifs_get_file_info(filp);
2066
Jeff Laytonabab0952010-02-12 07:44:18 -05002067 return rc;
2068}
2069
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002070int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002072 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002073 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00002074 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002075 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002076 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
Jeff Laytondf2cf172010-02-12 07:44:16 -05002078 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 return -ENOENT;
2080
Jeff Laytondf2cf172010-02-12 07:44:16 -05002081 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002082 return rc;
2083
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002084 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085
2086 /* can not safely grab the rename sem here if rename calls revalidate
2087 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05002088 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302090 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002091 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05002093
Joe Perchesf96637b2013-05-04 22:12:25 -05002094 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
2095 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02002096 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
Jeff Layton0d424ad2010-09-20 16:01:35 -07002098 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05002099 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
2100 else
2101 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
2102 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002104out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002106 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 return rc;
2108}
2109
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002110int cifs_revalidate_file(struct file *filp)
2111{
2112 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002113 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002114
2115 rc = cifs_revalidate_file_attr(filp);
2116 if (rc)
2117 return rc;
2118
Jeff Laytone284e532014-04-30 09:31:46 -04002119 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002120}
2121
2122/* revalidate a dentry's inode attributes */
2123int cifs_revalidate_dentry(struct dentry *dentry)
2124{
2125 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002126 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002127
2128 rc = cifs_revalidate_dentry_attr(dentry);
2129 if (rc)
2130 return rc;
2131
Jeff Laytone284e532014-04-30 09:31:46 -04002132 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002133}
2134
David Howellsa528d352017-01-31 16:46:22 +00002135int cifs_getattr(const struct path *path, struct kstat *stat,
2136 u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137{
David Howellsa528d352017-01-31 16:46:22 +00002138 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002139 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002140 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002141 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002142 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002143
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002144 /*
2145 * We need to be sure that all dirty pages are written and the server
2146 * has actual ctime, mtime and file length.
2147 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002148 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002149 inode->i_mapping->nrpages != 0) {
2150 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002151 if (rc) {
2152 mapping_set_error(inode->i_mapping, rc);
2153 return rc;
2154 }
Steve French5fe14c82006-11-07 19:26:33 +00002155 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002156
2157 rc = cifs_revalidate_dentry_attr(dentry);
2158 if (rc)
2159 return rc;
2160
2161 generic_fillattr(inode, stat);
Steve Frenche8506d22019-02-28 21:32:15 -06002162 stat->blksize = cifs_sb->bsize;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002163 stat->ino = CIFS_I(inode)->uniqueid;
2164
Steve French6e70e262017-09-21 21:32:29 -05002165 /* old CIFS Unix Extensions doesn't return create time */
2166 if (CIFS_I(inode)->createtime) {
2167 stat->result_mask |= STATX_BTIME;
Arnd Bergmann95390202018-06-19 17:27:58 +02002168 stat->btime =
2169 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
Steve French6e70e262017-09-21 21:32:29 -05002170 }
2171
2172 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2173 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2174 stat->attributes |= STATX_ATTR_COMPRESSED;
2175 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2176 stat->attributes |= STATX_ATTR_ENCRYPTED;
2177
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002178 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002179 * If on a multiuser mount without unix extensions or cifsacl being
2180 * enabled, and the admin hasn't overridden them, set the ownership
2181 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002182 */
2183 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002184 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002185 !tcon->unix_ext) {
2186 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2187 stat->uid = current_fsuid();
2188 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2189 stat->gid = current_fsgid();
2190 }
2191 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192}
2193
Ronnie Sahlberg2f3ebab2019-04-25 16:45:29 +10002194int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
2195 u64 len)
2196{
2197 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2198 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->vfs_inode.i_sb);
2199 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2200 struct TCP_Server_Info *server = tcon->ses->server;
2201 struct cifsFileInfo *cfile;
2202 int rc;
2203
2204 /*
2205 * We need to be sure that all dirty pages are written as they
2206 * might fill holes on the server.
2207 */
2208 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
2209 inode->i_mapping->nrpages != 0) {
2210 rc = filemap_fdatawait(inode->i_mapping);
2211 if (rc) {
2212 mapping_set_error(inode->i_mapping, rc);
2213 return rc;
2214 }
2215 }
2216
2217 cfile = find_readable_file(cifs_i, false);
2218 if (cfile == NULL)
2219 return -EINVAL;
2220
2221 if (server->ops->fiemap) {
2222 rc = server->ops->fiemap(tcon, cfile, fei, start, len);
2223 cifsFileInfo_put(cfile);
2224 return rc;
2225 }
2226
2227 cifsFileInfo_put(cfile);
2228 return -ENOTSUPP;
2229}
2230
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002231int cifs_truncate_page(struct address_space *mapping, loff_t from)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002233 pgoff_t index = from >> PAGE_SHIFT;
2234 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 int rc = 0;
2237
2238 page = grab_cache_page(mapping, index);
2239 if (!page)
2240 return -ENOMEM;
2241
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002242 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002244 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 return rc;
2246}
2247
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002248void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002249{
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002250 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2251
Steve Frenchba6a46a2007-02-26 20:06:29 +00002252 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002253 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002254 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002255
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002256 /* Cached inode must be refreshed on truncate */
2257 cifs_i->time = 0;
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002258 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002259}
2260
Jeff Layton8efdbde2008-07-23 21:28:12 +00002261static int
2262cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002263 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002264{
2265 int rc;
2266 struct cifsFileInfo *open_file;
2267 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2268 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002269 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002270 struct cifs_tcon *tcon = NULL;
2271 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002272
2273 /*
2274 * To avoid spurious oplock breaks from server, in the case of
2275 * inodes that we already have open, avoid doing path based
2276 * setting of file size if we can do it by handle.
2277 * This keeps our caching token (oplock) and avoids timeouts
2278 * when the local oplock break takes longer to flush
2279 * writebehind data than the SMB timeout for the SetPathInfo
2280 * request would allow
2281 */
Jeff Layton6508d902010-09-29 19:51:11 -04002282 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002283 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002284 tcon = tlink_tcon(open_file->tlink);
2285 server = tcon->ses->server;
2286 if (server->ops->set_file_size)
2287 rc = server->ops->set_file_size(xid, tcon, open_file,
2288 attrs->ia_size, false);
2289 else
2290 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002291 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002292 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002293 } else
2294 rc = -EINVAL;
2295
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002296 if (!rc)
2297 goto set_size_out;
Jeff Laytonba00ba642010-09-20 16:01:31 -07002298
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002299 if (tcon == NULL) {
2300 tlink = cifs_sb_tlink(cifs_sb);
2301 if (IS_ERR(tlink))
2302 return PTR_ERR(tlink);
2303 tcon = tlink_tcon(tlink);
2304 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002305 }
2306
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002307 /*
2308 * Set file size by pathname rather than by handle either because no
2309 * valid, writeable file handle for it was found or because there was
2310 * an error setting it by handle.
2311 */
2312 if (server->ops->set_path_size)
2313 rc = server->ops->set_path_size(xid, tcon, full_path,
2314 attrs->ia_size, cifs_sb, false);
2315 else
2316 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002317 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002318
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002319 if (tlink)
2320 cifs_put_tlink(tlink);
2321
2322set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002323 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002324 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002325 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002326 cifs_truncate_page(inode->i_mapping, inode->i_size);
2327 }
2328
2329 return rc;
2330}
2331
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002332static int
2333cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2334{
2335 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002336 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002337 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002338 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002339 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2340 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002341 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002342 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002343 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002344 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002345
Al Viro35c265e2014-08-19 20:25:34 -04002346 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2347 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002348
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002349 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002350
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002351 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2352 attrs->ia_valid |= ATTR_FORCE;
2353
Jan Kara31051c82016-05-26 16:55:18 +02002354 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002355 if (rc < 0)
2356 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002357
2358 full_path = build_path_from_dentry(direntry);
2359 if (full_path == NULL) {
2360 rc = -ENOMEM;
2361 goto out;
2362 }
2363
Jeff Layton0f4d6342009-03-26 13:35:37 -04002364 /*
2365 * Attempt to flush data before changing attributes. We need to do
2366 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2367 * ownership or mode then we may also need to do this. Here, we take
2368 * the safe way out and just do the flush on all setattr requests. If
2369 * the flush returns error, store it to report later and continue.
2370 *
2371 * BB: This should be smarter. Why bother flushing pages that
2372 * will be truncated anyway? Also, should we error out here if
2373 * the flush returns error?
2374 */
2375 rc = filemap_write_and_wait(inode->i_mapping);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002376 if (is_interrupt_error(rc)) {
2377 rc = -ERESTARTSYS;
2378 goto out;
2379 }
2380
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002381 mapping_set_error(inode->i_mapping, rc);
2382 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002383
2384 if (attrs->ia_valid & ATTR_SIZE) {
2385 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2386 if (rc != 0)
2387 goto out;
2388 }
2389
2390 /* skip mode change if it's just for clearing setuid/setgid */
2391 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2392 attrs->ia_valid &= ~ATTR_MODE;
2393
2394 args = kmalloc(sizeof(*args), GFP_KERNEL);
2395 if (args == NULL) {
2396 rc = -ENOMEM;
2397 goto out;
2398 }
2399
2400 /* set up the struct */
2401 if (attrs->ia_valid & ATTR_MODE)
2402 args->mode = attrs->ia_mode;
2403 else
2404 args->mode = NO_CHANGE_64;
2405
2406 if (attrs->ia_valid & ATTR_UID)
2407 args->uid = attrs->ia_uid;
2408 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002409 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002410
2411 if (attrs->ia_valid & ATTR_GID)
2412 args->gid = attrs->ia_gid;
2413 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002414 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002415
2416 if (attrs->ia_valid & ATTR_ATIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002417 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002418 else
2419 args->atime = NO_CHANGE_64;
2420
2421 if (attrs->ia_valid & ATTR_MTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002422 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002423 else
2424 args->mtime = NO_CHANGE_64;
2425
2426 if (attrs->ia_valid & ATTR_CTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002427 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002428 else
2429 args->ctime = NO_CHANGE_64;
2430
2431 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002432 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002433 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002434 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002435 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002436 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002437 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002438 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002439 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002440 tlink = cifs_sb_tlink(cifs_sb);
2441 if (IS_ERR(tlink)) {
2442 rc = PTR_ERR(tlink);
2443 goto out;
2444 }
2445 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002446 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002447 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002448 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002449 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002450 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002451
Christoph Hellwig10257742010-06-04 11:30:02 +02002452 if (rc)
2453 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002454
Christoph Hellwig10257742010-06-04 11:30:02 +02002455 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002456 attrs->ia_size != i_size_read(inode))
2457 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002458
2459 setattr_copy(inode, attrs);
2460 mark_inode_dirty(inode);
2461
2462 /* force revalidate when any of these times are set since some
2463 of the fs types (eg ext3, fat) do not have fine enough
2464 time granularity to match protocol, and we do not have a
2465 a way (yet) to query the server fs's time granularity (and
2466 whether it rounds times down).
2467 */
2468 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2469 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002470out:
2471 kfree(args);
2472 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002473 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002474 return rc;
2475}
2476
Jeff Layton0510eeb2008-08-02 07:26:12 -04002477static int
2478cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002480 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002481 kuid_t uid = INVALID_UID;
2482 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002483 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002484 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002485 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002486 struct cifsFileInfo *wfile;
2487 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 char *full_path = NULL;
2489 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002490 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002491 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002492
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002493 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
Colin Ian King63d614a2019-06-24 17:39:43 +01002495 cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
Al Viro35c265e2014-08-19 20:25:34 -04002496 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002497
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002498 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2499 attrs->ia_valid |= ATTR_FORCE;
2500
Jan Kara31051c82016-05-26 16:55:18 +02002501 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002502 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002503 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002504 return rc;
Steve French6473a552005-11-29 20:20:10 -08002505 }
Steve French50c2f752007-07-13 00:33:32 +00002506
Steve French7f573562005-08-30 11:32:14 -07002507 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302509 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002510 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302511 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513
Jeff Layton0f4d6342009-03-26 13:35:37 -04002514 /*
2515 * Attempt to flush data before changing attributes. We need to do
2516 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2517 * ownership or mode then we may also need to do this. Here, we take
2518 * the safe way out and just do the flush on all setattr requests. If
2519 * the flush returns error, store it to report later and continue.
2520 *
2521 * BB: This should be smarter. Why bother flushing pages that
2522 * will be truncated anyway? Also, should we error out here if
2523 * the flush returns error?
2524 */
2525 rc = filemap_write_and_wait(inode->i_mapping);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002526 if (is_interrupt_error(rc)) {
2527 rc = -ERESTARTSYS;
2528 goto cifs_setattr_exit;
2529 }
2530
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002531 mapping_set_error(inode->i_mapping, rc);
2532 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002533
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002534 if (attrs->ia_valid & ATTR_MTIME) {
2535 rc = cifs_get_writable_file(cifsInode, false, &wfile);
2536 if (!rc) {
2537 tcon = tlink_tcon(wfile->tlink);
2538 rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
2539 cifsFileInfo_put(wfile);
2540 if (rc)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002541 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002542 } else if (rc != -EBADF)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002543 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002544 else
2545 rc = 0;
2546 }
2547
Steve French50531442008-03-14 19:21:31 +00002548 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002549 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2550 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002551 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002553
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002554 if (attrs->ia_valid & ATTR_UID)
2555 uid = attrs->ia_uid;
2556
2557 if (attrs->ia_valid & ATTR_GID)
2558 gid = attrs->ia_gid;
2559
Steve French22442172019-07-19 08:15:55 +00002560 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2561 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002562 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002563 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2564 uid, gid);
2565 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002566 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2567 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002568 goto cifs_setattr_exit;
2569 }
2570 }
2571 } else
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002572 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002573 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574
Jeff Laytond32c4f22007-10-18 03:05:22 -07002575 /* skip mode change if it's just for clearing setuid/setgid */
2576 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2577 attrs->ia_valid &= ~ATTR_MODE;
2578
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 mode = attrs->ia_mode;
Steve Frenchcdbce9c82005-11-19 21:04:52 -08002581 rc = 0;
Steve French22442172019-07-19 08:15:55 +00002582 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2583 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002584 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002585 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002586 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002587 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2588 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002589 goto cifs_setattr_exit;
2590 }
2591 } else
Jeff Layton51328612008-05-22 09:33:34 -04002592 if (((mode & S_IWUGO) == 0) &&
2593 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002594
2595 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2596
Jeff Layton51328612008-05-22 09:33:34 -04002597 /* fix up mode if we're not using dynperm */
2598 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2599 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2600 } else if ((mode & S_IWUGO) &&
2601 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002602
2603 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2604 /* Attributes of 0 are ignored */
2605 if (dosattr == 0)
2606 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002607
2608 /* reset local inode permissions to normal */
2609 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2610 attrs->ia_mode &= ~(S_IALLUGO);
2611 if (S_ISDIR(inode->i_mode))
2612 attrs->ia_mode |=
2613 cifs_sb->mnt_dir_mode;
2614 else
2615 attrs->ia_mode |=
2616 cifs_sb->mnt_file_mode;
2617 }
2618 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2619 /* ignore mode change - ATTR_READONLY hasn't changed */
2620 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 }
2623
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002624 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2625 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2626 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2627 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628
Steve Frenche30dcf32005-09-20 20:49:16 -07002629 /* Even if error on time set, no sense failing the call if
2630 the server would set the time to a reasonable value anyway,
2631 and this check ensures that we are not being called from
2632 sys_utimes in which case we ought to fail the call back to
2633 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002634 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002635 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002636 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 }
2638
2639 /* do not need local check to inode_check_ok since the server does
2640 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002641 if (rc)
2642 goto cifs_setattr_exit;
2643
2644 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002645 attrs->ia_size != i_size_read(inode))
2646 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002647
2648 setattr_copy(inode, attrs);
2649 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002650
Steve Frenche30dcf32005-09-20 20:49:16 -07002651cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002653 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 return rc;
2655}
2656
Jeff Layton0510eeb2008-08-02 07:26:12 -04002657int
2658cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2659{
Al Virofc640052016-04-10 01:33:30 -04002660 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002661 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002662
2663 if (pTcon->unix_ext)
2664 return cifs_setattr_unix(direntry, attrs);
2665
2666 return cifs_setattr_nounix(direntry, attrs);
2667
2668 /* BB: add cifs_setattr_legacy for really old servers */
2669}
2670
Steve French99ee4db2007-02-27 05:35:17 +00002671#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672void cifs_delete_inode(struct inode *inode)
2673{
Joe Perchesf96637b2013-05-04 22:12:25 -05002674 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 /* may have to add back in if and when safe distributed caching of
2676 directories added e.g. via FindNotify */
2677}
Steve French99ee4db2007-02-27 05:35:17 +00002678#endif