blob: 6be9a7cfaf0e23bf90ad680efecf471c5fd6d64e [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)) {
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400751 if (CIFS_CACHE_READ(CIFS_I(*inode))) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500752 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400753 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 }
755 }
756
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400757 /* if inode info is not passed, get it from server */
758 if (data == NULL) {
759 if (!server->ops->query_path_info) {
760 rc = -ENOSYS;
761 goto cgii_exit;
762 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400764 if (buf == NULL) {
765 rc = -ENOMEM;
766 goto cgii_exit;
767 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400768 data = (FILE_ALL_INFO *)buf;
769 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400770 data, &adjust_tz, &symlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400772
773 if (!rc) {
Deepa Dinamanie37fea52017-05-08 15:59:16 -0700774 cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400775 symlink);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400776 } else if (rc == -EREMOTE) {
777 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000778 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500779 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
780 srchinf = kzalloc(sizeof(struct cifs_search_info),
781 GFP_KERNEL);
782 if (srchinf == NULL) {
783 rc = -ENOMEM;
784 goto cgii_exit;
785 }
786
787 srchinf->endOfSearch = false;
788 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
789
790 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
791 CIFS_SEARCH_CLOSE_AT_END |
792 CIFS_SEARCH_BACKUP_SEARCH;
793
794 rc = CIFSFindFirst(xid, tcon, full_path,
795 cifs_sb, NULL, srchflgs, srchinf, false);
796 if (!rc) {
797 data =
798 (FILE_ALL_INFO *)srchinf->srch_entries_start;
799
800 cifs_dir_info_to_fattr(&fattr,
801 (FILE_DIRECTORY_INFO *)data, cifs_sb);
802 fattr.cf_uniqueid = le64_to_cpu(
803 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
804 validinum = true;
805
806 cifs_buf_release(srchinf->ntwrk_buf_start);
807 }
808 kfree(srchinf);
Steve French4c5930e2015-03-30 22:03:06 -0500809 if (rc)
810 goto cgii_exit;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500811 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000812 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400814 /*
815 * If an inode wasn't passed in, then get the inode number
816 *
817 * Is an i_ino of zero legal? Can we use that to check if the server
818 * supports returning inode numbers? Are there other sanity checks we
819 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400820 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400821 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000822 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500823 if (validinum == false) {
824 if (server->ops->get_srv_inum)
825 tmprc = server->ops->get_srv_inum(xid,
826 tcon, cifs_sb, full_path,
827 &fattr.cf_uniqueid, data);
828 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500829 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
830 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500831 fattr.cf_uniqueid = iunique(sb, ROOT_I);
832 cifs_autodisable_serverino(cifs_sb);
Steve French7ea884c2018-03-31 18:13:38 -0500833 } else if ((fattr.cf_uniqueid == 0) &&
834 strlen(full_path) == 0) {
835 /* some servers ret bad root ino ie 0 */
836 cifs_dbg(FYI, "Invalid (0) inodenum\n");
837 fattr.cf_flags |=
838 CIFS_FATTR_FAKE_ROOT_INO;
839 fattr.cf_uniqueid =
840 simple_hashstr(tcon->treeName);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500841 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500842 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500843 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400844 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000845 } else {
846 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
847 validinum == false && server->ops->get_srv_inum) {
848 /*
849 * Pass a NULL tcon to ensure we don't make a round
850 * trip to the server. This only works for SMB2+.
851 */
852 tmprc = server->ops->get_srv_inum(xid,
853 NULL, cifs_sb, full_path,
854 &fattr.cf_uniqueid, data);
855 if (tmprc)
856 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve French7ea884c2018-03-31 18:13:38 -0500857 else if ((fattr.cf_uniqueid == 0) &&
858 strlen(full_path) == 0) {
859 /*
860 * Reuse existing root inode num since
861 * inum zero for root causes ls of . and .. to
862 * not be returned
863 */
864 cifs_dbg(FYI, "Srv ret 0 inode num for root\n");
865 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
866 }
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000867 } else
868 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
869 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000870
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400871 /* query for SFU type info if supported and needed */
872 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
873 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
874 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
875 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500876 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000877 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000878
Jeff Layton79df1ba2010-12-06 12:52:08 -0500879#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000880 /* fill in 0777 bits from ACL */
881 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400882 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600883 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500884 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
885 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600886 goto cgii_exit;
887 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000888 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500889#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400890
891 /* fill in remaining high mode bits e.g. SUID, VTX */
892 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
893 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
894
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200895 /* check for Minshall+French symlinks */
896 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000897 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
898 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200899 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000900 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200901 }
902
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400903 if (!*inode) {
904 *inode = cifs_iget(sb, &fattr);
905 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400906 rc = -ENOMEM;
907 } else {
Nakajima Akira7196ac12015-04-22 15:24:44 +0900908 /* we already have inode, update it */
909
Ross Lagerwalla108471b2015-12-02 14:46:08 +0000910 /* if uniqueid is different, return error */
911 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
912 CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
913 rc = -ESTALE;
914 goto cgii_exit;
915 }
916
Nakajima Akira7196ac12015-04-22 15:24:44 +0900917 /* if filetype is different, return error */
918 if (unlikely(((*inode)->i_mode & S_IFMT) !=
919 (fattr.cf_mode & S_IFMT))) {
920 rc = -ESTALE;
921 goto cgii_exit;
922 }
923
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400924 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000925 }
926
Igor Mammedov79626702008-03-09 03:44:18 +0000927cgii_exit:
Steve French7ea884c2018-03-31 18:13:38 -0500928 if ((*inode) && ((*inode)->i_ino == 0))
929 cifs_dbg(FYI, "inode number of zero returned\n");
930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400932 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 return rc;
934}
935
Steve French7f8ed422007-09-28 22:28:55 +0000936static const struct inode_operations cifs_ipc_inode_ops = {
937 .lookup = cifs_lookup,
938};
939
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400940static int
941cifs_find_inode(struct inode *inode, void *opaque)
942{
943 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
944
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400945 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400946 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
947 return 0;
948
Jeff Layton20054bd2011-01-07 11:30:27 -0500949 /* use createtime like an i_generation field */
950 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
951 return 0;
952
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400953 /* don't match inode of different type */
954 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
955 return 0;
956
Jeff Layton5acfec22010-08-02 17:43:54 -0400957 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400958 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400959 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400960
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400961 return 1;
962}
963
964static int
965cifs_init_inode(struct inode *inode, void *opaque)
966{
967 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
968
969 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500970 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400971 return 0;
972}
973
Jeff Layton5acfec22010-08-02 17:43:54 -0400974/*
975 * walk dentry list for an inode and report whether it has aliases that
976 * are hashed. We use this to determine if a directory inode can actually
977 * be used.
978 */
979static bool
980inode_has_hashed_dentries(struct inode *inode)
981{
982 struct dentry *dentry;
983
Nick Piggin873feea2011-01-07 17:50:06 +1100984 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -0400985 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400986 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100987 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400988 return true;
989 }
990 }
Nick Piggin873feea2011-01-07 17:50:06 +1100991 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400992 return false;
993}
994
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400995/* Given fattrs, get a corresponding inode */
996struct inode *
997cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
998{
999 unsigned long hash;
1000 struct inode *inode;
1001
Jeff Layton3d694382010-05-11 14:59:55 -04001002retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -05001003 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001004
1005 /* hash down to 32-bits on 32-bit arch */
1006 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
1007
1008 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001009 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -04001010 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -04001011 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -04001012 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -04001013
1014 if (inode_has_hashed_dentries(inode)) {
1015 cifs_autodisable_serverino(CIFS_SB(sb));
1016 iput(inode);
1017 fattr->cf_uniqueid = iunique(sb, ROOT_I);
1018 goto retry_iget5_locked;
1019 }
Jeff Layton3d694382010-05-11 14:59:55 -04001020 }
1021
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001022 cifs_fattr_to_inode(inode, fattr);
Linus Torvalds1751e8a2017-11-27 13:05:09 -08001023 if (sb->s_flags & SB_NOATIME)
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001024 inode->i_flags |= S_NOATIME | S_NOCMTIME;
1025 if (inode->i_state & I_NEW) {
1026 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +00001027#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301028 /* initialize per-inode cache cookie pointer */
1029 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +00001030#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001031 unlock_new_inode(inode);
1032 }
1033 }
1034
1035 return inode;
1036}
1037
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -06001039struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001041 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -07001042 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001043 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -08001044 long rc;
Steve French96daf2b2011-05-27 04:34:02 +00001045 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Aurelien Aptela6b50582016-05-25 19:59:09 +02001046 char *path = NULL;
1047 int len;
1048
1049 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
1050 && cifs_sb->prepath) {
1051 len = strlen(cifs_sb->prepath);
1052 path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
1053 if (path == NULL)
1054 return ERR_PTR(-ENOMEM);
1055 path[0] = '/';
1056 memcpy(path+1, cifs_sb->prepath, len);
1057 } else {
1058 path = kstrdup("", GFP_KERNEL);
1059 if (path == NULL)
1060 return ERR_PTR(-ENOMEM);
1061 }
David Howellsce634ab2008-02-07 00:15:33 -08001062
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001063 xid = get_xid();
Steve Frenchb5b374e2014-10-06 01:01:03 -05001064 if (tcon->unix_ext) {
Aurelien Aptela6b50582016-05-25 19:59:09 +02001065 rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001066 /* some servers mistakenly claim POSIX support */
1067 if (rc != -EOPNOTSUPP)
1068 goto iget_no_retry;
1069 cifs_dbg(VFS, "server does not support POSIX extensions");
1070 tcon->unix_ext = false;
1071 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -04001072
Aurelien Aptela6b50582016-05-25 19:59:09 +02001073 convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
1074 rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
Steve Frenchb5b374e2014-10-06 01:01:03 -05001075
1076iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001077 if (!inode) {
1078 inode = ERR_PTR(rc);
1079 goto out;
1080 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001081
Steve French0ccd4802010-07-16 04:31:02 +00001082#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301083 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -07001084 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +00001085#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +05301086
Aurelien Aptelb327a712018-01-24 13:46:10 +01001087 if (rc && tcon->pipe) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001088 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -05001089 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +00001090 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +02001091 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +00001092 inode->i_op = &cifs_ipc_inode_ops;
1093 inode->i_fop = &simple_dir_operations;
1094 inode->i_uid = cifs_sb->mnt_uid;
1095 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -05001096 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +00001097 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -08001098 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001099 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +00001100 }
1101
Oskar Schirmera7851ce2010-11-10 21:06:13 +00001102out:
Aurelien Aptela6b50582016-05-25 19:59:09 +02001103 kfree(path);
Phillip Potter31cd1062018-03-17 21:06:56 +00001104 free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001105 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106}
1107
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001108int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001109cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001110 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001111{
Steve French388e57b2008-09-16 23:50:58 +00001112 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001113 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001114 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001115 FILE_BASIC_INFO info_buf;
1116
Steve French1adcb712009-02-25 14:19:56 +00001117 if (attrs == NULL)
1118 return -EINVAL;
1119
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001120 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1121 if (!server->ops->set_file_info)
1122 return -ENOSYS;
1123
Steve French388e57b2008-09-16 23:50:58 +00001124 if (attrs->ia_valid & ATTR_ATIME) {
1125 set_time = true;
1126 info_buf.LastAccessTime =
Deepa Dinamani95582b02018-05-08 19:36:02 -07001127 cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_atime)));
Steve French388e57b2008-09-16 23:50:58 +00001128 } else
1129 info_buf.LastAccessTime = 0;
1130
1131 if (attrs->ia_valid & ATTR_MTIME) {
1132 set_time = true;
1133 info_buf.LastWriteTime =
Deepa Dinamani95582b02018-05-08 19:36:02 -07001134 cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_mtime)));
Steve French388e57b2008-09-16 23:50:58 +00001135 } else
1136 info_buf.LastWriteTime = 0;
1137
1138 /*
1139 * Samba throws this field away, but windows may actually use it.
1140 * Do not set ctime unless other time stamps are changed explicitly
1141 * (i.e. by utimes()) since we would then have a mix of client and
1142 * server times.
1143 */
1144 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001145 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001146 info_buf.ChangeTime =
Deepa Dinamani95582b02018-05-08 19:36:02 -07001147 cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_ctime)));
Steve French388e57b2008-09-16 23:50:58 +00001148 } else
1149 info_buf.ChangeTime = 0;
1150
1151 info_buf.CreationTime = 0; /* don't change */
1152 info_buf.Attributes = cpu_to_le32(dosattr);
1153
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001154 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001155}
1156
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001157/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001158 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001159 * and rename it to a random name that hopefully won't conflict with
1160 * anything else.
1161 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001162int
1163cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1164 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001165{
1166 int oplock = 0;
1167 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001168 struct cifs_fid fid;
1169 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001170 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001171 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1172 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001173 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001174 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001175 __u32 dosattr, origattr;
1176 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001177
Jeff Layton7ffec372010-09-29 19:51:11 -04001178 tlink = cifs_sb_tlink(cifs_sb);
1179 if (IS_ERR(tlink))
1180 return PTR_ERR(tlink);
1181 tcon = tlink_tcon(tlink);
1182
Sachin Prabhuc483a982013-03-05 19:25:56 +00001183 /*
1184 * We cannot rename the file if the server doesn't support
1185 * CAP_INFOLEVEL_PASSTHRU
1186 */
1187 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1188 rc = -EBUSY;
1189 goto out;
1190 }
1191
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001192 oparms.tcon = tcon;
1193 oparms.cifs_sb = cifs_sb;
1194 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1195 oparms.create_options = CREATE_NOT_DIR;
1196 oparms.disposition = FILE_OPEN;
1197 oparms.path = full_path;
1198 oparms.fid = &fid;
1199 oparms.reconnect = false;
1200
1201 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001202 if (rc != 0)
1203 goto out;
1204
Steve French32709582008-10-20 00:44:19 +00001205 origattr = cifsInode->cifsAttrs;
1206 if (origattr == 0)
1207 origattr |= ATTR_NORMAL;
1208
1209 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001210 if (dosattr == 0)
1211 dosattr |= ATTR_NORMAL;
1212 dosattr |= ATTR_HIDDEN;
1213
Steve French32709582008-10-20 00:44:19 +00001214 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1215 if (dosattr != origattr) {
1216 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1217 if (info_buf == NULL) {
1218 rc = -ENOMEM;
1219 goto out_close;
1220 }
1221 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001222 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001223 current->tgid);
1224 /* although we would like to mark the file hidden
1225 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001226 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001227 cifsInode->cifsAttrs = dosattr;
1228 else
1229 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001230 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001231
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001232 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001233 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1234 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001235 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001236 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001237 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001238 goto undo_setattr;
1239 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001240
Steve French32709582008-10-20 00:44:19 +00001241 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001242 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001243 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001244 current->tgid);
1245 /*
1246 * some samba versions return -ENOENT when we try to set the
1247 * file disposition here. Likely a samba bug, but work around
1248 * it for now. This means that some cifsXXX files may hang
1249 * around after they shouldn't.
1250 *
1251 * BB: remove this hack after more servers have the fix
1252 */
1253 if (rc == -ENOENT)
1254 rc = 0;
1255 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001256 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001257 goto undo_rename;
1258 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001259 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001260 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001261
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001262out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001263 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001264out:
Steve French32709582008-10-20 00:44:19 +00001265 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001266 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001267 return rc;
Steve French32709582008-10-20 00:44:19 +00001268
1269 /*
1270 * reset everything back to the original state. Don't bother
1271 * dealing with errors here since we can't do anything about
1272 * them anyway.
1273 */
1274undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001275 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001276 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001277undo_setattr:
1278 if (dosattr != origattr) {
1279 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001280 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001281 current->tgid))
1282 cifsInode->cifsAttrs = origattr;
1283 }
1284
1285 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001286}
1287
Steve Frenchb7ca6922012-08-03 08:43:01 -05001288/* copied from fs/nfs/dir.c with small changes */
1289static void
1290cifs_drop_nlink(struct inode *inode)
1291{
1292 spin_lock(&inode->i_lock);
1293 if (inode->i_nlink > 0)
1294 drop_nlink(inode);
1295 spin_unlock(&inode->i_lock);
1296}
Steve Frenchff694522009-04-20 19:45:13 +00001297
1298/*
David Howells2b0143b2015-03-17 22:25:59 +00001299 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001300 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001301 * if that fails we can not attempt the fall back mechanisms on EACCESS
1302 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001303 * unlink on negative dentries currently.
1304 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001305int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306{
1307 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001308 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001310 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001311 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001312 struct super_block *sb = dir->i_sb;
1313 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001314 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001315 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001316 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001317 struct iattr *attrs = NULL;
1318 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
Joe Perchesf96637b2013-05-04 22:12:25 -05001320 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
Jeff Layton7ffec372010-09-29 19:51:11 -04001322 tlink = cifs_sb_tlink(cifs_sb);
1323 if (IS_ERR(tlink))
1324 return PTR_ERR(tlink);
1325 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001326 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001327
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001328 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
Jeff Layton5f0319a2008-09-16 14:05:16 -04001330 /* Unlink can be called from rename so we can not take the
1331 * sb->s_vfs_rename_mutex here */
1332 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301334 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001335 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 }
Steve French2d785a52007-07-15 01:48:57 +00001337
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001338 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1339 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001340 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001341 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001342 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001343 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001344 if ((rc == 0) || (rc == -ENOENT))
1345 goto psx_del_no_retry;
1346 }
1347
Steve French60502472008-10-07 18:42:52 +00001348retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001349 if (!server->ops->unlink) {
1350 rc = -ENOSYS;
1351 goto psx_del_no_retry;
1352 }
1353
1354 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001355
Steve French2d785a52007-07-15 01:48:57 +00001356psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001358 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001359 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001361 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001362 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001363 if (server->ops->rename_pending_delete) {
1364 rc = server->ops->rename_pending_delete(full_path,
1365 dentry, xid);
1366 if (rc == 0)
1367 cifs_drop_nlink(inode);
1368 }
Steve Frenchff694522009-04-20 19:45:13 +00001369 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001370 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1371 if (attrs == NULL) {
1372 rc = -ENOMEM;
1373 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 }
Steve French388e57b2008-09-16 23:50:58 +00001375
1376 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001377 cifs_inode = CIFS_I(inode);
1378 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001379 if (origattr == 0)
1380 origattr |= ATTR_NORMAL;
1381 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001382 if (dosattr == 0)
1383 dosattr |= ATTR_NORMAL;
1384 dosattr |= ATTR_HIDDEN;
1385
1386 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001387 if (rc != 0)
1388 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001389
1390 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 }
Steve French60502472008-10-07 18:42:52 +00001392
1393 /* undo the setattr if we errored out and it's needed */
1394 if (rc != 0 && dosattr != 0)
1395 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1396
Steve French388e57b2008-09-16 23:50:58 +00001397out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001398 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001399 cifs_inode = CIFS_I(inode);
1400 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001401 when needed */
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001402 inode->i_ctime = current_time(inode);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001403 }
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001404 dir->i_ctime = dir->i_mtime = current_time(dir);
Steve Frenchff694522009-04-20 19:45:13 +00001405 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001406 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001407unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001409 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001410 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001411 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 return rc;
1413}
1414
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001415static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001416cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001417 const char *full_path, struct cifs_sb_info *cifs_sb,
1418 struct cifs_tcon *tcon, const unsigned int xid)
1419{
1420 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001421 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001422
1423 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001424 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001425 xid);
1426 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001427 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1428 xid, NULL);
1429
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001430 if (rc)
1431 return rc;
1432
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001433 /*
1434 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001435 * from the server or was set bogus. Also, since this is a brand new
1436 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001437 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001438 if (inode->i_nlink < 2)
1439 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001440 mode &= ~current_umask();
1441 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001442 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001443 mode |= S_ISGID;
1444
1445 if (tcon->unix_ext) {
1446 struct cifs_unix_set_info_args args = {
1447 .mode = mode,
1448 .ctime = NO_CHANGE_64,
1449 .atime = NO_CHANGE_64,
1450 .mtime = NO_CHANGE_64,
1451 .device = 0,
1452 };
1453 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001454 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001455 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001456 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001457 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001458 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001459 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001460 args.uid = INVALID_UID; /* no change */
1461 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001462 }
1463 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1464 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001465 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001466 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001467 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001468 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001469 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001470 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001471 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001472 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1473 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001474
Jeff Layton101b92d2012-09-19 06:22:45 -07001475 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1476 inode->i_uid = current_fsuid();
1477 if (inode->i_mode & S_ISGID)
1478 inode->i_gid = parent->i_gid;
1479 else
1480 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001481 }
1482 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001483 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001484 return rc;
1485}
1486
1487static int
1488cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1489 const char *full_path, struct cifs_sb_info *cifs_sb,
1490 struct cifs_tcon *tcon, const unsigned int xid)
1491{
1492 int rc = 0;
1493 u32 oplock = 0;
1494 FILE_UNIX_BASIC_INFO *info = NULL;
1495 struct inode *newinode = NULL;
1496 struct cifs_fattr fattr;
1497
1498 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1499 if (info == NULL) {
1500 rc = -ENOMEM;
1501 goto posix_mkdir_out;
1502 }
1503
1504 mode &= ~current_umask();
1505 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1506 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001507 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001508 if (rc == -EOPNOTSUPP)
1509 goto posix_mkdir_out;
1510 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001511 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001512 d_drop(dentry);
1513 goto posix_mkdir_out;
1514 }
1515
1516 if (info->Type == cpu_to_le32(-1))
1517 /* no return info, go query for it */
1518 goto posix_mkdir_get_info;
1519 /*
1520 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1521 * need to set uid/gid.
1522 */
1523
1524 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1525 cifs_fill_uniqueid(inode->i_sb, &fattr);
1526 newinode = cifs_iget(inode->i_sb, &fattr);
1527 if (!newinode)
1528 goto posix_mkdir_get_info;
1529
1530 d_instantiate(dentry, newinode);
1531
1532#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001533 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1534 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001535
1536 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001537 cifs_dbg(FYI, "unexpected number of links %d\n",
1538 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001539#endif
1540
1541posix_mkdir_out:
1542 kfree(info);
1543 return rc;
1544posix_mkdir_get_info:
1545 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1546 xid);
1547 goto posix_mkdir_out;
1548}
1549
Al Viro18bb1db2011-07-26 01:41:39 -04001550int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001552 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001553 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001555 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001556 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001557 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001558 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559
Joe Perchesf96637b2013-05-04 22:12:25 -05001560 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1561 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001564 tlink = cifs_sb_tlink(cifs_sb);
1565 if (IS_ERR(tlink))
1566 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001567 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001568
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001569 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
Steve French7f573562005-08-30 11:32:14 -07001571 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301573 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001574 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 }
Steve French50c2f752007-07-13 00:33:32 +00001576
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001577 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1578 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001579 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1580 tcon, xid);
1581 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001582 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001583 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001584
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001585 server = tcon->ses->server;
1586
1587 if (!server->ops->mkdir) {
1588 rc = -ENOSYS;
1589 goto mkdir_out;
1590 }
1591
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001593 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001595 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001597 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001599
1600 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1601 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001602mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001603 /*
1604 * Force revalidate to get parent dir info when needed since cached
1605 * attributes are invalid now.
1606 */
1607 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001609 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001610 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 return rc;
1612}
1613
1614int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1615{
1616 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001617 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001619 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001620 struct cifs_tcon *tcon;
1621 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 char *full_path = NULL;
1623 struct cifsInodeInfo *cifsInode;
1624
Joe Perchesf96637b2013-05-04 22:12:25 -05001625 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001627 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628
Steve French7f573562005-08-30 11:32:14 -07001629 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301631 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001632 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 }
1634
Jeff Layton7ffec372010-09-29 19:51:11 -04001635 cifs_sb = CIFS_SB(inode->i_sb);
1636 tlink = cifs_sb_tlink(cifs_sb);
1637 if (IS_ERR(tlink)) {
1638 rc = PTR_ERR(tlink);
1639 goto rmdir_exit;
1640 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001641 tcon = tlink_tcon(tlink);
1642 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001643
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001644 if (!server->ops->rmdir) {
1645 rc = -ENOSYS;
1646 cifs_put_tlink(tlink);
1647 goto rmdir_exit;
1648 }
1649
1650 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001651 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
1653 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001654 spin_lock(&d_inode(direntry)->i_lock);
1655 i_size_write(d_inode(direntry), 0);
1656 clear_nlink(d_inode(direntry));
1657 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 }
1659
David Howells2b0143b2015-03-17 22:25:59 +00001660 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001661 /* force revalidate to go get info when needed */
1662 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001663
1664 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001665 /*
1666 * Force revalidate to get parent dir info when needed since cached
1667 * attributes are invalid now.
1668 */
1669 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001670
David Howells2b0143b2015-03-17 22:25:59 +00001671 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001672 current_time(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
Jeff Layton7ffec372010-09-29 19:51:11 -04001674rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001676 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 return rc;
1678}
1679
Steve Frenchee2fd962008-09-23 18:23:33 +00001680static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001681cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1682 const char *from_path, struct dentry *to_dentry,
1683 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001684{
1685 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001686 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001687 struct cifs_tcon *tcon;
1688 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001689 struct cifs_fid fid;
1690 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001691 int oplock, rc;
1692
Jeff Layton7ffec372010-09-29 19:51:11 -04001693 tlink = cifs_sb_tlink(cifs_sb);
1694 if (IS_ERR(tlink))
1695 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001696 tcon = tlink_tcon(tlink);
1697 server = tcon->ses->server;
1698
1699 if (!server->ops->rename)
1700 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001701
Steve Frenchee2fd962008-09-23 18:23:33 +00001702 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001703 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001704
1705 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001706 * Don't bother with rename by filehandle unless file is busy and
1707 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001708 * rename by filehandle to various Windows servers.
1709 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001710 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001711 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001712
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001713 /* open-file renames don't work across directories */
1714 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001715 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001716
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001717 oparms.tcon = tcon;
1718 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00001719 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001720 oparms.desired_access = DELETE;
1721 oparms.create_options = CREATE_NOT_DIR;
1722 oparms.disposition = FILE_OPEN;
1723 oparms.path = from_path;
1724 oparms.fid = &fid;
1725 oparms.reconnect = false;
1726
1727 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00001728 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001729 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001730 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001731 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001732 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001733 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001734do_rename_exit:
1735 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001736 return rc;
1737}
1738
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001739int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001740cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
1741 struct inode *target_dir, struct dentry *target_dentry,
1742 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001744 char *from_name = NULL;
1745 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001746 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001747 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001748 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001749 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1750 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001751 unsigned int xid;
1752 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001754 if (flags & ~RENAME_NOREPLACE)
1755 return -EINVAL;
1756
Jeff Layton639e7a92010-09-03 11:50:09 -04001757 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001758 tlink = cifs_sb_tlink(cifs_sb);
1759 if (IS_ERR(tlink))
1760 return PTR_ERR(tlink);
1761 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001763 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001764
1765 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001766 * we already have the rename sem so we do not need to
1767 * grab it again here to protect the path integrity
1768 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001769 from_name = build_path_from_dentry(source_dentry);
1770 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 rc = -ENOMEM;
1772 goto cifs_rename_exit;
1773 }
1774
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001775 to_name = build_path_from_dentry(target_dentry);
1776 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001777 rc = -ENOMEM;
1778 goto cifs_rename_exit;
1779 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001781 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1782 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001783
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001784 /*
1785 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
1786 */
1787 if (flags & RENAME_NOREPLACE)
1788 goto cifs_rename_exit;
1789
Jeff Layton14121bd2008-10-20 14:45:22 -04001790 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001791 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001792 * Are src and dst hardlinks of same inode? We can only tell
1793 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001794 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001795 info_buf_source =
1796 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1797 GFP_KERNEL);
1798 if (info_buf_source == NULL) {
1799 rc = -ENOMEM;
1800 goto cifs_rename_exit;
1801 }
1802
1803 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001804 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1805 info_buf_source,
1806 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001807 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04001808 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001809 goto unlink_target;
1810
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001811 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1812 info_buf_target,
1813 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001814 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04001815
Jeff Layton8d281ef2008-10-22 13:57:01 -04001816 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001817 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001818 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001819 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001820 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001821 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001822 }
1823 /*
1824 * else ... BB we could add the same check for Windows by
1825 * checking the UniqueId via FILE_INTERNAL_INFO
1826 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001827
Jeff Layton14121bd2008-10-20 14:45:22 -04001828unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001829 /* Try unlinking the target dentry if it's not negative */
David Howells2b0143b2015-03-17 22:25:59 +00001830 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04001831 if (d_is_dir(target_dentry))
1832 tmprc = cifs_rmdir(target_dir, target_dentry);
1833 else
1834 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001835 if (tmprc)
1836 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001837 rc = cifs_do_rename(xid, source_dentry, from_name,
1838 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 }
1840
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001841 /* force revalidate to go get info when needed */
1842 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1843
1844 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
Deepa Dinamanie37fea52017-05-08 15:59:16 -07001845 target_dir->i_mtime = current_time(source_dir);
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001846
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001848 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001849 kfree(from_name);
1850 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001851 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001852 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 return rc;
1854}
1855
Jeff Laytondf2cf172010-02-12 07:44:16 -05001856static bool
1857cifs_inode_needs_reval(struct inode *inode)
1858{
1859 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301860 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001861
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001862 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001863 return false;
1864
1865 if (!lookupCacheEnabled)
1866 return true;
1867
1868 if (cifs_i->time == 0)
1869 return true;
1870
Jeff Laytona87c9ad2014-03-26 07:24:23 -07001871 if (!cifs_sb->actimeo)
1872 return true;
1873
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301874 if (!time_in_range(jiffies, cifs_i->time,
1875 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001876 return true;
1877
Jeff Laytondb192722010-05-17 14:51:49 -04001878 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301879 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001880 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1881 return true;
1882
Jeff Laytondf2cf172010-02-12 07:44:16 -05001883 return false;
1884}
1885
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301886/*
1887 * Zap the cache. Called when invalid_mapping flag is set.
1888 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001889int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001890cifs_invalidate_mapping(struct inode *inode)
1891{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001892 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001893
Jeff Laytondf2cf172010-02-12 07:44:16 -05001894 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001895 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001896 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001897 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1898 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001899 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001900
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301901 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001902 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001903}
1904
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001905/**
1906 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
1907 * @word: long word containing the bit lock
1908 */
1909static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01001910cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001911{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001912 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01001913 if (signal_pending_state(mode, current))
1914 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001915 return 0;
1916}
1917
Jeff Laytone284e532014-04-30 09:31:46 -04001918int
1919cifs_revalidate_mapping(struct inode *inode)
1920{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001921 int rc;
1922 unsigned long *flags = &CIFS_I(inode)->flags;
1923
NeilBrown74316202014-07-07 15:16:04 +10001924 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
1925 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001926 if (rc)
1927 return rc;
1928
1929 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
1930 rc = cifs_invalidate_mapping(inode);
1931 if (rc)
1932 set_bit(CIFS_INO_INVALID_MAPPING, flags);
1933 }
1934
1935 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07001936 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001937 wake_up_bit(flags, CIFS_INO_LOCK);
1938
1939 return rc;
1940}
1941
1942int
1943cifs_zap_mapping(struct inode *inode)
1944{
1945 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
1946 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04001947}
1948
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001949int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001950{
1951 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001952 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001953 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001954
1955 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001956 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001957
Jeff Layton13cfb732010-09-29 19:51:11 -04001958 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001959 rc = cifs_get_file_info_unix(filp);
1960 else
1961 rc = cifs_get_file_info(filp);
1962
Jeff Laytonabab0952010-02-12 07:44:18 -05001963 return rc;
1964}
1965
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001966int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001968 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001969 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00001970 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001971 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001972 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973
Jeff Laytondf2cf172010-02-12 07:44:16 -05001974 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 return -ENOENT;
1976
Jeff Laytondf2cf172010-02-12 07:44:16 -05001977 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001978 return rc;
1979
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001980 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981
1982 /* can not safely grab the rename sem here if rename calls revalidate
1983 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001984 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301986 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001987 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001989
Joe Perchesf96637b2013-05-04 22:12:25 -05001990 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1991 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02001992 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993
Jeff Layton0d424ad2010-09-20 16:01:35 -07001994 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001995 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1996 else
1997 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1998 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002000out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002002 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 return rc;
2004}
2005
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002006int cifs_revalidate_file(struct file *filp)
2007{
2008 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002009 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002010
2011 rc = cifs_revalidate_file_attr(filp);
2012 if (rc)
2013 return rc;
2014
Jeff Laytone284e532014-04-30 09:31:46 -04002015 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002016}
2017
2018/* revalidate a dentry's inode attributes */
2019int cifs_revalidate_dentry(struct dentry *dentry)
2020{
2021 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002022 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002023
2024 rc = cifs_revalidate_dentry_attr(dentry);
2025 if (rc)
2026 return rc;
2027
Jeff Laytone284e532014-04-30 09:31:46 -04002028 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002029}
2030
David Howellsa528d352017-01-31 16:46:22 +00002031int cifs_getattr(const struct path *path, struct kstat *stat,
2032 u32 request_mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033{
David Howellsa528d352017-01-31 16:46:22 +00002034 struct dentry *dentry = path->dentry;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002035 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002036 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002037 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002038 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002039
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002040 /*
2041 * We need to be sure that all dirty pages are written and the server
2042 * has actual ctime, mtime and file length.
2043 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002044 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002045 inode->i_mapping->nrpages != 0) {
2046 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002047 if (rc) {
2048 mapping_set_error(inode->i_mapping, rc);
2049 return rc;
2050 }
Steve French5fe14c82006-11-07 19:26:33 +00002051 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002052
2053 rc = cifs_revalidate_dentry_attr(dentry);
2054 if (rc)
2055 return rc;
2056
2057 generic_fillattr(inode, stat);
2058 stat->blksize = CIFS_MAX_MSGSIZE;
2059 stat->ino = CIFS_I(inode)->uniqueid;
2060
Steve French6e70e262017-09-21 21:32:29 -05002061 /* old CIFS Unix Extensions doesn't return create time */
2062 if (CIFS_I(inode)->createtime) {
2063 stat->result_mask |= STATX_BTIME;
Deepa Dinamani95582b02018-05-08 19:36:02 -07002064 stat->btime = timespec_to_timespec64(
2065 cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime)));
Steve French6e70e262017-09-21 21:32:29 -05002066 }
2067
2068 stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2069 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2070 stat->attributes |= STATX_ATTR_COMPRESSED;
2071 if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2072 stat->attributes |= STATX_ATTR_ENCRYPTED;
2073
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002074 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002075 * If on a multiuser mount without unix extensions or cifsacl being
2076 * enabled, and the admin hasn't overridden them, set the ownership
2077 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002078 */
2079 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002080 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002081 !tcon->unix_ext) {
2082 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2083 stat->uid = current_fsuid();
2084 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2085 stat->gid = current_fsgid();
2086 }
2087 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088}
2089
2090static int cifs_truncate_page(struct address_space *mapping, loff_t from)
2091{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002092 pgoff_t index = from >> PAGE_SHIFT;
2093 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 int rc = 0;
2096
2097 page = grab_cache_page(mapping, index);
2098 if (!page)
2099 return -ENOMEM;
2100
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002101 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002103 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 return rc;
2105}
2106
Christoph Hellwig1b947462010-07-18 17:51:21 -04002107static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002108{
Steve Frenchba6a46a2007-02-26 20:06:29 +00002109 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002110 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002111 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002112
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002113 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002114}
2115
Jeff Layton8efdbde2008-07-23 21:28:12 +00002116static int
2117cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002118 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002119{
2120 int rc;
2121 struct cifsFileInfo *open_file;
2122 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2123 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002124 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002125 struct cifs_tcon *tcon = NULL;
2126 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002127
2128 /*
2129 * To avoid spurious oplock breaks from server, in the case of
2130 * inodes that we already have open, avoid doing path based
2131 * setting of file size if we can do it by handle.
2132 * This keeps our caching token (oplock) and avoids timeouts
2133 * when the local oplock break takes longer to flush
2134 * writebehind data than the SMB timeout for the SetPathInfo
2135 * request would allow
2136 */
Jeff Layton6508d902010-09-29 19:51:11 -04002137 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002138 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002139 tcon = tlink_tcon(open_file->tlink);
2140 server = tcon->ses->server;
2141 if (server->ops->set_file_size)
2142 rc = server->ops->set_file_size(xid, tcon, open_file,
2143 attrs->ia_size, false);
2144 else
2145 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002146 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002147 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002148 } else
2149 rc = -EINVAL;
2150
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002151 if (!rc)
2152 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07002153
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002154 if (tcon == NULL) {
2155 tlink = cifs_sb_tlink(cifs_sb);
2156 if (IS_ERR(tlink))
2157 return PTR_ERR(tlink);
2158 tcon = tlink_tcon(tlink);
2159 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002160 }
2161
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002162 /*
2163 * Set file size by pathname rather than by handle either because no
2164 * valid, writeable file handle for it was found or because there was
2165 * an error setting it by handle.
2166 */
2167 if (server->ops->set_path_size)
2168 rc = server->ops->set_path_size(xid, tcon, full_path,
2169 attrs->ia_size, cifs_sb, false);
2170 else
2171 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002172 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002173
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002174 if (tlink)
2175 cifs_put_tlink(tlink);
2176
2177set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002178 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002179 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002180 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002181 cifs_truncate_page(inode->i_mapping, inode->i_size);
2182 }
2183
2184 return rc;
2185}
2186
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002187static int
2188cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2189{
2190 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002191 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002192 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002193 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002194 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2195 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002196 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002197 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002198 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002199 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002200
Al Viro35c265e2014-08-19 20:25:34 -04002201 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2202 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002203
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002204 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002205
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002206 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2207 attrs->ia_valid |= ATTR_FORCE;
2208
Jan Kara31051c82016-05-26 16:55:18 +02002209 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002210 if (rc < 0)
2211 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002212
2213 full_path = build_path_from_dentry(direntry);
2214 if (full_path == NULL) {
2215 rc = -ENOMEM;
2216 goto out;
2217 }
2218
Jeff Layton0f4d6342009-03-26 13:35:37 -04002219 /*
2220 * Attempt to flush data before changing attributes. We need to do
2221 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2222 * ownership or mode then we may also need to do this. Here, we take
2223 * the safe way out and just do the flush on all setattr requests. If
2224 * the flush returns error, store it to report later and continue.
2225 *
2226 * BB: This should be smarter. Why bother flushing pages that
2227 * will be truncated anyway? Also, should we error out here if
2228 * the flush returns error?
2229 */
2230 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002231 mapping_set_error(inode->i_mapping, rc);
2232 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002233
2234 if (attrs->ia_valid & ATTR_SIZE) {
2235 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2236 if (rc != 0)
2237 goto out;
2238 }
2239
2240 /* skip mode change if it's just for clearing setuid/setgid */
2241 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2242 attrs->ia_valid &= ~ATTR_MODE;
2243
2244 args = kmalloc(sizeof(*args), GFP_KERNEL);
2245 if (args == NULL) {
2246 rc = -ENOMEM;
2247 goto out;
2248 }
2249
2250 /* set up the struct */
2251 if (attrs->ia_valid & ATTR_MODE)
2252 args->mode = attrs->ia_mode;
2253 else
2254 args->mode = NO_CHANGE_64;
2255
2256 if (attrs->ia_valid & ATTR_UID)
2257 args->uid = attrs->ia_uid;
2258 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002259 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002260
2261 if (attrs->ia_valid & ATTR_GID)
2262 args->gid = attrs->ia_gid;
2263 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002264 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002265
2266 if (attrs->ia_valid & ATTR_ATIME)
Deepa Dinamani95582b02018-05-08 19:36:02 -07002267 args->atime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_atime));
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002268 else
2269 args->atime = NO_CHANGE_64;
2270
2271 if (attrs->ia_valid & ATTR_MTIME)
Deepa Dinamani95582b02018-05-08 19:36:02 -07002272 args->mtime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_mtime));
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002273 else
2274 args->mtime = NO_CHANGE_64;
2275
2276 if (attrs->ia_valid & ATTR_CTIME)
Deepa Dinamani95582b02018-05-08 19:36:02 -07002277 args->ctime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_ctime));
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002278 else
2279 args->ctime = NO_CHANGE_64;
2280
2281 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002282 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002283 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002284 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002285 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002286 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002287 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002288 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002289 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002290 tlink = cifs_sb_tlink(cifs_sb);
2291 if (IS_ERR(tlink)) {
2292 rc = PTR_ERR(tlink);
2293 goto out;
2294 }
2295 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002296 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002297 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002298 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002299 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002300 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002301
Christoph Hellwig10257742010-06-04 11:30:02 +02002302 if (rc)
2303 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002304
Christoph Hellwig10257742010-06-04 11:30:02 +02002305 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002306 attrs->ia_size != i_size_read(inode))
2307 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002308
2309 setattr_copy(inode, attrs);
2310 mark_inode_dirty(inode);
2311
2312 /* force revalidate when any of these times are set since some
2313 of the fs types (eg ext3, fat) do not have fine enough
2314 time granularity to match protocol, and we do not have a
2315 a way (yet) to query the server fs's time granularity (and
2316 whether it rounds times down).
2317 */
2318 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2319 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002320out:
2321 kfree(args);
2322 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002323 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002324 return rc;
2325}
2326
Jeff Layton0510eeb2008-08-02 07:26:12 -04002327static int
2328cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002330 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002331 kuid_t uid = INVALID_UID;
2332 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002333 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002334 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002335 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 char *full_path = NULL;
2337 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002338 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002339 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002340
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002341 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342
Al Viro35c265e2014-08-19 20:25:34 -04002343 cifs_dbg(FYI, "setattr on file %pd attrs->iavalid 0x%x\n",
2344 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002345
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002346 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2347 attrs->ia_valid |= ATTR_FORCE;
2348
Jan Kara31051c82016-05-26 16:55:18 +02002349 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002350 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002351 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002352 return rc;
Steve French6473a552005-11-29 20:20:10 -08002353 }
Steve French50c2f752007-07-13 00:33:32 +00002354
Steve French7f573562005-08-30 11:32:14 -07002355 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302357 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002358 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302359 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361
Jeff Layton0f4d6342009-03-26 13:35:37 -04002362 /*
2363 * Attempt to flush data before changing attributes. We need to do
2364 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2365 * ownership or mode then we may also need to do this. Here, we take
2366 * the safe way out and just do the flush on all setattr requests. If
2367 * the flush returns error, store it to report later and continue.
2368 *
2369 * BB: This should be smarter. Why bother flushing pages that
2370 * will be truncated anyway? Also, should we error out here if
2371 * the flush returns error?
2372 */
2373 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002374 mapping_set_error(inode->i_mapping, rc);
2375 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002376
Steve French50531442008-03-14 19:21:31 +00002377 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002378 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2379 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002380 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002382
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002383 if (attrs->ia_valid & ATTR_UID)
2384 uid = attrs->ia_uid;
2385
2386 if (attrs->ia_valid & ATTR_GID)
2387 gid = attrs->ia_gid;
2388
2389#ifdef CONFIG_CIFS_ACL
2390 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002391 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002392 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2393 uid, gid);
2394 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002395 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2396 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002397 goto cifs_setattr_exit;
2398 }
2399 }
2400 } else
2401#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002402 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002403 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404
Jeff Laytond32c4f22007-10-18 03:05:22 -07002405 /* skip mode change if it's just for clearing setuid/setgid */
2406 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2407 attrs->ia_valid &= ~ATTR_MODE;
2408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002411 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002412#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002413 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002414 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002415 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002416 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002417 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2418 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002419 goto cifs_setattr_exit;
2420 }
2421 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002422#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002423 if (((mode & S_IWUGO) == 0) &&
2424 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002425
2426 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2427
Jeff Layton51328612008-05-22 09:33:34 -04002428 /* fix up mode if we're not using dynperm */
2429 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2430 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2431 } else if ((mode & S_IWUGO) &&
2432 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002433
2434 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2435 /* Attributes of 0 are ignored */
2436 if (dosattr == 0)
2437 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002438
2439 /* reset local inode permissions to normal */
2440 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2441 attrs->ia_mode &= ~(S_IALLUGO);
2442 if (S_ISDIR(inode->i_mode))
2443 attrs->ia_mode |=
2444 cifs_sb->mnt_dir_mode;
2445 else
2446 attrs->ia_mode |=
2447 cifs_sb->mnt_file_mode;
2448 }
2449 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2450 /* ignore mode change - ATTR_READONLY hasn't changed */
2451 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 }
2454
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002455 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2456 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2457 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2458 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459
Steve Frenche30dcf32005-09-20 20:49:16 -07002460 /* Even if error on time set, no sense failing the call if
2461 the server would set the time to a reasonable value anyway,
2462 and this check ensures that we are not being called from
2463 sys_utimes in which case we ought to fail the call back to
2464 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002465 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002466 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002467 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 }
2469
2470 /* do not need local check to inode_check_ok since the server does
2471 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002472 if (rc)
2473 goto cifs_setattr_exit;
2474
2475 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002476 attrs->ia_size != i_size_read(inode))
2477 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002478
2479 setattr_copy(inode, attrs);
2480 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002481
Steve Frenche30dcf32005-09-20 20:49:16 -07002482cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002484 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 return rc;
2486}
2487
Jeff Layton0510eeb2008-08-02 07:26:12 -04002488int
2489cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2490{
Al Virofc640052016-04-10 01:33:30 -04002491 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002492 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002493
2494 if (pTcon->unix_ext)
2495 return cifs_setattr_unix(direntry, attrs);
2496
2497 return cifs_setattr_nounix(direntry, attrs);
2498
2499 /* BB: add cifs_setattr_legacy for really old servers */
2500}
2501
Steve French99ee4db2007-02-27 05:35:17 +00002502#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503void cifs_delete_inode(struct inode *inode)
2504{
Joe Perchesf96637b2013-05-04 22:12:25 -05002505 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 /* may have to add back in if and when safe distributed caching of
2507 directories added e.g. via FindNotify */
2508}
Steve French99ee4db2007-02-27 05:35:17 +00002509#endif