blob: f4697f548a394dbf5c42f731bf13bd529c9aaea0 [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);
Deepa Dinamani95582b02018-05-08 19:36:02 -070098 struct timespec ts;
Jeff Laytondf2cf172010-02-12 07:44:16 -050099
Joe Perchesf96637b2013-05-04 22:12:25 -0500100 cifs_dbg(FYI, "%s: revalidating inode %llu\n",
101 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500102
103 if (inode->i_state & I_NEW) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500104 cifs_dbg(FYI, "%s: inode %llu is new\n",
105 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500106 return;
107 }
108
109 /* don't bother with revalidation if we have an oplock */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400110 if (CIFS_CACHE_READ(cifs_i)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500111 cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
112 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500113 return;
114 }
115
116 /* revalidate if mtime or size have changed */
Deepa Dinamani95582b02018-05-08 19:36:02 -0700117 ts = timespec64_to_timespec(inode->i_mtime);
118 if (timespec_equal(&ts, &fattr->cf_mtime) &&
Jeff Laytondf2cf172010-02-12 07:44:16 -0500119 cifs_i->server_eof == fattr->cf_eof) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500120 cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
121 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500122 return;
123 }
124
Joe Perchesf96637b2013-05-04 22:12:25 -0500125 cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
126 __func__, cifs_i->uniqueid);
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400127 set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500128}
129
Jim McDonough74d290d2013-09-21 10:36:10 -0500130/*
131 * copy nlink to the inode, unless it wasn't provided. Provide
132 * sane values if we don't have an existing one and none was provided
133 */
134static void
135cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
136{
137 /*
138 * if we're in a situation where we can't trust what we
139 * got from the server (readdir, some non-unix cases)
140 * fake reasonable values
141 */
142 if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
143 /* only provide fake values on a new inode */
144 if (inode->i_state & I_NEW) {
145 if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
146 set_nlink(inode, 2);
147 else
148 set_nlink(inode, 1);
149 }
150 return;
151 }
152
153 /* we trust the server, so update it */
154 set_nlink(inode, fattr->cf_nlink);
155}
156
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400157/* populate an inode with info from a cifs_fattr struct */
158void
159cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
Christoph Hellwig75f12982008-02-25 20:25:21 +0000160{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400161 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400162 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000163
Jeff Laytondf2cf172010-02-12 07:44:16 -0500164 cifs_revalidate_cache(inode, fattr);
165
Steve Frenchb7ca6922012-08-03 08:43:01 -0500166 spin_lock(&inode->i_lock);
Deepa Dinamani95582b02018-05-08 19:36:02 -0700167 inode->i_atime = timespec_to_timespec64(fattr->cf_atime);
168 inode->i_mtime = timespec_to_timespec64(fattr->cf_mtime);
169 inode->i_ctime = timespec_to_timespec64(fattr->cf_ctime);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400170 inode->i_rdev = fattr->cf_rdev;
Jim McDonough74d290d2013-09-21 10:36:10 -0500171 cifs_nlink_fattr_to_inode(inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400172 inode->i_uid = fattr->cf_uid;
173 inode->i_gid = fattr->cf_gid;
174
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400175 /* if dynperm is set, don't clobber existing mode */
176 if (inode->i_state & I_NEW ||
177 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
178 inode->i_mode = fattr->cf_mode;
179
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400180 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400181
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400182 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
183 cifs_i->time = 0;
184 else
185 cifs_i->time = jiffies;
186
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400187 if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
188 set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
189 else
190 clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000191
Jeff Layton835a36c2010-02-10 16:21:33 -0500192 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000193 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400194 * Can't safely change the file size here if the client is writing to
195 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000196 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400197 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
198 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000199
200 /*
201 * i_blocks is not related to (i_size / i_blksize),
202 * but instead 512 byte (2**9) size is required for
203 * calculating num blocks.
204 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400205 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000206 }
207 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400208
David Howells01c64fe2011-01-14 18:45:47 +0000209 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
210 inode->i_flags |= S_AUTOMOUNT;
Jeff Laytonc2b93e02013-05-07 11:28:31 -0400211 if (inode->i_state & I_NEW)
212 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000213}
214
Jeff Layton4065c802010-05-17 07:18:58 -0400215void
216cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
217{
218 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
219
220 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
221 return;
222
223 fattr->cf_uniqueid = iunique(sb, ROOT_I);
224}
225
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400226/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
227void
228cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
229 struct cifs_sb_info *cifs_sb)
230{
231 memset(fattr, 0, sizeof(*fattr));
232 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
233 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
234 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
235
236 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
237 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
238 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
Steve French6e70e262017-09-21 21:32:29 -0500239 /* old POSIX extensions don't get create time */
240
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400241 fattr->cf_mode = le64_to_cpu(info->Permissions);
242
243 /*
244 * Since we set the inode type below we need to mask off
245 * to avoid strange results if bits set above.
246 */
247 fattr->cf_mode &= ~S_IFMT;
248 switch (le32_to_cpu(info->Type)) {
249 case UNIX_FILE:
250 fattr->cf_mode |= S_IFREG;
251 fattr->cf_dtype = DT_REG;
252 break;
253 case UNIX_SYMLINK:
254 fattr->cf_mode |= S_IFLNK;
255 fattr->cf_dtype = DT_LNK;
256 break;
257 case UNIX_DIR:
258 fattr->cf_mode |= S_IFDIR;
259 fattr->cf_dtype = DT_DIR;
260 break;
261 case UNIX_CHARDEV:
262 fattr->cf_mode |= S_IFCHR;
263 fattr->cf_dtype = DT_CHR;
264 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
265 le64_to_cpu(info->DevMinor) & MINORMASK);
266 break;
267 case UNIX_BLOCKDEV:
268 fattr->cf_mode |= S_IFBLK;
269 fattr->cf_dtype = DT_BLK;
270 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
271 le64_to_cpu(info->DevMinor) & MINORMASK);
272 break;
273 case UNIX_FIFO:
274 fattr->cf_mode |= S_IFIFO;
275 fattr->cf_dtype = DT_FIFO;
276 break;
277 case UNIX_SOCKET:
278 fattr->cf_mode |= S_IFSOCK;
279 fattr->cf_dtype = DT_SOCK;
280 break;
281 default:
282 /* safest to call it a file if we do not know */
283 fattr->cf_mode |= S_IFREG;
284 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500285 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400286 break;
287 }
288
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800289 fattr->cf_uid = cifs_sb->mnt_uid;
290 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
291 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800292 if (id < ((uid_t)-1)) {
293 kuid_t uid = make_kuid(&init_user_ns, id);
294 if (uid_valid(uid))
295 fattr->cf_uid = uid;
296 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800297 }
298
299 fattr->cf_gid = cifs_sb->mnt_gid;
300 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
301 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800302 if (id < ((gid_t)-1)) {
303 kgid_t gid = make_kgid(&init_user_ns, id);
304 if (gid_valid(gid))
305 fattr->cf_gid = gid;
306 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800307 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400308
309 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
310}
Steve Frenchb9a32602008-05-20 21:52:32 +0000311
312/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400313 * Fill a cifs_fattr struct with fake inode info.
314 *
315 * Needed to setup cifs_fattr data for the directory which is the
316 * junction to the new submount (ie to setup the fake directory
317 * which represents a DFS referral).
Steve Frenchb9a32602008-05-20 21:52:32 +0000318 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000319static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400320cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000321{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400322 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000323
Joe Perchesf96637b2013-05-04 22:12:25 -0500324 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000325
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400326 memset(fattr, 0, sizeof(*fattr));
327 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
328 fattr->cf_uid = cifs_sb->mnt_uid;
329 fattr->cf_gid = cifs_sb->mnt_gid;
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700330 ktime_get_real_ts(&fattr->cf_mtime);
331 fattr->cf_mtime = timespec_trunc(fattr->cf_mtime, sb->s_time_gran);
332 fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400333 fattr->cf_nlink = 2;
334 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000335}
336
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700337static int
338cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500339{
340 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400341 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500342 FILE_UNIX_BASIC_INFO find_data;
343 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500344 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500345 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700346 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000347 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500348
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400349 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700350 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500351 if (!rc) {
352 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
353 } else if (rc == -EREMOTE) {
354 cifs_create_dfs_fattr(&fattr, inode->i_sb);
355 rc = 0;
356 }
357
358 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400359 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500360 return rc;
361}
362
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400364 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400365 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400367 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000368 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400369 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000370 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400371 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Joe Perchesf96637b2013-05-04 22:12:25 -0500374 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000375
Jeff Layton7ffec372010-09-29 19:51:11 -0400376 tlink = cifs_sb_tlink(cifs_sb);
377 if (IS_ERR(tlink))
378 return PTR_ERR(tlink);
379 tcon = tlink_tcon(tlink);
380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400382 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +0900383 cifs_sb->local_nls, cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -0400384 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400385
386 if (!rc) {
387 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
388 } else if (rc == -EREMOTE) {
389 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700390 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400391 } else {
392 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000393 }
394
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200395 /* check for Minshall+French symlinks */
396 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000397 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
398 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200399 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000400 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200401 }
402
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400403 if (*pinode == NULL) {
404 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400405 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400406 *pinode = cifs_iget(sb, &fattr);
407 if (!*pinode)
408 rc = -ENOMEM;
409 } else {
410 /* we already have inode, update it */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900411
412 /* if uniqueid is different, return error */
413 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
414 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
415 rc = -ESTALE;
416 goto cgiiu_exit;
417 }
418
419 /* if filetype is different, return error */
420 if (unlikely(((*pinode)->i_mode & S_IFMT) !=
421 (fattr.cf_mode & S_IFMT))) {
422 rc = -ESTALE;
423 goto cgiiu_exit;
424 }
425
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400426 cifs_fattr_to_inode(*pinode, &fattr);
427 }
Steve French0e4bbde2008-05-20 19:50:46 +0000428
Nakajima Akira7196ac12015-04-22 15:24:44 +0900429cgiiu_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 return rc;
431}
432
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400433static int
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400434cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400435 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800436{
437 int rc;
Steve Frenchdb8b6312014-09-22 05:13:55 -0500438 __u32 oplock;
Jeff Layton7ffec372010-09-29 19:51:11 -0400439 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000440 struct cifs_tcon *tcon;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400441 struct cifs_fid fid;
442 struct cifs_open_parms oparms;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000443 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800444 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800445 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000446 char *pbuf;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400447 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800448
449 pbuf = buf;
450
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400451 fattr->cf_mode &= ~S_IFMT;
452
453 if (fattr->cf_eof == 0) {
454 fattr->cf_mode |= S_IFIFO;
455 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800456 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400457 } else if (fattr->cf_eof < 8) {
458 fattr->cf_mode |= S_IFREG;
459 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800460 return -EINVAL; /* EOPNOTSUPP? */
461 }
Steve French50c2f752007-07-13 00:33:32 +0000462
Jeff Layton7ffec372010-09-29 19:51:11 -0400463 tlink = cifs_sb_tlink(cifs_sb);
464 if (IS_ERR(tlink))
465 return PTR_ERR(tlink);
466 tcon = tlink_tcon(tlink);
467
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400468 oparms.tcon = tcon;
469 oparms.cifs_sb = cifs_sb;
470 oparms.desired_access = GENERIC_READ;
471 oparms.create_options = CREATE_NOT_DIR;
472 oparms.disposition = FILE_OPEN;
473 oparms.path = path;
474 oparms.fid = &fid;
475 oparms.reconnect = false;
476
Steve Frenchdb8b6312014-09-22 05:13:55 -0500477 if (tcon->ses->server->oplocks)
478 oplock = REQ_OPLOCK;
479 else
480 oplock = 0;
481 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400482 if (rc) {
Steve Frenchdb8b6312014-09-22 05:13:55 -0500483 cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400484 cifs_put_tlink(tlink);
485 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800486 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400487
488 /* Read header */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400489 io_parms.netfid = fid.netfid;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400490 io_parms.pid = current->tgid;
491 io_parms.tcon = tcon;
492 io_parms.offset = 0;
493 io_parms.length = 24;
494
Steve Frenchdb8b6312014-09-22 05:13:55 -0500495 rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
496 &bytes_read, &pbuf, &buf_type);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400497 if ((rc == 0) && (bytes_read >= 8)) {
498 if (memcmp("IntxBLK", pbuf, 8) == 0) {
499 cifs_dbg(FYI, "Block device\n");
500 fattr->cf_mode |= S_IFBLK;
501 fattr->cf_dtype = DT_BLK;
502 if (bytes_read == 24) {
503 /* we have enough to decode dev num */
504 __u64 mjr; /* major */
505 __u64 mnr; /* minor */
506 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
507 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
508 fattr->cf_rdev = MKDEV(mjr, mnr);
509 }
510 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
511 cifs_dbg(FYI, "Char device\n");
512 fattr->cf_mode |= S_IFCHR;
513 fattr->cf_dtype = DT_CHR;
514 if (bytes_read == 24) {
515 /* we have enough to decode dev num */
516 __u64 mjr; /* major */
517 __u64 mnr; /* minor */
518 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
519 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
520 fattr->cf_rdev = MKDEV(mjr, mnr);
521 }
522 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
523 cifs_dbg(FYI, "Symlink\n");
524 fattr->cf_mode |= S_IFLNK;
525 fattr->cf_dtype = DT_LNK;
526 } else {
527 fattr->cf_mode |= S_IFREG; /* file? */
528 fattr->cf_dtype = DT_REG;
529 rc = -EOPNOTSUPP;
530 }
531 } else {
532 fattr->cf_mode |= S_IFREG; /* then it is a file */
533 fattr->cf_dtype = DT_REG;
534 rc = -EOPNOTSUPP; /* or some unknown SFU type */
535 }
Steve Frenchdb8b6312014-09-22 05:13:55 -0500536
537 tcon->ses->server->ops->close(xid, tcon, &fid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400538 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800539 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800540}
541
Steve French9e294f12005-11-17 16:59:21 -0800542#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
543
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400544/*
545 * Fetch mode bits as provided by SFU.
546 *
547 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
548 */
549static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400550 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800551{
Steve French3020a1f2005-11-18 11:31:10 -0800552#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800553 ssize_t rc;
554 char ea_value[4];
555 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400556 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000557 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800558
Jeff Layton7ffec372010-09-29 19:51:11 -0400559 tlink = cifs_sb_tlink(cifs_sb);
560 if (IS_ERR(tlink))
561 return PTR_ERR(tlink);
562 tcon = tlink_tcon(tlink);
563
Steve Frenchd979f3b2014-02-01 23:27:18 -0600564 if (tcon->ses->server->ops->query_all_EAs == NULL) {
565 cifs_put_tlink(tlink);
566 return -EOPNOTSUPP;
567 }
568
569 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
570 "SETFILEBITS", ea_value, 4 /* size of buf */,
Steve French67b4c882017-05-12 20:59:10 -0500571 cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400572 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000573 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800574 return (int)rc;
575 else if (rc > 3) {
576 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400577 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500578 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
579 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400580 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500581 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800582 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400583
584 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800585#else
586 return -EOPNOTSUPP;
587#endif
Steve French9e294f12005-11-17 16:59:21 -0800588}
589
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400590/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000591static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400592cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700593 struct super_block *sb, bool adjust_tz,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400594 bool symlink)
Steve Frenchb9a32602008-05-20 21:52:32 +0000595{
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700596 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French96daf2b2011-05-27 04:34:02 +0000597 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700598
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400599 memset(fattr, 0, sizeof(*fattr));
600 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
601 if (info->DeletePending)
602 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000603
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400604 if (info->LastAccessTime)
605 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700606 else {
607 ktime_get_real_ts(&fattr->cf_atime);
608 fattr->cf_atime = timespec_trunc(fattr->cf_atime, sb->s_time_gran);
609 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400610
611 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
612 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
613
614 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700615 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
616 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400617 }
618
619 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
620 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500621 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400622
Jim McDonough74d290d2013-09-21 10:36:10 -0500623 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400624
625 if (symlink) {
626 fattr->cf_mode = S_IFLNK;
627 fattr->cf_dtype = DT_LNK;
628 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400629 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
630 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300631 /*
632 * Server can return wrong NumberOfLinks value for directories
633 * when Unix extensions are disabled - fake it.
634 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500635 if (!tcon->unix_ext)
636 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400637 } else {
638 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
639 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400640
Jeff Laytond0c280d2009-07-09 01:46:44 -0400641 /* clear write bits if ATTR_READONLY is set */
642 if (fattr->cf_cifsattrs & ATTR_READONLY)
643 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400644
Jim McDonough74d290d2013-09-21 10:36:10 -0500645 /*
646 * Don't accept zero nlink from non-unix servers unless
647 * delete is pending. Instead mark it as unknown.
648 */
649 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
650 !info->DeletePending) {
651 cifs_dbg(1, "bogus file nlink value %u\n",
Steve French6658b9f2013-07-04 14:38:48 -0500652 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500653 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500654 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300655 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400656
657 fattr->cf_uid = cifs_sb->mnt_uid;
658 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000659}
660
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700661static int
662cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500663{
664 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400665 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500666 FILE_ALL_INFO find_data;
667 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500668 struct inode *inode = file_inode(filp);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700669 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000670 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700671 struct TCP_Server_Info *server = tcon->ses->server;
672
673 if (!server->ops->query_file_info)
674 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500675
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400676 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700677 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400678 switch (rc) {
679 case 0:
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700680 cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400681 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400682 break;
683 case -EREMOTE:
684 cifs_create_dfs_fattr(&fattr, inode->i_sb);
685 rc = 0;
686 break;
687 case -EOPNOTSUPP:
688 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500689 /*
690 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000691 * for now, just skip revalidating and mark inode for
692 * immediate reval.
693 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500694 rc = 0;
695 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400696 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500697 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400698 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500699
700 /*
701 * don't bother with SFU junk here -- just mark inode as needing
702 * revalidation.
703 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500704 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
705 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
706 cifs_fattr_to_inode(inode, &fattr);
707cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400708 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500709 return rc;
710}
711
Steve French7ea884c2018-03-31 18:13:38 -0500712/* Simple function to return a 64 bit hash of string. Rarely called */
713static __u64 simple_hashstr(const char *str)
714{
Geert Uytterhoeven3995bbf2018-04-05 14:57:11 +0200715 const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
Steve French7ea884c2018-03-31 18:13:38 -0500716 __u64 hash = 0;
717
718 while (*str)
719 hash = (hash + (__u64) *str++) * hash_mult;
720
721 return hash;
722}
723
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400724int
725cifs_get_inode_info(struct inode **inode, const char *full_path,
726 FILE_ALL_INFO *data, struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600727 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500729 bool validinum = false;
730 __u16 srchflgs;
731 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400732 struct cifs_tcon *tcon;
733 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400734 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400737 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400738 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500739 struct cifs_search_info *srchinf = NULL;
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400740 bool symlink = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Jeff Layton7ffec372010-09-29 19:51:11 -0400742 tlink = cifs_sb_tlink(cifs_sb);
743 if (IS_ERR(tlink))
744 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400745 tcon = tlink_tcon(tlink);
746 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400747
Joe Perchesf96637b2013-05-04 22:12:25 -0500748 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400750 if ((data == NULL) && (*inode != NULL)) {
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +1000751 if (CIFS_CACHE_READ(CIFS_I(*inode)) &&
752 CIFS_I(*inode)->time != 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500753 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400754 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 }
756 }
757
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400758 /* if inode info is not passed, get it from server */
759 if (data == NULL) {
760 if (!server->ops->query_path_info) {
761 rc = -ENOSYS;
762 goto cgii_exit;
763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400765 if (buf == NULL) {
766 rc = -ENOMEM;
767 goto cgii_exit;
768 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400769 data = (FILE_ALL_INFO *)buf;
770 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400771 data, &adjust_tz, &symlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400773
774 if (!rc) {
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700775 cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400776 symlink);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400777 } else if (rc == -EREMOTE) {
778 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000779 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500780 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
781 srchinf = kzalloc(sizeof(struct cifs_search_info),
782 GFP_KERNEL);
783 if (srchinf == NULL) {
784 rc = -ENOMEM;
785 goto cgii_exit;
786 }
787
788 srchinf->endOfSearch = false;
789 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
790
791 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
792 CIFS_SEARCH_CLOSE_AT_END |
793 CIFS_SEARCH_BACKUP_SEARCH;
794
795 rc = CIFSFindFirst(xid, tcon, full_path,
796 cifs_sb, NULL, srchflgs, srchinf, false);
797 if (!rc) {
798 data =
799 (FILE_ALL_INFO *)srchinf->srch_entries_start;
800
801 cifs_dir_info_to_fattr(&fattr,
802 (FILE_DIRECTORY_INFO *)data, cifs_sb);
803 fattr.cf_uniqueid = le64_to_cpu(
804 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
805 validinum = true;
806
807 cifs_buf_release(srchinf->ntwrk_buf_start);
808 }
809 kfree(srchinf);
Steve French4c5930e2015-03-30 22:03:06 -0500810 if (rc)
811 goto cgii_exit;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500812 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000813 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400815 /*
816 * If an inode wasn't passed in, then get the inode number
817 *
818 * Is an i_ino of zero legal? Can we use that to check if the server
819 * supports returning inode numbers? Are there other sanity checks we
820 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400821 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400822 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000823 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500824 if (validinum == false) {
825 if (server->ops->get_srv_inum)
826 tmprc = server->ops->get_srv_inum(xid,
827 tcon, cifs_sb, full_path,
828 &fattr.cf_uniqueid, data);
829 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500830 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
831 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500832 fattr.cf_uniqueid = iunique(sb, ROOT_I);
833 cifs_autodisable_serverino(cifs_sb);
Steve French7ea884c2018-03-31 18:13:38 -0500834 } else if ((fattr.cf_uniqueid == 0) &&
835 strlen(full_path) == 0) {
836 /* some servers ret bad root ino ie 0 */
837 cifs_dbg(FYI, "Invalid (0) inodenum\n");
838 fattr.cf_flags |=
839 CIFS_FATTR_FAKE_ROOT_INO;
840 fattr.cf_uniqueid =
841 simple_hashstr(tcon->treeName);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500842 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500843 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500844 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400845 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000846 } else {
847 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
848 validinum == false && server->ops->get_srv_inum) {
849 /*
850 * Pass a NULL tcon to ensure we don't make a round
851 * trip to the server. This only works for SMB2+.
852 */
853 tmprc = server->ops->get_srv_inum(xid,
854 NULL, cifs_sb, full_path,
855 &fattr.cf_uniqueid, data);
856 if (tmprc)
857 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve French7ea884c2018-03-31 18:13:38 -0500858 else if ((fattr.cf_uniqueid == 0) &&
859 strlen(full_path) == 0) {
860 /*
861 * Reuse existing root inode num since
862 * inum zero for root causes ls of . and .. to
863 * not be returned
864 */
865 cifs_dbg(FYI, "Srv ret 0 inode num for root\n");
866 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
867 }
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000868 } else
869 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
870 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000871
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400872 /* query for SFU type info if supported and needed */
873 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
874 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
875 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
876 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500877 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000878 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000879
Jeff Layton79df1ba2010-12-06 12:52:08 -0500880#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000881 /* fill in 0777 bits from ACL */
882 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400883 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600884 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500885 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
886 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600887 goto cgii_exit;
888 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000889 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500890#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400891
892 /* fill in remaining high mode bits e.g. SUID, VTX */
893 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
894 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
895
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200896 /* check for Minshall+French symlinks */
897 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000898 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
899 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200900 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000901 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200902 }
903
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400904 if (!*inode) {
905 *inode = cifs_iget(sb, &fattr);
906 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400907 rc = -ENOMEM;
908 } else {
Nakajima Akira7196ac12015-04-22 15:24:44 +0900909 /* we already have inode, update it */
910
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000911 /* if uniqueid is different, return error */
912 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
913 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
914 rc = -ESTALE;
915 goto cgii_exit;
916 }
917
Nakajima Akira7196ac12015-04-22 15:24:44 +0900918 /* if filetype is different, return error */
919 if (unlikely(((*inode)->i_mode & S_IFMT) !=
920 (fattr.cf_mode & S_IFMT))) {
921 rc = -ESTALE;
922 goto cgii_exit;
923 }
924
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400925 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000926 }
927
Igor Mammedov79626702008-03-09 03:44:18 +0000928cgii_exit:
Steve French7ea884c2018-03-31 18:13:38 -0500929 if ((*inode) && ((*inode)->i_ino == 0))
930 cifs_dbg(FYI, "inode number of zero returned\n");
931
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400933 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 return rc;
935}
936
Steve French7f8ed422007-09-28 22:28:55 +0000937static const struct inode_operations cifs_ipc_inode_ops = {
938 .lookup = cifs_lookup,
939};
940
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400941static int
942cifs_find_inode(struct inode *inode, void *opaque)
943{
944 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
945
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400946 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400947 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
948 return 0;
949
Jeff Layton20054bd2011-01-07 11:30:27 -0500950 /* use createtime like an i_generation field */
951 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
952 return 0;
953
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400954 /* don't match inode of different type */
955 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
956 return 0;
957
Jeff Layton5acfec22010-08-02 17:43:54 -0400958 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400959 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400960 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400961
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400962 return 1;
963}
964
965static int
966cifs_init_inode(struct inode *inode, void *opaque)
967{
968 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
969
970 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500971 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400972 return 0;
973}
974
Jeff Layton5acfec22010-08-02 17:43:54 -0400975/*
976 * walk dentry list for an inode and report whether it has aliases that
977 * are hashed. We use this to determine if a directory inode can actually
978 * be used.
979 */
980static bool
981inode_has_hashed_dentries(struct inode *inode)
982{
983 struct dentry *dentry;
984
Nick Piggin873feea2011-01-07 17:50:06 +1100985 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -0400986 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400987 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100988 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400989 return true;
990 }
991 }
Nick Piggin873feea2011-01-07 17:50:06 +1100992 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400993 return false;
994}
995
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400996/* Given fattrs, get a corresponding inode */
997struct inode *
998cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
999{
1000 unsigned long hash;
1001 struct inode *inode;
1002
Jeff Layton3d694382010-05-11 14:59:55 -04001003retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -05001004 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001005
1006 /* hash down to 32-bits on 32-bit arch */
1007 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
1008
1009 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001010 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001011 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -04001012 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -04001013 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -04001014
1015 if (inode_has_hashed_dentries(inode)) {
1016 cifs_autodisable_serverino(CIFS_SB(sb));
1017 iput(inode);
1018 fattr->cf_uniqueid = iunique(sb, ROOT_I);
1019 goto retry_iget5_locked;
1020 }
Jeff Layton3d694382010-05-11 14:59:55 -04001021 }
1022
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001023 cifs_fattr_to_inode(inode, fattr);
Linus Torvalds1751e8a2017-11-27 13:05:09 -08001024 if (sb->s_flags & SB_NOATIME)
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001025 inode->i_flags |= S_NOATIME | S_NOCMTIME;
1026 if (inode->i_state & I_NEW) {
1027 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +00001028#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301029 /* initialize per-inode cache cookie pointer */
1030 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +00001031#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001032 unlock_new_inode(inode);
1033 }
1034 }
1035
1036 return inode;
1037}
1038
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001040struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001042 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001043 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001044 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001045 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001046 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001047 char *path = NULL;
1048 int len;
1049
1050 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1051 && cifs_sb->prepath) {
1052 len = strlen(cifs_sb->prepath);
1053 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1054 if (path == NULL)
1055 return ERR_PTR(-ENOMEM);
1056 path[0] = '/';
1057 memcpy(path+1, cifs_sb->prepath, len);
1058 } else {
1059 path = kstrdup("", GFP_KERNEL);
1060 if (path == NULL)
1061 return ERR_PTR(-ENOMEM);
1062 }
David Howellsce634ab2008-02-07 00:15:33 -08001063
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001064 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001065 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001066 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001067 /* some servers mistakenly claim POSIX support */
1068 if (rc != -EOPNOTSUPP)
1069 goto iget_no_retry;
1070 cifs_dbg(VFS, "server does not support POSIX extensions");
1071 tcon->unix_ext = false;
1072 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001073
Aurelien Aptela6b50582016-05-25 19:59:09 +02001074 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
1075 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001076
1077iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001078 if (!inode) {
1079 inode = ERR_PTR(rc);
1080 goto out;
1081 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001082
Steve French0ccd4802010-07-16 04:31:02 +00001083#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301084 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001085 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001086#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301087
Aurelien Aptelb327a712018-01-24 13:46:10 +01001088 if (rc && tcon->pipe) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001089 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001090 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001091 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001092 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001093 inode->i_op = &cifs_ipc_inode_ops;
1094 inode->i_fop = &simple_dir_operations;
1095 inode->i_uid = cifs_sb->mnt_uid;
1096 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001097 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001098 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001099 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001100 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001101 }
1102
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001103out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001104 kfree(path);
Phillip Potter31cd1062018-03-17 21:06:56 +00001105 free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001106 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107}
1108
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001109int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001110cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001111 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001112{
Steve French388e57b2008-09-16 23:50:58 +00001113 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001114 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001115 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001116 FILE_BASIC_INFO info_buf;
1117
Steve French1adcb712009-02-25 14:19:56 +00001118 if (attrs == NULL)
1119 return -EINVAL;
1120
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001121 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1122 if (!server->ops->set_file_info)
1123 return -ENOSYS;
1124
Steve French388e57b2008-09-16 23:50:58 +00001125 if (attrs->ia_valid & ATTR_ATIME) {
1126 set_time = true;
1127 info_buf.LastAccessTime =
Deepa Dinamani95582b02018-05-08 19:36:02 -07001128 cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_atime)));
Steve French388e57b2008-09-16 23:50:58 +00001129 } else
1130 info_buf.LastAccessTime = 0;
1131
1132 if (attrs->ia_valid & ATTR_MTIME) {
1133 set_time = true;
1134 info_buf.LastWriteTime =
Deepa Dinamani95582b02018-05-08 19:36:02 -07001135 cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_mtime)));
Steve French388e57b2008-09-16 23:50:58 +00001136 } else
1137 info_buf.LastWriteTime = 0;
1138
1139 /*
1140 * Samba throws this field away, but windows may actually use it.
1141 * Do not set ctime unless other time stamps are changed explicitly
1142 * (i.e. by utimes()) since we would then have a mix of client and
1143 * server times.
1144 */
1145 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001146 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001147 info_buf.ChangeTime =
Deepa Dinamani95582b02018-05-08 19:36:02 -07001148 cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_ctime)));
Steve French388e57b2008-09-16 23:50:58 +00001149 } else
1150 info_buf.ChangeTime = 0;
1151
1152 info_buf.CreationTime = 0; /* don't change */
1153 info_buf.Attributes = cpu_to_le32(dosattr);
1154
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001155 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001156}
1157
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001158/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001159 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001160 * and rename it to a random name that hopefully won't conflict with
1161 * anything else.
1162 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001163int
1164cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1165 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001166{
1167 int oplock = 0;
1168 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001169 struct cifs_fid fid;
1170 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001171 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001172 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1173 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001174 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001175 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001176 __u32 dosattr, origattr;
1177 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001178
Jeff Layton7ffec372010-09-29 19:51:11 -04001179 tlink = cifs_sb_tlink(cifs_sb);
1180 if (IS_ERR(tlink))
1181 return PTR_ERR(tlink);
1182 tcon = tlink_tcon(tlink);
1183
Sachin Prabhuc483a982013-03-05 19:25:56 +00001184 /*
1185 * We cannot rename the file if the server doesn't support
1186 * CAP_INFOLEVEL_PASSTHRU
1187 */
1188 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1189 rc = -EBUSY;
1190 goto out;
1191 }
1192
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001193 oparms.tcon = tcon;
1194 oparms.cifs_sb = cifs_sb;
1195 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1196 oparms.create_options = CREATE_NOT_DIR;
1197 oparms.disposition = FILE_OPEN;
1198 oparms.path = full_path;
1199 oparms.fid = &fid;
1200 oparms.reconnect = false;
1201
1202 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001203 if (rc != 0)
1204 goto out;
1205
Steve French32709582008-10-20 00:44:19 +00001206 origattr = cifsInode->cifsAttrs;
1207 if (origattr == 0)
1208 origattr |= ATTR_NORMAL;
1209
1210 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001211 if (dosattr == 0)
1212 dosattr |= ATTR_NORMAL;
1213 dosattr |= ATTR_HIDDEN;
1214
Steve French32709582008-10-20 00:44:19 +00001215 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1216 if (dosattr != origattr) {
1217 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1218 if (info_buf == NULL) {
1219 rc = -ENOMEM;
1220 goto out_close;
1221 }
1222 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001223 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001224 current->tgid);
1225 /* although we would like to mark the file hidden
1226 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001227 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001228 cifsInode->cifsAttrs = dosattr;
1229 else
1230 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001231 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001232
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001233 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001234 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1235 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001236 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001237 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001238 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001239 goto undo_setattr;
1240 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001241
Steve French32709582008-10-20 00:44:19 +00001242 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001243 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001244 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001245 current->tgid);
1246 /*
1247 * some samba versions return -ENOENT when we try to set the
1248 * file disposition here. Likely a samba bug, but work around
1249 * it for now. This means that some cifsXXX files may hang
1250 * around after they shouldn't.
1251 *
1252 * BB: remove this hack after more servers have the fix
1253 */
1254 if (rc == -ENOENT)
1255 rc = 0;
1256 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001257 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001258 goto undo_rename;
1259 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001260 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001261 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001262
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001263out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001264 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001265out:
Steve French32709582008-10-20 00:44:19 +00001266 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001267 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001268 return rc;
Steve French32709582008-10-20 00:44:19 +00001269
1270 /*
1271 * reset everything back to the original state. Don't bother
1272 * dealing with errors here since we can't do anything about
1273 * them anyway.
1274 */
1275undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001276 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001277 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001278undo_setattr:
1279 if (dosattr != origattr) {
1280 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001281 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001282 current->tgid))
1283 cifsInode->cifsAttrs = origattr;
1284 }
1285
1286 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001287}
1288
Steve Frenchb7ca6922012-08-03 08:43:01 -05001289/* copied from fs/nfs/dir.c with small changes */
1290static void
1291cifs_drop_nlink(struct inode *inode)
1292{
1293 spin_lock(&inode->i_lock);
1294 if (inode->i_nlink > 0)
1295 drop_nlink(inode);
1296 spin_unlock(&inode->i_lock);
1297}
Steve Frenchff694522009-04-20 19:45:13 +00001298
1299/*
David Howells2b0143b2015-03-17 22:25:59 +00001300 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001301 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001302 * if that fails we can not attempt the fall back mechanisms on EACCESS
1303 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001304 * unlink on negative dentries currently.
1305 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001306int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307{
1308 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001309 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001311 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001312 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001313 struct super_block *sb = dir->i_sb;
1314 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001315 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001316 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001317 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001318 struct iattr *attrs = NULL;
1319 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
Joe Perchesf96637b2013-05-04 22:12:25 -05001321 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Jeff Layton7ffec372010-09-29 19:51:11 -04001323 tlink = cifs_sb_tlink(cifs_sb);
1324 if (IS_ERR(tlink))
1325 return PTR_ERR(tlink);
1326 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001327 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001328
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001329 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Jeff Layton5f0319a2008-09-16 14:05:16 -04001331 /* Unlink can be called from rename so we can not take the
1332 * sb->s_vfs_rename_mutex here */
1333 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301335 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001336 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 }
Steve French2d785a52007-07-15 01:48:57 +00001338
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001339 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1340 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001341 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001342 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001343 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001344 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001345 if ((rc == 0) || (rc == -ENOENT))
1346 goto psx_del_no_retry;
1347 }
1348
Steve French60502472008-10-07 18:42:52 +00001349retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001350 if (!server->ops->unlink) {
1351 rc = -ENOSYS;
1352 goto psx_del_no_retry;
1353 }
1354
1355 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001356
Steve French2d785a52007-07-15 01:48:57 +00001357psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001359 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001360 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001362 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001363 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001364 if (server->ops->rename_pending_delete) {
1365 rc = server->ops->rename_pending_delete(full_path,
1366 dentry, xid);
1367 if (rc == 0)
1368 cifs_drop_nlink(inode);
1369 }
Steve Frenchff694522009-04-20 19:45:13 +00001370 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001371 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1372 if (attrs == NULL) {
1373 rc = -ENOMEM;
1374 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 }
Steve French388e57b2008-09-16 23:50:58 +00001376
1377 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001378 cifs_inode = CIFS_I(inode);
1379 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001380 if (origattr == 0)
1381 origattr |= ATTR_NORMAL;
1382 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001383 if (dosattr == 0)
1384 dosattr |= ATTR_NORMAL;
1385 dosattr |= ATTR_HIDDEN;
1386
1387 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001388 if (rc != 0)
1389 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001390
1391 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 }
Steve French60502472008-10-07 18:42:52 +00001393
1394 /* undo the setattr if we errored out and it's needed */
1395 if (rc != 0 && dosattr != 0)
1396 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1397
Steve French388e57b2008-09-16 23:50:58 +00001398out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001399 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001400 cifs_inode = CIFS_I(inode);
1401 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001402 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001403 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001404 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001405 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001406 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001407 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001408unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001410 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001411 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001412 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 return rc;
1414}
1415
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001416static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001417cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001418 const char *full_path, struct cifs_sb_info *cifs_sb,
1419 struct cifs_tcon *tcon, const unsigned int xid)
1420{
1421 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001422 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001423
1424 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001425 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001426 xid);
1427 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001428 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1429 xid, NULL);
1430
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001431 if (rc)
1432 return rc;
1433
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001434 /*
1435 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001436 * from the server or was set bogus. Also, since this is a brand new
1437 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001438 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001439 if (inode->i_nlink < 2)
1440 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001441 mode &= ~current_umask();
1442 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001443 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001444 mode |= S_ISGID;
1445
1446 if (tcon->unix_ext) {
1447 struct cifs_unix_set_info_args args = {
1448 .mode = mode,
1449 .ctime = NO_CHANGE_64,
1450 .atime = NO_CHANGE_64,
1451 .mtime = NO_CHANGE_64,
1452 .device = 0,
1453 };
1454 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001455 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001456 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001457 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001458 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001459 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001460 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001461 args.uid = INVALID_UID; /* no change */
1462 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001463 }
1464 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1465 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001466 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001467 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001468 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001469 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001470 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001471 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001472 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001473 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1474 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001475
Jeff Layton101b92d2012-09-19 06:22:45 -07001476 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1477 inode->i_uid = current_fsuid();
1478 if (inode->i_mode & S_ISGID)
1479 inode->i_gid = parent->i_gid;
1480 else
1481 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001482 }
1483 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001484 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001485 return rc;
1486}
1487
1488static int
1489cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1490 const char *full_path, struct cifs_sb_info *cifs_sb,
1491 struct cifs_tcon *tcon, const unsigned int xid)
1492{
1493 int rc = 0;
1494 u32 oplock = 0;
1495 FILE_UNIX_BASIC_INFO *info = NULL;
1496 struct inode *newinode = NULL;
1497 struct cifs_fattr fattr;
1498
1499 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1500 if (info == NULL) {
1501 rc = -ENOMEM;
1502 goto posix_mkdir_out;
1503 }
1504
1505 mode &= ~current_umask();
1506 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1507 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001508 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001509 if (rc == -EOPNOTSUPP)
1510 goto posix_mkdir_out;
1511 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001512 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001513 d_drop(dentry);
1514 goto posix_mkdir_out;
1515 }
1516
1517 if (info->Type == cpu_to_le32(-1))
1518 /* no return info, go query for it */
1519 goto posix_mkdir_get_info;
1520 /*
1521 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1522 * need to set uid/gid.
1523 */
1524
1525 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1526 cifs_fill_uniqueid(inode->i_sb, &fattr);
1527 newinode = cifs_iget(inode->i_sb, &fattr);
1528 if (!newinode)
1529 goto posix_mkdir_get_info;
1530
1531 d_instantiate(dentry, newinode);
1532
1533#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001534 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1535 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001536
1537 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001538 cifs_dbg(FYI, "unexpected number of links %d\n",
1539 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001540#endif
1541
1542posix_mkdir_out:
1543 kfree(info);
1544 return rc;
1545posix_mkdir_get_info:
1546 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1547 xid);
1548 goto posix_mkdir_out;
1549}
1550
Al Viro18bb1db2011-07-26 01:41:39 -04001551int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001553 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001554 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001556 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001557 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001558 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001559 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
Joe Perchesf96637b2013-05-04 22:12:25 -05001561 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1562 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001565 tlink = cifs_sb_tlink(cifs_sb);
1566 if (IS_ERR(tlink))
1567 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001568 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001569
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001570 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
Steve French7f573562005-08-30 11:32:14 -07001572 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301574 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001575 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 }
Steve French50c2f752007-07-13 00:33:32 +00001577
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001578 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1579 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001580 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1581 tcon, xid);
1582 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001583 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001584 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001585
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001586 server = tcon->ses->server;
1587
1588 if (!server->ops->mkdir) {
1589 rc = -ENOSYS;
1590 goto mkdir_out;
1591 }
1592
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001594 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001596 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001598 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001600
1601 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1602 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001603mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001604 /*
1605 * Force revalidate to get parent dir info when needed since cached
1606 * attributes are invalid now.
1607 */
1608 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001610 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001611 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 return rc;
1613}
1614
1615int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1616{
1617 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001618 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001620 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001621 struct cifs_tcon *tcon;
1622 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 char *full_path = NULL;
1624 struct cifsInodeInfo *cifsInode;
1625
Joe Perchesf96637b2013-05-04 22:12:25 -05001626 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001628 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629
Steve French7f573562005-08-30 11:32:14 -07001630 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301632 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001633 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 }
1635
Jeff Layton7ffec372010-09-29 19:51:11 -04001636 cifs_sb = CIFS_SB(inode->i_sb);
1637 tlink = cifs_sb_tlink(cifs_sb);
1638 if (IS_ERR(tlink)) {
1639 rc = PTR_ERR(tlink);
1640 goto rmdir_exit;
1641 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001642 tcon = tlink_tcon(tlink);
1643 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001644
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001645 if (!server->ops->rmdir) {
1646 rc = -ENOSYS;
1647 cifs_put_tlink(tlink);
1648 goto rmdir_exit;
1649 }
1650
1651 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001652 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653
1654 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001655 spin_lock(&d_inode(direntry)->i_lock);
1656 i_size_write(d_inode(direntry), 0);
1657 clear_nlink(d_inode(direntry));
1658 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 }
1660
David Howells2b0143b2015-03-17 22:25:59 +00001661 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001662 /* force revalidate to go get info when needed */
1663 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001664
1665 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001666 /*
1667 * Force revalidate to get parent dir info when needed since cached
1668 * attributes are invalid now.
1669 */
1670 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001671
David Howells2b0143b2015-03-17 22:25:59 +00001672 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001673 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674
Jeff Layton7ffec372010-09-29 19:51:11 -04001675rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001677 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 return rc;
1679}
1680
Steve Frenchee2fd962008-09-23 18:23:33 +00001681static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001682cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1683 const char *from_path, struct dentry *to_dentry,
1684 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001685{
1686 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001687 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001688 struct cifs_tcon *tcon;
1689 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001690 struct cifs_fid fid;
1691 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001692 int oplock, rc;
1693
Jeff Layton7ffec372010-09-29 19:51:11 -04001694 tlink = cifs_sb_tlink(cifs_sb);
1695 if (IS_ERR(tlink))
1696 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001697 tcon = tlink_tcon(tlink);
1698 server = tcon->ses->server;
1699
1700 if (!server->ops->rename)
1701 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001702
Steve Frenchee2fd962008-09-23 18:23:33 +00001703 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001704 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001705
1706 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001707 * Don't bother with rename by filehandle unless file is busy and
1708 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001709 * rename by filehandle to various Windows servers.
1710 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001711 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001712 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001713
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001714 /* open-file renames don't work across directories */
1715 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001716 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001717
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001718 oparms.tcon = tcon;
1719 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00001720 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001721 oparms.desired_access = DELETE;
1722 oparms.create_options = CREATE_NOT_DIR;
1723 oparms.disposition = FILE_OPEN;
1724 oparms.path = from_path;
1725 oparms.fid = &fid;
1726 oparms.reconnect = false;
1727
1728 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00001729 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001730 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001731 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001732 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001733 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001734 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001735do_rename_exit:
1736 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001737 return rc;
1738}
1739
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001740int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001741cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
1742 struct inode *target_dir, struct dentry *target_dentry,
1743 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001745 char *from_name = NULL;
1746 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001747 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001748 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001749 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001750 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1751 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001752 unsigned int xid;
1753 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001755 if (flags & ~RENAME_NOREPLACE)
1756 return -EINVAL;
1757
Jeff Layton639e7a92010-09-03 11:50:09 -04001758 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001759 tlink = cifs_sb_tlink(cifs_sb);
1760 if (IS_ERR(tlink))
1761 return PTR_ERR(tlink);
1762 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001764 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001765
1766 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001767 * we already have the rename sem so we do not need to
1768 * grab it again here to protect the path integrity
1769 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001770 from_name = build_path_from_dentry(source_dentry);
1771 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 rc = -ENOMEM;
1773 goto cifs_rename_exit;
1774 }
1775
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001776 to_name = build_path_from_dentry(target_dentry);
1777 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001778 rc = -ENOMEM;
1779 goto cifs_rename_exit;
1780 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001782 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1783 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001784
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001785 /*
1786 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
1787 */
1788 if (flags & RENAME_NOREPLACE)
1789 goto cifs_rename_exit;
1790
Jeff Layton14121bd2008-10-20 14:45:22 -04001791 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001792 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001793 * Are src and dst hardlinks of same inode? We can only tell
1794 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001795 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001796 info_buf_source =
Kees Cook6da2ec52018-06-12 13:55:00 -07001797 kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
Jeff Layton14121bd2008-10-20 14:45:22 -04001798 GFP_KERNEL);
1799 if (info_buf_source == NULL) {
1800 rc = -ENOMEM;
1801 goto cifs_rename_exit;
1802 }
1803
1804 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001805 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1806 info_buf_source,
1807 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001808 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04001809 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001810 goto unlink_target;
1811
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001812 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1813 info_buf_target,
1814 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001815 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04001816
Jeff Layton8d281ef2008-10-22 13:57:01 -04001817 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001818 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001819 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001820 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001821 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001822 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001823 }
1824 /*
1825 * else ... BB we could add the same check for Windows by
1826 * checking the UniqueId via FILE_INTERNAL_INFO
1827 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001828
Jeff Layton14121bd2008-10-20 14:45:22 -04001829unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001830 /* Try unlinking the target dentry if it's not negative */
David Howells2b0143b2015-03-17 22:25:59 +00001831 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04001832 if (d_is_dir(target_dentry))
1833 tmprc = cifs_rmdir(target_dir, target_dentry);
1834 else
1835 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001836 if (tmprc)
1837 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001838 rc = cifs_do_rename(xid, source_dentry, from_name,
1839 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 }
1841
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001842 /* force revalidate to go get info when needed */
1843 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1844
1845 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001846 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001847
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001849 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001850 kfree(from_name);
1851 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001852 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001853 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 return rc;
1855}
1856
Jeff Laytondf2cf172010-02-12 07:44:16 -05001857static bool
1858cifs_inode_needs_reval(struct inode *inode)
1859{
1860 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301861 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001862
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10001863 if (cifs_i->time == 0)
1864 return true;
1865
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001866 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001867 return false;
1868
1869 if (!lookupCacheEnabled)
1870 return true;
1871
Jeff Laytona87c9ad2014-03-26 07:24:23 -07001872 if (!cifs_sb->actimeo)
1873 return true;
1874
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301875 if (!time_in_range(jiffies, cifs_i->time,
1876 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001877 return true;
1878
Jeff Laytondb192722010-05-17 14:51:49 -04001879 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301880 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001881 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1882 return true;
1883
Jeff Laytondf2cf172010-02-12 07:44:16 -05001884 return false;
1885}
1886
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301887/*
1888 * Zap the cache. Called when invalid_mapping flag is set.
1889 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001890int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001891cifs_invalidate_mapping(struct inode *inode)
1892{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001893 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001894
Jeff Laytondf2cf172010-02-12 07:44:16 -05001895 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001896 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001897 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001898 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1899 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001900 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001901
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301902 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001903 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001904}
1905
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001906/**
1907 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
1908 * @word: long word containing the bit lock
1909 */
1910static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01001911cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001912{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001913 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01001914 if (signal_pending_state(mode, current))
1915 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001916 return 0;
1917}
1918
Jeff Laytone284e532014-04-30 09:31:46 -04001919int
1920cifs_revalidate_mapping(struct inode *inode)
1921{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001922 int rc;
1923 unsigned long *flags = &CIFS_I(inode)->flags;
1924
NeilBrown74316202014-07-07 15:16:04 +10001925 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
1926 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001927 if (rc)
1928 return rc;
1929
1930 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
1931 rc = cifs_invalidate_mapping(inode);
1932 if (rc)
1933 set_bit(CIFS_INO_INVALID_MAPPING, flags);
1934 }
1935
1936 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07001937 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001938 wake_up_bit(flags, CIFS_INO_LOCK);
1939
1940 return rc;
1941}
1942
1943int
1944cifs_zap_mapping(struct inode *inode)
1945{
1946 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
1947 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04001948}
1949
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001950int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001951{
1952 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001953 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001954 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001955
1956 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001957 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001958
Jeff Layton13cfb732010-09-29 19:51:11 -04001959 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001960 rc = cifs_get_file_info_unix(filp);
1961 else
1962 rc = cifs_get_file_info(filp);
1963
Jeff Laytonabab0952010-02-12 07:44:18 -05001964 return rc;
1965}
1966
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001967int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001969 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001970 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00001971 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001972 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001973 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974
Jeff Laytondf2cf172010-02-12 07:44:16 -05001975 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 return -ENOENT;
1977
Jeff Laytondf2cf172010-02-12 07:44:16 -05001978 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001979 return rc;
1980
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001981 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
1983 /* can not safely grab the rename sem here if rename calls revalidate
1984 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001985 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301987 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001988 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001990
Joe Perchesf96637b2013-05-04 22:12:25 -05001991 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1992 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02001993 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
Jeff Layton0d424ad2010-09-20 16:01:35 -07001995 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001996 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1997 else
1998 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1999 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002001out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002003 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 return rc;
2005}
2006
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002007int cifs_revalidate_file(struct file *filp)
2008{
2009 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002010 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002011
2012 rc = cifs_revalidate_file_attr(filp);
2013 if (rc)
2014 return rc;
2015
Jeff Laytone284e532014-04-30 09:31:46 -04002016 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002017}
2018
2019/* revalidate a dentry's inode attributes */
2020int cifs_revalidate_dentry(struct dentry *dentry)
2021{
2022 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002023 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002024
2025 rc = cifs_revalidate_dentry_attr(dentry);
2026 if (rc)
2027 return rc;
2028
Jeff Laytone284e532014-04-30 09:31:46 -04002029 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002030}
2031
David Howellsa528d352017-01-31 16:46:22 +00002032int cifs_getattr(const struct path *path, struct kstat *stat,
2033 u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034{
David Howellsa528d352017-01-31 16:46:22 +00002035 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002036 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002037 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002038 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002039 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002040
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002041 /*
2042 * We need to be sure that all dirty pages are written and the server
2043 * has actual ctime, mtime and file length.
2044 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002045 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002046 inode->i_mapping->nrpages != 0) {
2047 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002048 if (rc) {
2049 mapping_set_error(inode->i_mapping, rc);
2050 return rc;
2051 }
Steve French5fe14c82006-11-07 19:26:33 +00002052 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002053
2054 rc = cifs_revalidate_dentry_attr(dentry);
2055 if (rc)
2056 return rc;
2057
2058 generic_fillattr(inode, stat);
2059 stat->blksize = CIFS_MAX_MSGSIZE;
2060 stat->ino = CIFS_I(inode)->uniqueid;
2061
Steve French6e70e262017-09-21 21:32:29 -05002062 /* old CIFS Unix Extensions doesn't return create time */
2063 if (CIFS_I(inode)->createtime) {
2064 stat->result_mask |= STATX_BTIME;
Deepa Dinamani95582b02018-05-08 19:36:02 -07002065 stat->btime = timespec_to_timespec64(
2066 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime)));
Steve French6e70e262017-09-21 21:32:29 -05002067 }
2068
2069 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2070 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2071 stat->attributes |= STATX_ATTR_COMPRESSED;
2072 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2073 stat->attributes |= STATX_ATTR_ENCRYPTED;
2074
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002075 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002076 * If on a multiuser mount without unix extensions or cifsacl being
2077 * enabled, and the admin hasn't overridden them, set the ownership
2078 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002079 */
2080 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002081 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002082 !tcon->unix_ext) {
2083 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2084 stat->uid = current_fsuid();
2085 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2086 stat->gid = current_fsgid();
2087 }
2088 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089}
2090
2091static int cifs_truncate_page(struct address_space *mapping, loff_t from)
2092{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002093 pgoff_t index = from >> PAGE_SHIFT;
2094 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 int rc = 0;
2097
2098 page = grab_cache_page(mapping, index);
2099 if (!page)
2100 return -ENOMEM;
2101
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002102 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002104 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 return rc;
2106}
2107
Christoph Hellwig1b947462010-07-18 17:51:21 -04002108static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002109{
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002110 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
2111
Steve Frenchba6a46a2007-02-26 20:06:29 +00002112 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002113 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002114 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002115
Ronnie Sahlberg57c55cd2018-05-24 06:54:27 +10002116 /* Cached inode must be refreshed on truncate */
2117 cifs_i->time = 0;
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002118 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002119}
2120
Jeff Layton8efdbde2008-07-23 21:28:12 +00002121static int
2122cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002123 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002124{
2125 int rc;
2126 struct cifsFileInfo *open_file;
2127 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2128 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002129 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002130 struct cifs_tcon *tcon = NULL;
2131 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002132
2133 /*
2134 * To avoid spurious oplock breaks from server, in the case of
2135 * inodes that we already have open, avoid doing path based
2136 * setting of file size if we can do it by handle.
2137 * This keeps our caching token (oplock) and avoids timeouts
2138 * when the local oplock break takes longer to flush
2139 * writebehind data than the SMB timeout for the SetPathInfo
2140 * request would allow
2141 */
Jeff Layton6508d902010-09-29 19:51:11 -04002142 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002143 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002144 tcon = tlink_tcon(open_file->tlink);
2145 server = tcon->ses->server;
2146 if (server->ops->set_file_size)
2147 rc = server->ops->set_file_size(xid, tcon, open_file,
2148 attrs->ia_size, false);
2149 else
2150 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002151 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002152 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002153 } else
2154 rc = -EINVAL;
2155
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002156 if (!rc)
2157 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07002158
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002159 if (tcon == NULL) {
2160 tlink = cifs_sb_tlink(cifs_sb);
2161 if (IS_ERR(tlink))
2162 return PTR_ERR(tlink);
2163 tcon = tlink_tcon(tlink);
2164 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002165 }
2166
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002167 /*
2168 * Set file size by pathname rather than by handle either because no
2169 * valid, writeable file handle for it was found or because there was
2170 * an error setting it by handle.
2171 */
2172 if (server->ops->set_path_size)
2173 rc = server->ops->set_path_size(xid, tcon, full_path,
2174 attrs->ia_size, cifs_sb, false);
2175 else
2176 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002177 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002178
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002179 if (tlink)
2180 cifs_put_tlink(tlink);
2181
2182set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002183 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002184 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002185 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002186 cifs_truncate_page(inode->i_mapping, inode->i_size);
2187 }
2188
2189 return rc;
2190}
2191
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002192static int
2193cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2194{
2195 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002196 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002197 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002198 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002199 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2200 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002201 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002202 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002203 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002204 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002205
Al Viro35c265e2014-08-19 20:25:34 -04002206 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2207 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002208
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002209 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002210
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002211 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2212 attrs->ia_valid |= ATTR_FORCE;
2213
Jan Kara31051c82016-05-26 16:55:18 +02002214 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002215 if (rc < 0)
2216 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002217
2218 full_path = build_path_from_dentry(direntry);
2219 if (full_path == NULL) {
2220 rc = -ENOMEM;
2221 goto out;
2222 }
2223
Jeff Layton0f4d6342009-03-26 13:35:37 -04002224 /*
2225 * Attempt to flush data before changing attributes. We need to do
2226 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2227 * ownership or mode then we may also need to do this. Here, we take
2228 * the safe way out and just do the flush on all setattr requests. If
2229 * the flush returns error, store it to report later and continue.
2230 *
2231 * BB: This should be smarter. Why bother flushing pages that
2232 * will be truncated anyway? Also, should we error out here if
2233 * the flush returns error?
2234 */
2235 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002236 mapping_set_error(inode->i_mapping, rc);
2237 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002238
2239 if (attrs->ia_valid & ATTR_SIZE) {
2240 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2241 if (rc != 0)
2242 goto out;
2243 }
2244
2245 /* skip mode change if it's just for clearing setuid/setgid */
2246 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2247 attrs->ia_valid &= ~ATTR_MODE;
2248
2249 args = kmalloc(sizeof(*args), GFP_KERNEL);
2250 if (args == NULL) {
2251 rc = -ENOMEM;
2252 goto out;
2253 }
2254
2255 /* set up the struct */
2256 if (attrs->ia_valid & ATTR_MODE)
2257 args->mode = attrs->ia_mode;
2258 else
2259 args->mode = NO_CHANGE_64;
2260
2261 if (attrs->ia_valid & ATTR_UID)
2262 args->uid = attrs->ia_uid;
2263 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002264 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002265
2266 if (attrs->ia_valid & ATTR_GID)
2267 args->gid = attrs->ia_gid;
2268 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002269 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002270
2271 if (attrs->ia_valid & ATTR_ATIME)
Deepa Dinamani95582b02018-05-08 19:36:02 -07002272 args->atime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_atime));
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002273 else
2274 args->atime = NO_CHANGE_64;
2275
2276 if (attrs->ia_valid & ATTR_MTIME)
Deepa Dinamani95582b02018-05-08 19:36:02 -07002277 args->mtime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_mtime));
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002278 else
2279 args->mtime = NO_CHANGE_64;
2280
2281 if (attrs->ia_valid & ATTR_CTIME)
Deepa Dinamani95582b02018-05-08 19:36:02 -07002282 args->ctime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_ctime));
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002283 else
2284 args->ctime = NO_CHANGE_64;
2285
2286 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002287 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002288 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002289 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002290 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002291 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002292 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002293 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002294 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002295 tlink = cifs_sb_tlink(cifs_sb);
2296 if (IS_ERR(tlink)) {
2297 rc = PTR_ERR(tlink);
2298 goto out;
2299 }
2300 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002301 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002302 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002303 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002304 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002305 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002306
Christoph Hellwig10257742010-06-04 11:30:02 +02002307 if (rc)
2308 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002309
Christoph Hellwig10257742010-06-04 11:30:02 +02002310 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002311 attrs->ia_size != i_size_read(inode))
2312 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002313
2314 setattr_copy(inode, attrs);
2315 mark_inode_dirty(inode);
2316
2317 /* force revalidate when any of these times are set since some
2318 of the fs types (eg ext3, fat) do not have fine enough
2319 time granularity to match protocol, and we do not have a
2320 a way (yet) to query the server fs's time granularity (and
2321 whether it rounds times down).
2322 */
2323 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2324 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002325out:
2326 kfree(args);
2327 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002328 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002329 return rc;
2330}
2331
Jeff Layton0510eeb2008-08-02 07:26:12 -04002332static int
2333cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002335 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002336 kuid_t uid = INVALID_UID;
2337 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002338 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002339 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002340 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 char *full_path = NULL;
2342 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002343 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002344 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002345
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002346 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347
Al Viro35c265e2014-08-19 20:25:34 -04002348 cifs_dbg(FYI, "setattr on file %pd attrs->iavalid 0x%x\n",
2349 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002350
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002351 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2352 attrs->ia_valid |= ATTR_FORCE;
2353
Jan Kara31051c82016-05-26 16:55:18 +02002354 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002355 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002356 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002357 return rc;
Steve French6473a552005-11-29 20:20:10 -08002358 }
Steve French50c2f752007-07-13 00:33:32 +00002359
Steve French7f573562005-08-30 11:32:14 -07002360 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302362 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002363 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302364 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
Jeff Layton0f4d6342009-03-26 13:35:37 -04002367 /*
2368 * Attempt to flush data before changing attributes. We need to do
2369 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2370 * ownership or mode then we may also need to do this. Here, we take
2371 * the safe way out and just do the flush on all setattr requests. If
2372 * the flush returns error, store it to report later and continue.
2373 *
2374 * BB: This should be smarter. Why bother flushing pages that
2375 * will be truncated anyway? Also, should we error out here if
2376 * the flush returns error?
2377 */
2378 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002379 mapping_set_error(inode->i_mapping, rc);
2380 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002381
Steve French50531442008-03-14 19:21:31 +00002382 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002383 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2384 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002385 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002387
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002388 if (attrs->ia_valid & ATTR_UID)
2389 uid = attrs->ia_uid;
2390
2391 if (attrs->ia_valid & ATTR_GID)
2392 gid = attrs->ia_gid;
2393
2394#ifdef CONFIG_CIFS_ACL
2395 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002396 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002397 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2398 uid, gid);
2399 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002400 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2401 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002402 goto cifs_setattr_exit;
2403 }
2404 }
2405 } else
2406#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002407 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002408 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409
Jeff Laytond32c4f22007-10-18 03:05:22 -07002410 /* skip mode change if it's just for clearing setuid/setgid */
2411 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2412 attrs->ia_valid &= ~ATTR_MODE;
2413
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002416 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002417#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002418 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002419 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002420 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002421 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002422 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2423 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002424 goto cifs_setattr_exit;
2425 }
2426 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002427#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002428 if (((mode & S_IWUGO) == 0) &&
2429 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002430
2431 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2432
Jeff Layton51328612008-05-22 09:33:34 -04002433 /* fix up mode if we're not using dynperm */
2434 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2435 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2436 } else if ((mode & S_IWUGO) &&
2437 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002438
2439 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2440 /* Attributes of 0 are ignored */
2441 if (dosattr == 0)
2442 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002443
2444 /* reset local inode permissions to normal */
2445 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2446 attrs->ia_mode &= ~(S_IALLUGO);
2447 if (S_ISDIR(inode->i_mode))
2448 attrs->ia_mode |=
2449 cifs_sb->mnt_dir_mode;
2450 else
2451 attrs->ia_mode |=
2452 cifs_sb->mnt_file_mode;
2453 }
2454 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2455 /* ignore mode change - ATTR_READONLY hasn't changed */
2456 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 }
2459
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002460 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2461 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2462 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2463 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464
Steve Frenche30dcf32005-09-20 20:49:16 -07002465 /* Even if error on time set, no sense failing the call if
2466 the server would set the time to a reasonable value anyway,
2467 and this check ensures that we are not being called from
2468 sys_utimes in which case we ought to fail the call back to
2469 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002470 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002471 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002472 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 }
2474
2475 /* do not need local check to inode_check_ok since the server does
2476 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002477 if (rc)
2478 goto cifs_setattr_exit;
2479
2480 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002481 attrs->ia_size != i_size_read(inode))
2482 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002483
2484 setattr_copy(inode, attrs);
2485 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002486
Steve Frenche30dcf32005-09-20 20:49:16 -07002487cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002489 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 return rc;
2491}
2492
Jeff Layton0510eeb2008-08-02 07:26:12 -04002493int
2494cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2495{
Al Virofc640052016-04-10 01:33:30 -04002496 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002497 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002498
2499 if (pTcon->unix_ext)
2500 return cifs_setattr_unix(direntry, attrs);
2501
2502 return cifs_setattr_nounix(direntry, attrs);
2503
2504 /* BB: add cifs_setattr_legacy for really old servers */
2505}
2506
Steve French99ee4db2007-02-27 05:35:17 +00002507#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508void cifs_delete_inode(struct inode *inode)
2509{
Joe Perchesf96637b2013-05-04 22:12:25 -05002510 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 /* may have to add back in if and when safe distributed caching of
2512 directories added e.g. via FindNotify */
2513}
Steve French99ee4db2007-02-27 05:35:17 +00002514#endif