blob: b1383c524b9867dd80d68354088ed789de05671e [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;
Amir Goldstein0f060932020-02-03 21:46:43 +0200475 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400476 oparms.disposition = FILE_OPEN;
477 oparms.path = path;
478 oparms.fid = &fid;
479 oparms.reconnect = false;
480
Steve Frenchdb8b6312014-09-22 05:13:55 -0500481 if (tcon->ses->server->oplocks)
482 oplock = REQ_OPLOCK;
483 else
484 oplock = 0;
485 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400486 if (rc) {
Steve Frenchdb8b6312014-09-22 05:13:55 -0500487 cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400488 cifs_put_tlink(tlink);
489 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800490 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400491
492 /* Read header */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400493 io_parms.netfid = fid.netfid;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400494 io_parms.pid = current->tgid;
495 io_parms.tcon = tcon;
496 io_parms.offset = 0;
497 io_parms.length = 24;
498
Steve Frenchdb8b6312014-09-22 05:13:55 -0500499 rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
500 &bytes_read, &pbuf, &buf_type);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400501 if ((rc == 0) && (bytes_read >= 8)) {
502 if (memcmp("IntxBLK", pbuf, 8) == 0) {
503 cifs_dbg(FYI, "Block device\n");
504 fattr->cf_mode |= S_IFBLK;
505 fattr->cf_dtype = DT_BLK;
506 if (bytes_read == 24) {
507 /* we have enough to decode dev num */
508 __u64 mjr; /* major */
509 __u64 mnr; /* minor */
510 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
511 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
512 fattr->cf_rdev = MKDEV(mjr, mnr);
513 }
514 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
515 cifs_dbg(FYI, "Char device\n");
516 fattr->cf_mode |= S_IFCHR;
517 fattr->cf_dtype = DT_CHR;
518 if (bytes_read == 24) {
519 /* we have enough to decode dev num */
520 __u64 mjr; /* major */
521 __u64 mnr; /* minor */
522 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
523 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
524 fattr->cf_rdev = MKDEV(mjr, mnr);
525 }
526 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
527 cifs_dbg(FYI, "Symlink\n");
528 fattr->cf_mode |= S_IFLNK;
529 fattr->cf_dtype = DT_LNK;
530 } else {
531 fattr->cf_mode |= S_IFREG; /* file? */
532 fattr->cf_dtype = DT_REG;
533 rc = -EOPNOTSUPP;
534 }
535 } else {
536 fattr->cf_mode |= S_IFREG; /* then it is a file */
537 fattr->cf_dtype = DT_REG;
538 rc = -EOPNOTSUPP; /* or some unknown SFU type */
539 }
Steve Frenchdb8b6312014-09-22 05:13:55 -0500540
541 tcon->ses->server->ops->close(xid, tcon, &fid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400542 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800543 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800544}
545
Steve French9e294f12005-11-17 16:59:21 -0800546#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
547
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400548/*
549 * Fetch mode bits as provided by SFU.
550 *
551 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
552 */
553static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400554 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800555{
Steve French3020a1f2005-11-18 11:31:10 -0800556#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800557 ssize_t rc;
558 char ea_value[4];
559 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400560 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000561 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800562
Jeff Layton7ffec372010-09-29 19:51:11 -0400563 tlink = cifs_sb_tlink(cifs_sb);
564 if (IS_ERR(tlink))
565 return PTR_ERR(tlink);
566 tcon = tlink_tcon(tlink);
567
Steve Frenchd979f3b2014-02-01 23:27:18 -0600568 if (tcon->ses->server->ops->query_all_EAs == NULL) {
569 cifs_put_tlink(tlink);
570 return -EOPNOTSUPP;
571 }
572
573 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
574 "SETFILEBITS", ea_value, 4 /* size of buf */,
Steve French67b4c882017-05-12 20:59:10 -0500575 cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400576 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000577 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800578 return (int)rc;
579 else if (rc > 3) {
580 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400581 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500582 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
583 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400584 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500585 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800586 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400587
588 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800589#else
590 return -EOPNOTSUPP;
591#endif
Steve French9e294f12005-11-17 16:59:21 -0800592}
593
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400594/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000595static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400596cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700597 struct super_block *sb, bool adjust_tz,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400598 bool symlink)
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000599{
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700600 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French96daf2b2011-05-27 04:34:02 +0000601 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700602
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400603 memset(fattr, 0, sizeof(*fattr));
604 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
605 if (info->DeletePending)
606 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000607
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400608 if (info->LastAccessTime)
609 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700610 else {
Arnd Bergmann95390202018-06-19 17:27:58 +0200611 ktime_get_real_ts64(&fattr->cf_atime);
612 fattr->cf_atime = timespec64_trunc(fattr->cf_atime, sb->s_time_gran);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700613 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400614
615 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
616 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
617
618 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700619 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
620 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400621 }
622
623 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
624 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500625 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400626
Jim McDonough74d290d2013-09-21 10:36:10 -0500627 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400628
629 if (symlink) {
630 fattr->cf_mode = S_IFLNK;
631 fattr->cf_dtype = DT_LNK;
632 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400633 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
634 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300635 /*
636 * Server can return wrong NumberOfLinks value for directories
637 * when Unix extensions are disabled - fake it.
638 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500639 if (!tcon->unix_ext)
640 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400641 } else {
642 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
643 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400644
Jeff Laytond0c280d2009-07-09 01:46:44 -0400645 /* clear write bits if ATTR_READONLY is set */
646 if (fattr->cf_cifsattrs & ATTR_READONLY)
647 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400648
Jim McDonough74d290d2013-09-21 10:36:10 -0500649 /*
650 * Don't accept zero nlink from non-unix servers unless
651 * delete is pending. Instead mark it as unknown.
652 */
653 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
654 !info->DeletePending) {
655 cifs_dbg(1, "bogus file nlink value %u\n",
Steve French6658b9f2013-07-04 14:38:48 -0500656 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500657 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500658 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300659 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400660
661 fattr->cf_uid = cifs_sb->mnt_uid;
662 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000663}
664
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700665static int
666cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500667{
668 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400669 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500670 FILE_ALL_INFO find_data;
671 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500672 struct inode *inode = file_inode(filp);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700673 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000674 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700675 struct TCP_Server_Info *server = tcon->ses->server;
676
677 if (!server->ops->query_file_info)
678 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500679
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400680 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700681 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400682 switch (rc) {
683 case 0:
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700684 cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400685 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400686 break;
687 case -EREMOTE:
688 cifs_create_dfs_fattr(&fattr, inode->i_sb);
689 rc = 0;
690 break;
691 case -EOPNOTSUPP:
692 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500693 /*
694 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000695 * for now, just skip revalidating and mark inode for
696 * immediate reval.
697 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500698 rc = 0;
699 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400700 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500701 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400702 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500703
704 /*
705 * don't bother with SFU junk here -- just mark inode as needing
706 * revalidation.
707 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500708 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
709 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
710 cifs_fattr_to_inode(inode, &fattr);
711cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400712 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500713 return rc;
714}
715
Steve French7ea884c2018-03-31 18:13:38 -0500716/* Simple function to return a 64 bit hash of string. Rarely called */
717static __u64 simple_hashstr(const char *str)
718{
Geert Uytterhoeven3995bbf2018-04-05 14:57:11 +0200719 const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
Steve French7ea884c2018-03-31 18:13:38 -0500720 __u64 hash = 0;
721
722 while (*str)
723 hash = (hash + (__u64) *str++) * hash_mult;
724
725 return hash;
726}
727
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100728/**
729 * cifs_backup_query_path_info - SMB1 fallback code to get ino
730 *
731 * Fallback code to get file metadata when we don't have access to
732 * @full_path (EACCESS) and have backup creds.
733 *
734 * @data will be set to search info result buffer
735 * @resp_buf will be set to cifs resp buf and needs to be freed with
736 * cifs_buf_release() when done with @data.
737 */
738static int
739cifs_backup_query_path_info(int xid,
740 struct cifs_tcon *tcon,
741 struct super_block *sb,
742 const char *full_path,
743 void **resp_buf,
744 FILE_ALL_INFO **data)
745{
746 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
747 struct cifs_search_info info = {0};
748 u16 flags;
749 int rc;
750
751 *resp_buf = NULL;
752 info.endOfSearch = false;
753 if (tcon->unix_ext)
754 info.info_level = SMB_FIND_FILE_UNIX;
755 else if ((tcon->ses->capabilities &
756 tcon->ses->server->vals->cap_nt_find) == 0)
757 info.info_level = SMB_FIND_FILE_INFO_STANDARD;
758 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
759 info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
760 else /* no srvino useful for fallback to some netapp */
761 info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
762
763 flags = CIFS_SEARCH_CLOSE_ALWAYS |
764 CIFS_SEARCH_CLOSE_AT_END |
765 CIFS_SEARCH_BACKUP_SEARCH;
766
767 rc = CIFSFindFirst(xid, tcon, full_path,
768 cifs_sb, NULL, flags, &info, false);
769 if (rc)
770 return rc;
771
772 *resp_buf = (void *)info.ntwrk_buf_start;
773 *data = (FILE_ALL_INFO *)info.srch_entries_start;
774 return 0;
775}
776
777static void
778cifs_set_fattr_ino(int xid,
779 struct cifs_tcon *tcon,
780 struct super_block *sb,
781 struct inode **inode,
782 const char *full_path,
783 FILE_ALL_INFO *data,
784 struct cifs_fattr *fattr)
785{
786 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
787 struct TCP_Server_Info *server = tcon->ses->server;
788 int rc;
789
790 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
791 if (*inode)
792 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
793 else
794 fattr->cf_uniqueid = iunique(sb, ROOT_I);
795 return;
796 }
797
798 /*
799 * If we have an inode pass a NULL tcon to ensure we don't
800 * make a round trip to the server. This only works for SMB2+.
801 */
802 rc = server->ops->get_srv_inum(xid,
803 *inode ? NULL : tcon,
804 cifs_sb, full_path,
805 &fattr->cf_uniqueid,
806 data);
807 if (rc) {
808 /*
809 * If that fails reuse existing ino or generate one
810 * and disable server ones
811 */
812 if (*inode)
813 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
814 else {
815 fattr->cf_uniqueid = iunique(sb, ROOT_I);
816 cifs_autodisable_serverino(cifs_sb);
817 }
818 return;
819 }
820
821 /* If no errors, check for zero root inode (invalid) */
822 if (fattr->cf_uniqueid == 0 && strlen(full_path) == 0) {
823 cifs_dbg(FYI, "Invalid (0) inodenum\n");
824 if (*inode) {
825 /* reuse */
826 fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
827 } else {
828 /* make an ino by hashing the UNC */
829 fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
830 fattr->cf_uniqueid = simple_hashstr(tcon->treeName);
831 }
832 }
833}
834
835static inline bool is_inode_cache_good(struct inode *ino)
836{
837 return ino && CIFS_CACHE_READ(CIFS_I(ino)) && CIFS_I(ino)->time != 0;
838}
839
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400840int
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100841cifs_get_inode_info(struct inode **inode,
842 const char *full_path,
843 FILE_ALL_INFO *in_data,
844 struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600845 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846{
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100847
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400848 struct cifs_tcon *tcon;
849 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400850 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400852 bool adjust_tz = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100853 struct cifs_fattr fattr = {0};
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400854 bool symlink = false;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100855 FILE_ALL_INFO *data = in_data;
856 FILE_ALL_INFO *tmp_data = NULL;
857 void *smb1_backup_rsp_buf = NULL;
858 int rc = 0;
859 int tmprc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860
Jeff Layton7ffec372010-09-29 19:51:11 -0400861 tlink = cifs_sb_tlink(cifs_sb);
862 if (IS_ERR(tlink))
863 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400864 tcon = tlink_tcon(tlink);
865 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400866
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100867 /*
868 * 1. Fetch file metadata if not provided (data)
869 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100871 if (!data) {
872 if (is_inode_cache_good(*inode)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500873 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100874 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100876 tmp_data = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
877 if (!tmp_data) {
Jeff Layton7ffec372010-09-29 19:51:11 -0400878 rc = -ENOMEM;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100879 goto out;
Jeff Layton7ffec372010-09-29 19:51:11 -0400880 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100881 rc = server->ops->query_path_info(xid, tcon, cifs_sb,
882 full_path, tmp_data,
883 &adjust_tz, &symlink);
884 data = tmp_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400886
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400887 /*
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100888 * 2. Convert it to internal cifs metadata (fattr)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400889 */
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100890
891 switch (rc) {
892 case 0:
893 cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
894 break;
895 case -EREMOTE:
896 /* DFS link, no metadata available on this server */
897 cifs_create_dfs_fattr(&fattr, sb);
898 rc = 0;
899 break;
900 case -EACCES:
901 /*
902 * perm errors, try again with backup flags if possible
903 *
904 * For SMB2 and later the backup intent flag
905 * is already sent if needed on open and there
906 * is no path based FindFirst operation to use
907 * to retry with
908 */
909 if (backup_cred(cifs_sb) && is_smb1_server(server)) {
910 /* for easier reading */
911 FILE_DIRECTORY_INFO *fdi;
912 SEARCH_ID_FULL_DIR_INFO *si;
913
914 rc = cifs_backup_query_path_info(xid, tcon, sb,
915 full_path,
916 &smb1_backup_rsp_buf,
917 &data);
918 if (rc)
919 goto out;
920
921 fdi = (FILE_DIRECTORY_INFO *)data;
922 si = (SEARCH_ID_FULL_DIR_INFO *)data;
923
924 cifs_dir_info_to_fattr(&fattr, fdi, cifs_sb);
925 fattr.cf_uniqueid = le64_to_cpu(si->UniqueId);
926 /* uniqueid set, skip get inum step */
927 goto handle_mnt_opt;
928 } else {
929 /* nothing we can do, bail out */
930 goto out;
931 }
932 break;
933 default:
934 cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
935 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000936 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000937
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100938 /*
939 * 3. Get or update inode number (fattr.cf_uniqueid)
940 */
941
942 cifs_set_fattr_ino(xid, tcon, sb, inode, full_path, data, &fattr);
943
944 /*
945 * 4. Tweak fattr based on mount options
946 */
947
948handle_mnt_opt:
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400949 /* query for SFU type info if supported and needed */
950 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
951 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
952 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
953 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500954 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000955 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000956
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000957 /* fill in 0777 bits from ACL */
Steve Frenche2f8fbf2019-07-19 06:30:07 +0000958 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
959 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
960 full_path, fid);
961 if (rc) {
962 cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100963 __func__, rc);
964 goto out;
Steve Frenche2f8fbf2019-07-19 06:30:07 +0000965 }
966 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
967 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
Dan Carpenter via samba-technical68464b82019-11-26 15:11:15 +0300968 full_path, fid);
969 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500970 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
971 __func__, rc);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100972 goto out;
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600973 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000974 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400975
976 /* fill in remaining high mode bits e.g. SUID, VTX */
977 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
978 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
979
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200980 /* check for Minshall+French symlinks */
981 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000982 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
983 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200984 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000985 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200986 }
987
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +0100988 /*
989 * 5. Update inode with final fattr data
990 */
991
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400992 if (!*inode) {
993 *inode = cifs_iget(sb, &fattr);
994 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400995 rc = -ENOMEM;
996 } else {
Nakajima Akira7196ac12015-04-22 15:24:44 +0900997 /* we already have inode, update it */
998
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000999 /* if uniqueid is different, return error */
1000 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
1001 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001002 CIFS_I(*inode)->time = 0; /* force reval */
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001003 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001004 goto out;
Ross Lagerwalla108471b2015-12-02 14:46:08 +00001005 }
1006
Nakajima Akira7196ac12015-04-22 15:24:44 +09001007 /* if filetype is different, return error */
1008 if (unlikely(((*inode)->i_mode & S_IFMT) !=
1009 (fattr.cf_mode & S_IFMT))) {
Pavel Shilovskyc82e5ac2019-09-30 10:06:19 -07001010 CIFS_I(*inode)->time = 0; /* force reval */
Nakajima Akira7196ac12015-04-22 15:24:44 +09001011 rc = -ESTALE;
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001012 goto out;
Nakajima Akira7196ac12015-04-22 15:24:44 +09001013 }
1014
Pavel Shilovsky1208ef12012-05-27 17:34:43 +04001015 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a3260f2008-05-20 21:52:32 +00001016 }
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001017out:
1018 cifs_buf_release(smb1_backup_rsp_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001019 cifs_put_tlink(tlink);
Aurelien Aptelb8f7442b2019-11-18 21:04:08 +01001020 kfree(tmp_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 return rc;
1022}
1023
Steve French7f8ed422007-09-28 22:28:55 +00001024static const struct inode_operations cifs_ipc_inode_ops = {
1025 .lookup = cifs_lookup,
1026};
1027
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001028static int
1029cifs_find_inode(struct inode *inode, void *opaque)
1030{
1031 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1032
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001033 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001034 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
1035 return 0;
1036
Jeff Layton20054bd2011-01-07 11:30:27 -05001037 /* use createtime like an i_generation field */
1038 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
1039 return 0;
1040
Jeff Laytonf30b9c12010-07-19 18:00:17 -04001041 /* don't match inode of different type */
1042 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
1043 return 0;
1044
Jeff Layton5acfec22010-08-02 17:43:54 -04001045 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -04001046 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -04001047 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -04001048
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001049 return 1;
1050}
1051
1052static int
1053cifs_init_inode(struct inode *inode, void *opaque)
1054{
1055 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
1056
1057 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -05001058 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001059 return 0;
1060}
1061
Jeff Layton5acfec22010-08-02 17:43:54 -04001062/*
1063 * walk dentry list for an inode and report whether it has aliases that
1064 * are hashed. We use this to determine if a directory inode can actually
1065 * be used.
1066 */
1067static bool
1068inode_has_hashed_dentries(struct inode *inode)
1069{
1070 struct dentry *dentry;
1071
Nick Piggin873feea2011-01-07 17:50:06 +11001072 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -04001073 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001074 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +11001075 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001076 return true;
1077 }
1078 }
Nick Piggin873feea2011-01-07 17:50:06 +11001079 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -04001080 return false;
1081}
1082
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001083/* Given fattrs, get a corresponding inode */
1084struct inode *
1085cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
1086{
1087 unsigned long hash;
1088 struct inode *inode;
1089
Jeff Layton3d694382010-05-11 14:59:55 -04001090retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -05001091 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001092
1093 /* hash down to 32-bits on 32-bit arch */
1094 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
1095
1096 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001097 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001098 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -04001099 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -04001100 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -04001101
1102 if (inode_has_hashed_dentries(inode)) {
1103 cifs_autodisable_serverino(CIFS_SB(sb));
1104 iput(inode);
1105 fattr->cf_uniqueid = iunique(sb, ROOT_I);
1106 goto retry_iget5_locked;
1107 }
Jeff Layton3d694382010-05-11 14:59:55 -04001108 }
1109
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001110 cifs_fattr_to_inode(inode, fattr);
Linus Torvalds1751e8a2017-11-27 13:05:09 -08001111 if (sb->s_flags & SB_NOATIME)
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001112 inode->i_flags |= S_NOATIME | S_NOCMTIME;
1113 if (inode->i_state & I_NEW) {
1114 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +00001115#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301116 /* initialize per-inode cache cookie pointer */
1117 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +00001118#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001119 unlock_new_inode(inode);
1120 }
1121 }
1122
1123 return inode;
1124}
1125
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001127struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001129 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001130 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001131 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001132 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001133 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001134 char *path = NULL;
1135 int len;
1136
1137 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1138 && cifs_sb->prepath) {
1139 len = strlen(cifs_sb->prepath);
1140 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1141 if (path == NULL)
1142 return ERR_PTR(-ENOMEM);
1143 path[0] = '/';
1144 memcpy(path+1, cifs_sb->prepath, len);
1145 } else {
1146 path = kstrdup("", GFP_KERNEL);
1147 if (path == NULL)
1148 return ERR_PTR(-ENOMEM);
1149 }
David Howellsce634ab2008-02-07 00:15:33 -08001150
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001151 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001152 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001153 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001154 /* some servers mistakenly claim POSIX support */
1155 if (rc != -EOPNOTSUPP)
1156 goto iget_no_retry;
1157 cifs_dbg(VFS, "server does not support POSIX extensions");
1158 tcon->unix_ext = false;
1159 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001160
Aurelien Aptela6b50582016-05-25 19:59:09 +02001161 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
1162 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001163
1164iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001165 if (!inode) {
1166 inode = ERR_PTR(rc);
1167 goto out;
1168 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001169
Steve French0ccd4802010-07-16 04:31:02 +00001170#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301171 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001172 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001173#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301174
Aurelien Aptelb327a712018-01-24 13:46:10 +01001175 if (rc && tcon->pipe) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001176 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001177 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001178 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001179 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001180 inode->i_op = &cifs_ipc_inode_ops;
1181 inode->i_fop = &simple_dir_operations;
1182 inode->i_uid = cifs_sb->mnt_uid;
1183 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001184 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001185 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001186 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001187 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001188 }
1189
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001190out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001191 kfree(path);
Phillip Potter31cd1062018-03-17 21:06:56 +00001192 free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001193 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194}
1195
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001196int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001197cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001198 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001199{
Steve French388e57b2008-09-16 23:50:58 +00001200 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001201 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001202 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001203 FILE_BASIC_INFO info_buf;
1204
Steve French1adcb712009-02-25 14:19:56 +00001205 if (attrs == NULL)
1206 return -EINVAL;
1207
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001208 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1209 if (!server->ops->set_file_info)
1210 return -ENOSYS;
1211
Steve Frenchfd09b7d2018-08-02 20:28:18 -05001212 info_buf.Pad = 0;
1213
Steve French388e57b2008-09-16 23:50:58 +00001214 if (attrs->ia_valid & ATTR_ATIME) {
1215 set_time = true;
1216 info_buf.LastAccessTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001217 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
Steve French388e57b2008-09-16 23:50:58 +00001218 } else
1219 info_buf.LastAccessTime = 0;
1220
1221 if (attrs->ia_valid & ATTR_MTIME) {
1222 set_time = true;
1223 info_buf.LastWriteTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001224 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
Steve French388e57b2008-09-16 23:50:58 +00001225 } else
1226 info_buf.LastWriteTime = 0;
1227
1228 /*
1229 * Samba throws this field away, but windows may actually use it.
1230 * Do not set ctime unless other time stamps are changed explicitly
1231 * (i.e. by utimes()) since we would then have a mix of client and
1232 * server times.
1233 */
1234 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001235 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001236 info_buf.ChangeTime =
Arnd Bergmann95390202018-06-19 17:27:58 +02001237 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
Steve French388e57b2008-09-16 23:50:58 +00001238 } else
1239 info_buf.ChangeTime = 0;
1240
1241 info_buf.CreationTime = 0; /* don't change */
1242 info_buf.Attributes = cpu_to_le32(dosattr);
1243
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001244 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001245}
1246
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001247/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001248 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001249 * and rename it to a random name that hopefully won't conflict with
1250 * anything else.
1251 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001252int
1253cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1254 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001255{
1256 int oplock = 0;
1257 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001258 struct cifs_fid fid;
1259 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001260 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001261 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1262 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001263 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001264 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001265 __u32 dosattr, origattr;
1266 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001267
Jeff Layton7ffec372010-09-29 19:51:11 -04001268 tlink = cifs_sb_tlink(cifs_sb);
1269 if (IS_ERR(tlink))
1270 return PTR_ERR(tlink);
1271 tcon = tlink_tcon(tlink);
1272
Sachin Prabhuc483a982013-03-05 19:25:56 +00001273 /*
1274 * We cannot rename the file if the server doesn't support
1275 * CAP_INFOLEVEL_PASSTHRU
1276 */
1277 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1278 rc = -EBUSY;
1279 goto out;
1280 }
1281
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001282 oparms.tcon = tcon;
1283 oparms.cifs_sb = cifs_sb;
1284 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
Amir Goldstein0f060932020-02-03 21:46:43 +02001285 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001286 oparms.disposition = FILE_OPEN;
1287 oparms.path = full_path;
1288 oparms.fid = &fid;
1289 oparms.reconnect = false;
1290
1291 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001292 if (rc != 0)
1293 goto out;
1294
Steve French32709582008-10-20 00:44:19 +00001295 origattr = cifsInode->cifsAttrs;
1296 if (origattr == 0)
1297 origattr |= ATTR_NORMAL;
1298
1299 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001300 if (dosattr == 0)
1301 dosattr |= ATTR_NORMAL;
1302 dosattr |= ATTR_HIDDEN;
1303
Steve French32709582008-10-20 00:44:19 +00001304 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1305 if (dosattr != origattr) {
1306 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1307 if (info_buf == NULL) {
1308 rc = -ENOMEM;
1309 goto out_close;
1310 }
1311 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001312 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001313 current->tgid);
1314 /* although we would like to mark the file hidden
1315 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001316 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001317 cifsInode->cifsAttrs = dosattr;
1318 else
1319 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001320 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001321
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001322 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001323 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1324 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001325 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001326 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001327 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001328 goto undo_setattr;
1329 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001330
Steve French32709582008-10-20 00:44:19 +00001331 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001332 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001333 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001334 current->tgid);
1335 /*
1336 * some samba versions return -ENOENT when we try to set the
1337 * file disposition here. Likely a samba bug, but work around
1338 * it for now. This means that some cifsXXX files may hang
1339 * around after they shouldn't.
1340 *
1341 * BB: remove this hack after more servers have the fix
1342 */
1343 if (rc == -ENOENT)
1344 rc = 0;
1345 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001346 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001347 goto undo_rename;
1348 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001349 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001350 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001351
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001352out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001353 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001354out:
Steve French32709582008-10-20 00:44:19 +00001355 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001356 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001357 return rc;
Steve French32709582008-10-20 00:44:19 +00001358
1359 /*
1360 * reset everything back to the original state. Don't bother
1361 * dealing with errors here since we can't do anything about
1362 * them anyway.
1363 */
1364undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001365 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001366 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001367undo_setattr:
1368 if (dosattr != origattr) {
1369 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001370 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001371 current->tgid))
1372 cifsInode->cifsAttrs = origattr;
1373 }
1374
1375 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001376}
1377
Steve Frenchb7ca6922012-08-03 08:43:01 -05001378/* copied from fs/nfs/dir.c with small changes */
1379static void
1380cifs_drop_nlink(struct inode *inode)
1381{
1382 spin_lock(&inode->i_lock);
1383 if (inode->i_nlink > 0)
1384 drop_nlink(inode);
1385 spin_unlock(&inode->i_lock);
1386}
Steve Frenchff694522009-04-20 19:45:13 +00001387
1388/*
David Howells2b0143b2015-03-17 22:25:59 +00001389 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001390 * is a negative dentry) then we would attempt a standard SMB delete, but
Colin Ian King413d6102018-10-26 19:07:21 +01001391 * if that fails we can not attempt the fall back mechanisms on EACCES
1392 * but will return the EACCES to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001393 * unlink on negative dentries currently.
1394 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001395int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396{
1397 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001398 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001400 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001401 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001402 struct super_block *sb = dir->i_sb;
1403 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001404 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001405 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001406 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001407 struct iattr *attrs = NULL;
1408 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409
Joe Perchesf96637b2013-05-04 22:12:25 -05001410 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
Jeff Layton7ffec372010-09-29 19:51:11 -04001412 tlink = cifs_sb_tlink(cifs_sb);
1413 if (IS_ERR(tlink))
1414 return PTR_ERR(tlink);
1415 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001416 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001417
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001418 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
Jeff Layton5f0319a2008-09-16 14:05:16 -04001420 /* Unlink can be called from rename so we can not take the
1421 * sb->s_vfs_rename_mutex here */
1422 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301424 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001425 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 }
Steve French2d785a52007-07-15 01:48:57 +00001427
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001428 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1429 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001430 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001431 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001432 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001433 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001434 if ((rc == 0) || (rc == -ENOENT))
1435 goto psx_del_no_retry;
1436 }
1437
Steve French60502472008-10-07 18:42:52 +00001438retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001439 if (!server->ops->unlink) {
1440 rc = -ENOSYS;
1441 goto psx_del_no_retry;
1442 }
1443
1444 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001445
Steve French2d785a52007-07-15 01:48:57 +00001446psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001448 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001449 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001451 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001452 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001453 if (server->ops->rename_pending_delete) {
1454 rc = server->ops->rename_pending_delete(full_path,
1455 dentry, xid);
1456 if (rc == 0)
1457 cifs_drop_nlink(inode);
1458 }
Steve Frenchff694522009-04-20 19:45:13 +00001459 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001460 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1461 if (attrs == NULL) {
1462 rc = -ENOMEM;
1463 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 }
Steve French388e57b2008-09-16 23:50:58 +00001465
1466 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001467 cifs_inode = CIFS_I(inode);
1468 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001469 if (origattr == 0)
1470 origattr |= ATTR_NORMAL;
1471 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001472 if (dosattr == 0)
1473 dosattr |= ATTR_NORMAL;
1474 dosattr |= ATTR_HIDDEN;
1475
1476 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001477 if (rc != 0)
1478 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001479
1480 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 }
Steve French60502472008-10-07 18:42:52 +00001482
1483 /* undo the setattr if we errored out and it's needed */
1484 if (rc != 0 && dosattr != 0)
1485 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1486
Steve French388e57b2008-09-16 23:50:58 +00001487out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001488 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001489 cifs_inode = CIFS_I(inode);
1490 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001491 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001492 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001493 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001494 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001495 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001496 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001497unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001499 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001500 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001501 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 return rc;
1503}
1504
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001505static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001506cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001507 const char *full_path, struct cifs_sb_info *cifs_sb,
1508 struct cifs_tcon *tcon, const unsigned int xid)
1509{
1510 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001511 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001512
1513 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001514 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001515 xid);
1516 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001517 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1518 xid, NULL);
1519
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001520 if (rc)
1521 return rc;
1522
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001523 /*
1524 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001525 * from the server or was set bogus. Also, since this is a brand new
1526 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001527 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001528 if (inode->i_nlink < 2)
1529 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001530 mode &= ~current_umask();
1531 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001532 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001533 mode |= S_ISGID;
1534
1535 if (tcon->unix_ext) {
1536 struct cifs_unix_set_info_args args = {
1537 .mode = mode,
1538 .ctime = NO_CHANGE_64,
1539 .atime = NO_CHANGE_64,
1540 .mtime = NO_CHANGE_64,
1541 .device = 0,
1542 };
1543 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001544 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001545 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001546 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001547 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001548 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001549 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001550 args.uid = INVALID_UID; /* no change */
1551 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001552 }
1553 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1554 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001555 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001556 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001557 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001558 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001559 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001560 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001561 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001562 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1563 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001564
Jeff Layton101b92d2012-09-19 06:22:45 -07001565 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1566 inode->i_uid = current_fsuid();
1567 if (inode->i_mode & S_ISGID)
1568 inode->i_gid = parent->i_gid;
1569 else
1570 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001571 }
1572 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001573 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001574 return rc;
1575}
1576
1577static int
1578cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1579 const char *full_path, struct cifs_sb_info *cifs_sb,
1580 struct cifs_tcon *tcon, const unsigned int xid)
1581{
1582 int rc = 0;
1583 u32 oplock = 0;
1584 FILE_UNIX_BASIC_INFO *info = NULL;
1585 struct inode *newinode = NULL;
1586 struct cifs_fattr fattr;
1587
1588 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1589 if (info == NULL) {
1590 rc = -ENOMEM;
1591 goto posix_mkdir_out;
1592 }
1593
1594 mode &= ~current_umask();
1595 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1596 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001597 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001598 if (rc == -EOPNOTSUPP)
1599 goto posix_mkdir_out;
1600 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001601 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001602 d_drop(dentry);
1603 goto posix_mkdir_out;
1604 }
1605
1606 if (info->Type == cpu_to_le32(-1))
1607 /* no return info, go query for it */
1608 goto posix_mkdir_get_info;
1609 /*
1610 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1611 * need to set uid/gid.
1612 */
1613
1614 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1615 cifs_fill_uniqueid(inode->i_sb, &fattr);
1616 newinode = cifs_iget(inode->i_sb, &fattr);
1617 if (!newinode)
1618 goto posix_mkdir_get_info;
1619
1620 d_instantiate(dentry, newinode);
1621
1622#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001623 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1624 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001625
1626 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001627 cifs_dbg(FYI, "unexpected number of links %d\n",
1628 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001629#endif
1630
1631posix_mkdir_out:
1632 kfree(info);
1633 return rc;
1634posix_mkdir_get_info:
1635 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1636 xid);
1637 goto posix_mkdir_out;
1638}
1639
Al Viro18bb1db2011-07-26 01:41:39 -04001640int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001642 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001643 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001645 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001646 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001647 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001648 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649
Joe Perchesf96637b2013-05-04 22:12:25 -05001650 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1651 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001654 tlink = cifs_sb_tlink(cifs_sb);
1655 if (IS_ERR(tlink))
1656 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001657 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001658
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001659 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660
Steve French7f573562005-08-30 11:32:14 -07001661 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301663 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001664 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 }
Steve French50c2f752007-07-13 00:33:32 +00001666
Steve Frenchbea851b2018-06-14 21:56:32 -05001667 server = tcon->ses->server;
1668
Steve Frenchbea851b2018-06-14 21:56:32 -05001669 if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
1670 rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
1671 cifs_sb);
1672 d_drop(direntry); /* for time being always refresh inode info */
1673 goto mkdir_out;
1674 }
Steve Frenchbea851b2018-06-14 21:56:32 -05001675
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001676 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1677 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001678 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1679 tcon, xid);
1680 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001681 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001682 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001683
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001684 if (!server->ops->mkdir) {
1685 rc = -ENOSYS;
1686 goto mkdir_out;
1687 }
1688
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001690 rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001692 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001694 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001696
Steve Frenchc3ca78e2019-09-25 00:32:13 -05001697 /* TODO: skip this for smb2/smb3 */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001698 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1699 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001700mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001701 /*
1702 * Force revalidate to get parent dir info when needed since cached
1703 * attributes are invalid now.
1704 */
1705 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001707 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001708 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 return rc;
1710}
1711
1712int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1713{
1714 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001715 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001717 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001718 struct cifs_tcon *tcon;
1719 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 char *full_path = NULL;
1721 struct cifsInodeInfo *cifsInode;
1722
Joe Perchesf96637b2013-05-04 22:12:25 -05001723 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001725 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Steve French7f573562005-08-30 11:32:14 -07001727 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301729 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001730 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 }
1732
Jeff Layton7ffec372010-09-29 19:51:11 -04001733 cifs_sb = CIFS_SB(inode->i_sb);
1734 tlink = cifs_sb_tlink(cifs_sb);
1735 if (IS_ERR(tlink)) {
1736 rc = PTR_ERR(tlink);
1737 goto rmdir_exit;
1738 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001739 tcon = tlink_tcon(tlink);
1740 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001741
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001742 if (!server->ops->rmdir) {
1743 rc = -ENOSYS;
1744 cifs_put_tlink(tlink);
1745 goto rmdir_exit;
1746 }
1747
1748 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001749 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750
1751 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001752 spin_lock(&d_inode(direntry)->i_lock);
1753 i_size_write(d_inode(direntry), 0);
1754 clear_nlink(d_inode(direntry));
1755 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 }
1757
David Howells2b0143b2015-03-17 22:25:59 +00001758 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001759 /* force revalidate to go get info when needed */
1760 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001761
1762 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001763 /*
1764 * Force revalidate to get parent dir info when needed since cached
1765 * attributes are invalid now.
1766 */
1767 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001768
David Howells2b0143b2015-03-17 22:25:59 +00001769 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001770 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
Jeff Layton7ffec372010-09-29 19:51:11 -04001772rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001774 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 return rc;
1776}
1777
Steve Frenchee2fd962008-09-23 18:23:33 +00001778static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001779cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1780 const char *from_path, struct dentry *to_dentry,
1781 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001782{
1783 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001784 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001785 struct cifs_tcon *tcon;
1786 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001787 struct cifs_fid fid;
1788 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001789 int oplock, rc;
1790
Jeff Layton7ffec372010-09-29 19:51:11 -04001791 tlink = cifs_sb_tlink(cifs_sb);
1792 if (IS_ERR(tlink))
1793 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001794 tcon = tlink_tcon(tlink);
1795 server = tcon->ses->server;
1796
1797 if (!server->ops->rename)
1798 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001799
Steve Frenchee2fd962008-09-23 18:23:33 +00001800 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001801 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001802
1803 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001804 * Don't bother with rename by filehandle unless file is busy and
1805 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001806 * rename by filehandle to various Windows servers.
1807 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001808 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001809 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001810
Frank Sorenson652727b2019-04-16 08:37:27 -05001811 /* Don't fall back to using SMB on SMB 2+ mount */
1812 if (server->vals->protocol_id != 0)
1813 goto do_rename_exit;
1814
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001815 /* open-file renames don't work across directories */
1816 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001817 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001818
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001819 oparms.tcon = tcon;
1820 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00001821 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001822 oparms.desired_access = DELETE;
Amir Goldstein0f060932020-02-03 21:46:43 +02001823 oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001824 oparms.disposition = FILE_OPEN;
1825 oparms.path = from_path;
1826 oparms.fid = &fid;
1827 oparms.reconnect = false;
1828
1829 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00001830 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001831 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001832 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001833 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001834 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001835 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001836do_rename_exit:
1837 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001838 return rc;
1839}
1840
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001841int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001842cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
1843 struct inode *target_dir, struct dentry *target_dentry,
1844 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001846 char *from_name = NULL;
1847 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001848 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001849 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001850 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001851 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1852 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001853 unsigned int xid;
1854 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001856 if (flags & ~RENAME_NOREPLACE)
1857 return -EINVAL;
1858
Jeff Layton639e7a92010-09-03 11:50:09 -04001859 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001860 tlink = cifs_sb_tlink(cifs_sb);
1861 if (IS_ERR(tlink))
1862 return PTR_ERR(tlink);
1863 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001865 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001866
1867 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001868 * we already have the rename sem so we do not need to
1869 * grab it again here to protect the path integrity
1870 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001871 from_name = build_path_from_dentry(source_dentry);
1872 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 rc = -ENOMEM;
1874 goto cifs_rename_exit;
1875 }
1876
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001877 to_name = build_path_from_dentry(target_dentry);
1878 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001879 rc = -ENOMEM;
1880 goto cifs_rename_exit;
1881 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001883 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1884 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001885
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001886 /*
1887 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
1888 */
1889 if (flags & RENAME_NOREPLACE)
1890 goto cifs_rename_exit;
1891
Jeff Layton14121bd2008-10-20 14:45:22 -04001892 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001893 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001894 * Are src and dst hardlinks of same inode? We can only tell
1895 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001896 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001897 info_buf_source =
Kees Cook6da2ec52018-06-12 13:55:00 -07001898 kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
Jeff Layton14121bd2008-10-20 14:45:22 -04001899 GFP_KERNEL);
1900 if (info_buf_source == NULL) {
1901 rc = -ENOMEM;
1902 goto cifs_rename_exit;
1903 }
1904
1905 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001906 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1907 info_buf_source,
1908 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001909 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04001910 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001911 goto unlink_target;
1912
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001913 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1914 info_buf_target,
1915 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001916 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04001917
Jeff Layton8d281ef2008-10-22 13:57:01 -04001918 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001919 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001920 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001921 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001922 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001923 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001924 }
1925 /*
1926 * else ... BB we could add the same check for Windows by
1927 * checking the UniqueId via FILE_INTERNAL_INFO
1928 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001929
Jeff Layton14121bd2008-10-20 14:45:22 -04001930unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001931 /* Try unlinking the target dentry if it's not negative */
David Howells2b0143b2015-03-17 22:25:59 +00001932 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04001933 if (d_is_dir(target_dentry))
1934 tmprc = cifs_rmdir(target_dir, target_dentry);
1935 else
1936 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001937 if (tmprc)
1938 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001939 rc = cifs_do_rename(xid, source_dentry, from_name,
1940 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 }
1942
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001943 /* force revalidate to go get info when needed */
1944 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1945
1946 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001947 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001948
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001950 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001951 kfree(from_name);
1952 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001953 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001954 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 return rc;
1956}
1957
Jeff Laytondf2cf172010-02-12 07:44:16 -05001958static bool
1959cifs_inode_needs_reval(struct inode *inode)
1960{
1961 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301962 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001963
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10001964 if (cifs_i->time == 0)
1965 return true;
1966
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001967 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001968 return false;
1969
1970 if (!lookupCacheEnabled)
1971 return true;
1972
Jeff Laytona87c9ad2014-03-26 07:24:23 -07001973 if (!cifs_sb->actimeo)
1974 return true;
1975
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301976 if (!time_in_range(jiffies, cifs_i->time,
1977 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001978 return true;
1979
Jeff Laytondb192722010-05-17 14:51:49 -04001980 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301981 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001982 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1983 return true;
1984
Jeff Laytondf2cf172010-02-12 07:44:16 -05001985 return false;
1986}
1987
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301988/*
1989 * Zap the cache. Called when invalid_mapping flag is set.
1990 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001991int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001992cifs_invalidate_mapping(struct inode *inode)
1993{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001994 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001995
Jeff Laytondf2cf172010-02-12 07:44:16 -05001996 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001997 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001998 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001999 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
2000 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002001 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03002002
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05302003 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002004 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002005}
2006
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002007/**
2008 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
2009 * @word: long word containing the bit lock
2010 */
2011static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002012cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002013{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002014 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01002015 if (signal_pending_state(mode, current))
2016 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002017 return 0;
2018}
2019
Jeff Laytone284e532014-04-30 09:31:46 -04002020int
2021cifs_revalidate_mapping(struct inode *inode)
2022{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002023 int rc;
2024 unsigned long *flags = &CIFS_I(inode)->flags;
2025
NeilBrown74316202014-07-07 15:16:04 +10002026 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
2027 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002028 if (rc)
2029 return rc;
2030
2031 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
2032 rc = cifs_invalidate_mapping(inode);
2033 if (rc)
2034 set_bit(CIFS_INO_INVALID_MAPPING, flags);
2035 }
2036
2037 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07002038 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04002039 wake_up_bit(flags, CIFS_INO_LOCK);
2040
2041 return rc;
2042}
2043
2044int
2045cifs_zap_mapping(struct inode *inode)
2046{
2047 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
2048 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04002049}
2050
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002051int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05002052{
2053 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05002054 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba642010-09-20 16:01:31 -07002055 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05002056
2057 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002058 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05002059
Jeff Layton13cfb732010-09-29 19:51:11 -04002060 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05002061 rc = cifs_get_file_info_unix(filp);
2062 else
2063 rc = cifs_get_file_info(filp);
2064
Jeff Laytonabab0952010-02-12 07:44:18 -05002065 return rc;
2066}
2067
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002068int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002070 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05002071 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00002072 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05002073 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002074 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075
Jeff Laytondf2cf172010-02-12 07:44:16 -05002076 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 return -ENOENT;
2078
Jeff Laytondf2cf172010-02-12 07:44:16 -05002079 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002080 return rc;
2081
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002082 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083
2084 /* can not safely grab the rename sem here if rename calls revalidate
2085 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05002086 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302088 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002089 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05002091
Joe Perchesf96637b2013-05-04 22:12:25 -05002092 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
2093 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02002094 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095
Jeff Layton0d424ad2010-09-20 16:01:35 -07002096 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05002097 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
2098 else
2099 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
2100 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002102out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002104 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 return rc;
2106}
2107
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002108int cifs_revalidate_file(struct file *filp)
2109{
2110 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002111 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002112
2113 rc = cifs_revalidate_file_attr(filp);
2114 if (rc)
2115 return rc;
2116
Jeff Laytone284e532014-04-30 09:31:46 -04002117 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002118}
2119
2120/* revalidate a dentry's inode attributes */
2121int cifs_revalidate_dentry(struct dentry *dentry)
2122{
2123 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002124 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002125
2126 rc = cifs_revalidate_dentry_attr(dentry);
2127 if (rc)
2128 return rc;
2129
Jeff Laytone284e532014-04-30 09:31:46 -04002130 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002131}
2132
David Howellsa528d352017-01-31 16:46:22 +00002133int cifs_getattr(const struct path *path, struct kstat *stat,
2134 u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135{
David Howellsa528d352017-01-31 16:46:22 +00002136 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002137 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002138 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002139 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002140 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002141
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002142 /*
2143 * We need to be sure that all dirty pages are written and the server
2144 * has actual ctime, mtime and file length.
2145 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002146 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002147 inode->i_mapping->nrpages != 0) {
2148 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002149 if (rc) {
2150 mapping_set_error(inode->i_mapping, rc);
2151 return rc;
2152 }
Steve French5fe14c82006-11-07 19:26:33 +00002153 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002154
2155 rc = cifs_revalidate_dentry_attr(dentry);
2156 if (rc)
2157 return rc;
2158
2159 generic_fillattr(inode, stat);
Steve Frenche8506d22019-02-28 21:32:15 -06002160 stat->blksize = cifs_sb->bsize;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002161 stat->ino = CIFS_I(inode)->uniqueid;
2162
Steve French6e70e262017-09-21 21:32:29 -05002163 /* old CIFS Unix Extensions doesn't return create time */
2164 if (CIFS_I(inode)->createtime) {
2165 stat->result_mask |= STATX_BTIME;
Arnd Bergmann95390202018-06-19 17:27:58 +02002166 stat->btime =
2167 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
Steve French6e70e262017-09-21 21:32:29 -05002168 }
2169
2170 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2171 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2172 stat->attributes |= STATX_ATTR_COMPRESSED;
2173 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2174 stat->attributes |= STATX_ATTR_ENCRYPTED;
2175
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002176 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002177 * If on a multiuser mount without unix extensions or cifsacl being
2178 * enabled, and the admin hasn't overridden them, set the ownership
2179 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002180 */
2181 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002182 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002183 !tcon->unix_ext) {
2184 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2185 stat->uid = current_fsuid();
2186 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2187 stat->gid = current_fsgid();
2188 }
2189 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190}
2191
Ronnie Sahlberg2f3ebab2019-04-25 16:45:29 +10002192int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
2193 u64 len)
2194{
2195 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2196 struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->vfs_inode.i_sb);
2197 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
2198 struct TCP_Server_Info *server = tcon->ses->server;
2199 struct cifsFileInfo *cfile;
2200 int rc;
2201
2202 /*
2203 * We need to be sure that all dirty pages are written as they
2204 * might fill holes on the server.
2205 */
2206 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
2207 inode->i_mapping->nrpages != 0) {
2208 rc = filemap_fdatawait(inode->i_mapping);
2209 if (rc) {
2210 mapping_set_error(inode->i_mapping, rc);
2211 return rc;
2212 }
2213 }
2214
2215 cfile = find_readable_file(cifs_i, false);
2216 if (cfile == NULL)
2217 return -EINVAL;
2218
2219 if (server->ops->fiemap) {
2220 rc = server->ops->fiemap(tcon, cfile, fei, start, len);
2221 cifsFileInfo_put(cfile);
2222 return rc;
2223 }
2224
2225 cifsFileInfo_put(cfile);
2226 return -ENOTSUPP;
2227}
2228
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002229int cifs_truncate_page(struct address_space *mapping, loff_t from)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002231 pgoff_t index = from >> PAGE_SHIFT;
2232 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 int rc = 0;
2235
2236 page = grab_cache_page(mapping, index);
2237 if (!page)
2238 return -ENOMEM;
2239
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002240 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002242 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 return rc;
2244}
2245
Ronnie Sahlberg8bd0d702020-01-17 11:45:02 +10002246void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002247{
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002248 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2249
Steve Frenchba6a46a2007-02-26 20:06:29 +00002250 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002251 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002252 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002253
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002254 /* Cached inode must be refreshed on truncate */
2255 cifs_i->time = 0;
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002256 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002257}
2258
Jeff Layton8efdbde2008-07-23 21:28:12 +00002259static int
2260cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002261 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002262{
2263 int rc;
2264 struct cifsFileInfo *open_file;
2265 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2266 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002267 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002268 struct cifs_tcon *tcon = NULL;
2269 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002270
2271 /*
2272 * To avoid spurious oplock breaks from server, in the case of
2273 * inodes that we already have open, avoid doing path based
2274 * setting of file size if we can do it by handle.
2275 * This keeps our caching token (oplock) and avoids timeouts
2276 * when the local oplock break takes longer to flush
2277 * writebehind data than the SMB timeout for the SetPathInfo
2278 * request would allow
2279 */
Jeff Layton6508d902010-09-29 19:51:11 -04002280 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002281 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002282 tcon = tlink_tcon(open_file->tlink);
2283 server = tcon->ses->server;
2284 if (server->ops->set_file_size)
2285 rc = server->ops->set_file_size(xid, tcon, open_file,
2286 attrs->ia_size, false);
2287 else
2288 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002289 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002290 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002291 } else
2292 rc = -EINVAL;
2293
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002294 if (!rc)
2295 goto set_size_out;
Jeff Laytonba00ba642010-09-20 16:01:31 -07002296
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002297 if (tcon == NULL) {
2298 tlink = cifs_sb_tlink(cifs_sb);
2299 if (IS_ERR(tlink))
2300 return PTR_ERR(tlink);
2301 tcon = tlink_tcon(tlink);
2302 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002303 }
2304
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002305 /*
2306 * Set file size by pathname rather than by handle either because no
2307 * valid, writeable file handle for it was found or because there was
2308 * an error setting it by handle.
2309 */
2310 if (server->ops->set_path_size)
2311 rc = server->ops->set_path_size(xid, tcon, full_path,
2312 attrs->ia_size, cifs_sb, false);
2313 else
2314 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002315 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002316
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002317 if (tlink)
2318 cifs_put_tlink(tlink);
2319
2320set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002321 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002322 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002323 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002324 cifs_truncate_page(inode->i_mapping, inode->i_size);
2325 }
2326
2327 return rc;
2328}
2329
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002330static int
2331cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2332{
2333 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002334 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002335 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002336 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002337 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2338 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002339 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002340 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002341 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002342 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002343
Al Viro35c265e2014-08-19 20:25:34 -04002344 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2345 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002346
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002347 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002348
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002349 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2350 attrs->ia_valid |= ATTR_FORCE;
2351
Jan Kara31051c82016-05-26 16:55:18 +02002352 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002353 if (rc < 0)
2354 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002355
2356 full_path = build_path_from_dentry(direntry);
2357 if (full_path == NULL) {
2358 rc = -ENOMEM;
2359 goto out;
2360 }
2361
Jeff Layton0f4d6342009-03-26 13:35:37 -04002362 /*
2363 * Attempt to flush data before changing attributes. We need to do
2364 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2365 * ownership or mode then we may also need to do this. Here, we take
2366 * the safe way out and just do the flush on all setattr requests. If
2367 * the flush returns error, store it to report later and continue.
2368 *
2369 * BB: This should be smarter. Why bother flushing pages that
2370 * will be truncated anyway? Also, should we error out here if
2371 * the flush returns error?
2372 */
2373 rc = filemap_write_and_wait(inode->i_mapping);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002374 if (is_interrupt_error(rc)) {
2375 rc = -ERESTARTSYS;
2376 goto out;
2377 }
2378
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002379 mapping_set_error(inode->i_mapping, rc);
2380 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002381
2382 if (attrs->ia_valid & ATTR_SIZE) {
2383 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2384 if (rc != 0)
2385 goto out;
2386 }
2387
2388 /* skip mode change if it's just for clearing setuid/setgid */
2389 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2390 attrs->ia_valid &= ~ATTR_MODE;
2391
2392 args = kmalloc(sizeof(*args), GFP_KERNEL);
2393 if (args == NULL) {
2394 rc = -ENOMEM;
2395 goto out;
2396 }
2397
2398 /* set up the struct */
2399 if (attrs->ia_valid & ATTR_MODE)
2400 args->mode = attrs->ia_mode;
2401 else
2402 args->mode = NO_CHANGE_64;
2403
2404 if (attrs->ia_valid & ATTR_UID)
2405 args->uid = attrs->ia_uid;
2406 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002407 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002408
2409 if (attrs->ia_valid & ATTR_GID)
2410 args->gid = attrs->ia_gid;
2411 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002412 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002413
2414 if (attrs->ia_valid & ATTR_ATIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002415 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002416 else
2417 args->atime = NO_CHANGE_64;
2418
2419 if (attrs->ia_valid & ATTR_MTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002420 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002421 else
2422 args->mtime = NO_CHANGE_64;
2423
2424 if (attrs->ia_valid & ATTR_CTIME)
Arnd Bergmann95390202018-06-19 17:27:58 +02002425 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002426 else
2427 args->ctime = NO_CHANGE_64;
2428
2429 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002430 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002431 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002432 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002433 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002434 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002435 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002436 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002437 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002438 tlink = cifs_sb_tlink(cifs_sb);
2439 if (IS_ERR(tlink)) {
2440 rc = PTR_ERR(tlink);
2441 goto out;
2442 }
2443 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002444 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002445 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002446 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002447 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002448 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002449
Christoph Hellwig10257742010-06-04 11:30:02 +02002450 if (rc)
2451 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002452
Christoph Hellwig10257742010-06-04 11:30:02 +02002453 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002454 attrs->ia_size != i_size_read(inode))
2455 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002456
2457 setattr_copy(inode, attrs);
2458 mark_inode_dirty(inode);
2459
2460 /* force revalidate when any of these times are set since some
2461 of the fs types (eg ext3, fat) do not have fine enough
2462 time granularity to match protocol, and we do not have a
2463 a way (yet) to query the server fs's time granularity (and
2464 whether it rounds times down).
2465 */
2466 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2467 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002468out:
2469 kfree(args);
2470 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002471 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002472 return rc;
2473}
2474
Jeff Layton0510eeb2008-08-02 07:26:12 -04002475static int
2476cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002478 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002479 kuid_t uid = INVALID_UID;
2480 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002481 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002482 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002483 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002484 struct cifsFileInfo *wfile;
2485 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 char *full_path = NULL;
2487 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002488 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002489 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002490
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002491 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492
Colin Ian King63d614a2019-06-24 17:39:43 +01002493 cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
Al Viro35c265e2014-08-19 20:25:34 -04002494 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002495
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002496 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2497 attrs->ia_valid |= ATTR_FORCE;
2498
Jan Kara31051c82016-05-26 16:55:18 +02002499 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002500 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002501 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002502 return rc;
Steve French6473a552005-11-29 20:20:10 -08002503 }
Steve French50c2f752007-07-13 00:33:32 +00002504
Steve French7f573562005-08-30 11:32:14 -07002505 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302507 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002508 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302509 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511
Jeff Layton0f4d6342009-03-26 13:35:37 -04002512 /*
2513 * Attempt to flush data before changing attributes. We need to do
2514 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2515 * ownership or mode then we may also need to do this. Here, we take
2516 * the safe way out and just do the flush on all setattr requests. If
2517 * the flush returns error, store it to report later and continue.
2518 *
2519 * BB: This should be smarter. Why bother flushing pages that
2520 * will be truncated anyway? Also, should we error out here if
2521 * the flush returns error?
2522 */
2523 rc = filemap_write_and_wait(inode->i_mapping);
Pavel Shilovsky9a663962019-01-08 11:15:28 -08002524 if (is_interrupt_error(rc)) {
2525 rc = -ERESTARTSYS;
2526 goto cifs_setattr_exit;
2527 }
2528
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002529 mapping_set_error(inode->i_mapping, rc);
2530 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002531
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002532 if (attrs->ia_valid & ATTR_MTIME) {
2533 rc = cifs_get_writable_file(cifsInode, false, &wfile);
2534 if (!rc) {
2535 tcon = tlink_tcon(wfile->tlink);
2536 rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
2537 cifsFileInfo_put(wfile);
2538 if (rc)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002539 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002540 } else if (rc != -EBADF)
Chuhong Yuan783bf7b2019-10-14 15:15:31 +08002541 goto cifs_setattr_exit;
Ronnie Sahlbergaa081852019-07-19 08:12:11 +10002542 else
2543 rc = 0;
2544 }
2545
Steve French50531442008-03-14 19:21:31 +00002546 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002547 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2548 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002549 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002551
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002552 if (attrs->ia_valid & ATTR_UID)
2553 uid = attrs->ia_uid;
2554
2555 if (attrs->ia_valid & ATTR_GID)
2556 gid = attrs->ia_gid;
2557
Steve French22442172019-07-19 08:15:55 +00002558 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2559 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002560 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002561 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2562 uid, gid);
2563 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002564 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2565 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002566 goto cifs_setattr_exit;
2567 }
2568 }
2569 } else
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002570 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002571 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572
Jeff Laytond32c4f22007-10-18 03:05:22 -07002573 /* skip mode change if it's just for clearing setuid/setgid */
2574 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2575 attrs->ia_valid &= ~ATTR_MODE;
2576
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 mode = attrs->ia_mode;
Steve Frenchcdbce9c82005-11-19 21:04:52 -08002579 rc = 0;
Steve French22442172019-07-19 08:15:55 +00002580 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
2581 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002582 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002583 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002584 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002585 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2586 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002587 goto cifs_setattr_exit;
2588 }
2589 } else
Jeff Layton51328612008-05-22 09:33:34 -04002590 if (((mode & S_IWUGO) == 0) &&
2591 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002592
2593 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2594
Jeff Layton51328612008-05-22 09:33:34 -04002595 /* fix up mode if we're not using dynperm */
2596 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2597 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2598 } else if ((mode & S_IWUGO) &&
2599 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002600
2601 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2602 /* Attributes of 0 are ignored */
2603 if (dosattr == 0)
2604 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002605
2606 /* reset local inode permissions to normal */
2607 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2608 attrs->ia_mode &= ~(S_IALLUGO);
2609 if (S_ISDIR(inode->i_mode))
2610 attrs->ia_mode |=
2611 cifs_sb->mnt_dir_mode;
2612 else
2613 attrs->ia_mode |=
2614 cifs_sb->mnt_file_mode;
2615 }
2616 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2617 /* ignore mode change - ATTR_READONLY hasn't changed */
2618 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 }
2621
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002622 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2623 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2624 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2625 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626
Steve Frenche30dcf32005-09-20 20:49:16 -07002627 /* Even if error on time set, no sense failing the call if
2628 the server would set the time to a reasonable value anyway,
2629 and this check ensures that we are not being called from
2630 sys_utimes in which case we ought to fail the call back to
2631 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002632 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002633 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002634 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 }
2636
2637 /* do not need local check to inode_check_ok since the server does
2638 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002639 if (rc)
2640 goto cifs_setattr_exit;
2641
2642 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002643 attrs->ia_size != i_size_read(inode))
2644 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002645
2646 setattr_copy(inode, attrs);
2647 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002648
Steve Frenche30dcf32005-09-20 20:49:16 -07002649cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002651 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 return rc;
2653}
2654
Jeff Layton0510eeb2008-08-02 07:26:12 -04002655int
2656cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2657{
Al Virofc640052016-04-10 01:33:30 -04002658 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002659 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002660
2661 if (pTcon->unix_ext)
2662 return cifs_setattr_unix(direntry, attrs);
2663
2664 return cifs_setattr_nounix(direntry, attrs);
2665
2666 /* BB: add cifs_setattr_legacy for really old servers */
2667}
2668
Steve French99ee4db2007-02-27 05:35:17 +00002669#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670void cifs_delete_inode(struct inode *inode)
2671{
Joe Perchesf96637b2013-05-04 22:12:25 -05002672 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 /* may have to add back in if and when safe distributed caching of
2674 directories added e.g. via FindNotify */
2675}
Steve French99ee4db2007-02-27 05:35:17 +00002676#endif