blob: 57c938ffeb6e2eb1e1d952bab9c2b71044cd31ba [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/div64.h>
27#include "cifsfs.h"
28#include "cifspdu.h"
29#include "cifsglob.h"
30#include "cifsproto.h"
31#include "cifs_debug.h"
32#include "cifs_fs_sb.h"
Steve French2baa2682014-09-27 02:19:01 -050033#include "cifs_unicode.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053034#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Christoph Hellwig70eff552008-02-15 20:55:05 +000036
David Howells01c64fe2011-01-14 18:45:47 +000037static void cifs_set_ops(struct inode *inode)
Christoph Hellwig70eff552008-02-15 20:55:05 +000038{
39 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
40
41 switch (inode->i_mode & S_IFMT) {
42 case S_IFREG:
43 inode->i_op = &cifs_file_inode_ops;
44 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
45 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
46 inode->i_fop = &cifs_file_direct_nobrl_ops;
47 else
48 inode->i_fop = &cifs_file_direct_ops;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +030049 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
50 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
51 inode->i_fop = &cifs_file_strict_nobrl_ops;
52 else
53 inode->i_fop = &cifs_file_strict_ops;
Christoph Hellwig70eff552008-02-15 20:55:05 +000054 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
55 inode->i_fop = &cifs_file_nobrl_ops;
56 else { /* not direct, send byte range locks */
57 inode->i_fop = &cifs_file_ops;
58 }
59
Christoph Hellwig70eff552008-02-15 20:55:05 +000060 /* check if server can support readpages */
Jeff Layton0d424ad2010-09-20 16:01:35 -070061 if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +030062 PAGE_SIZE + MAX_CIFS_HDR_SIZE)
Christoph Hellwig70eff552008-02-15 20:55:05 +000063 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
64 else
65 inode->i_data.a_ops = &cifs_addr_ops;
66 break;
67 case S_IFDIR:
Steve Frenchbc5b6e22008-03-11 21:07:48 +000068#ifdef CONFIG_CIFS_DFS_UPCALL
David Howells01c64fe2011-01-14 18:45:47 +000069 if (IS_AUTOMOUNT(inode)) {
Igor Mammedov79626702008-03-09 03:44:18 +000070 inode->i_op = &cifs_dfs_referral_inode_operations;
71 } else {
Steve Frenchbc5b6e22008-03-11 21:07:48 +000072#else /* NO DFS support, treat as a directory */
73 {
74#endif
Igor Mammedov79626702008-03-09 03:44:18 +000075 inode->i_op = &cifs_dir_inode_ops;
76 inode->i_fop = &cifs_dir_ops;
77 }
Christoph Hellwig70eff552008-02-15 20:55:05 +000078 break;
79 case S_IFLNK:
80 inode->i_op = &cifs_symlink_inode_ops;
81 break;
82 default:
83 init_special_inode(inode, inode->i_mode, inode->i_rdev);
84 break;
85 }
86}
87
Jeff Laytondf2cf172010-02-12 07:44:16 -050088/* check inode attributes against fattr. If they don't match, tag the
89 * inode for cache invalidation
90 */
91static void
92cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
93{
94 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
95
Joe Perchesf96637b2013-05-04 22:12:25 -050096 cifs_dbg(FYI, "%s: revalidating inode %llu\n",
97 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -050098
99 if (inode->i_state & I_NEW) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500100 cifs_dbg(FYI, "%s: inode %llu is new\n",
101 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500102 return;
103 }
104
105 /* don't bother with revalidation if we have an oplock */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400106 if (CIFS_CACHE_READ(cifs_i)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500107 cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
108 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500109 return;
110 }
111
112 /* revalidate if mtime or size have changed */
113 if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
114 cifs_i->server_eof == fattr->cf_eof) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500115 cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
116 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500117 return;
118 }
119
Joe Perchesf96637b2013-05-04 22:12:25 -0500120 cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
121 __func__, cifs_i->uniqueid);
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400122 set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500123}
124
Jim McDonough74d290d2013-09-21 10:36:10 -0500125/*
126 * copy nlink to the inode, unless it wasn't provided. Provide
127 * sane values if we don't have an existing one and none was provided
128 */
129static void
130cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
131{
132 /*
133 * if we're in a situation where we can't trust what we
134 * got from the server (readdir, some non-unix cases)
135 * fake reasonable values
136 */
137 if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
138 /* only provide fake values on a new inode */
139 if (inode->i_state & I_NEW) {
140 if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
141 set_nlink(inode, 2);
142 else
143 set_nlink(inode, 1);
144 }
145 return;
146 }
147
148 /* we trust the server, so update it */
149 set_nlink(inode, fattr->cf_nlink);
150}
151
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400152/* populate an inode with info from a cifs_fattr struct */
153void
154cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
Christoph Hellwig75f12982008-02-25 20:25:21 +0000155{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400156 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400157 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000158
Jeff Laytondf2cf172010-02-12 07:44:16 -0500159 cifs_revalidate_cache(inode, fattr);
160
Steve Frenchb7ca6922012-08-03 08:43:01 -0500161 spin_lock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400162 inode->i_atime = fattr->cf_atime;
163 inode->i_mtime = fattr->cf_mtime;
164 inode->i_ctime = fattr->cf_ctime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400165 inode->i_rdev = fattr->cf_rdev;
Jim McDonough74d290d2013-09-21 10:36:10 -0500166 cifs_nlink_fattr_to_inode(inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400167 inode->i_uid = fattr->cf_uid;
168 inode->i_gid = fattr->cf_gid;
169
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400170 /* if dynperm is set, don't clobber existing mode */
171 if (inode->i_state & I_NEW ||
172 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
173 inode->i_mode = fattr->cf_mode;
174
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400175 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400176
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400177 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
178 cifs_i->time = 0;
179 else
180 cifs_i->time = jiffies;
181
Jeff Laytonaff8d5c2014-04-30 09:31:45 -0400182 if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
183 set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
184 else
185 clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000186
Jeff Layton835a36c2010-02-10 16:21:33 -0500187 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000188 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400189 * Can't safely change the file size here if the client is writing to
190 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000191 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400192 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
193 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000194
195 /*
196 * i_blocks is not related to (i_size / i_blksize),
197 * but instead 512 byte (2**9) size is required for
198 * calculating num blocks.
199 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400200 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000201 }
202 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400203
David Howells01c64fe2011-01-14 18:45:47 +0000204 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
205 inode->i_flags |= S_AUTOMOUNT;
Jeff Laytonc2b93e02013-05-07 11:28:31 -0400206 if (inode->i_state & I_NEW)
207 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000208}
209
Jeff Layton4065c802010-05-17 07:18:58 -0400210void
211cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
212{
213 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
214
215 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
216 return;
217
218 fattr->cf_uniqueid = iunique(sb, ROOT_I);
219}
220
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400221/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
222void
223cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
224 struct cifs_sb_info *cifs_sb)
225{
226 memset(fattr, 0, sizeof(*fattr));
227 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
228 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
229 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
230
231 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
232 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
233 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
234 fattr->cf_mode = le64_to_cpu(info->Permissions);
235
236 /*
237 * Since we set the inode type below we need to mask off
238 * to avoid strange results if bits set above.
239 */
240 fattr->cf_mode &= ~S_IFMT;
241 switch (le32_to_cpu(info->Type)) {
242 case UNIX_FILE:
243 fattr->cf_mode |= S_IFREG;
244 fattr->cf_dtype = DT_REG;
245 break;
246 case UNIX_SYMLINK:
247 fattr->cf_mode |= S_IFLNK;
248 fattr->cf_dtype = DT_LNK;
249 break;
250 case UNIX_DIR:
251 fattr->cf_mode |= S_IFDIR;
252 fattr->cf_dtype = DT_DIR;
253 break;
254 case UNIX_CHARDEV:
255 fattr->cf_mode |= S_IFCHR;
256 fattr->cf_dtype = DT_CHR;
257 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
258 le64_to_cpu(info->DevMinor) & MINORMASK);
259 break;
260 case UNIX_BLOCKDEV:
261 fattr->cf_mode |= S_IFBLK;
262 fattr->cf_dtype = DT_BLK;
263 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
264 le64_to_cpu(info->DevMinor) & MINORMASK);
265 break;
266 case UNIX_FIFO:
267 fattr->cf_mode |= S_IFIFO;
268 fattr->cf_dtype = DT_FIFO;
269 break;
270 case UNIX_SOCKET:
271 fattr->cf_mode |= S_IFSOCK;
272 fattr->cf_dtype = DT_SOCK;
273 break;
274 default:
275 /* safest to call it a file if we do not know */
276 fattr->cf_mode |= S_IFREG;
277 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500278 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400279 break;
280 }
281
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800282 fattr->cf_uid = cifs_sb->mnt_uid;
283 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
284 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800285 if (id < ((uid_t)-1)) {
286 kuid_t uid = make_kuid(&init_user_ns, id);
287 if (uid_valid(uid))
288 fattr->cf_uid = uid;
289 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800290 }
291
292 fattr->cf_gid = cifs_sb->mnt_gid;
293 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
294 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800295 if (id < ((gid_t)-1)) {
296 kgid_t gid = make_kgid(&init_user_ns, id);
297 if (gid_valid(gid))
298 fattr->cf_gid = gid;
299 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800300 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400301
302 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
303}
Steve Frenchb9a32602008-05-20 21:52:32 +0000304
305/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400306 * Fill a cifs_fattr struct with fake inode info.
307 *
308 * Needed to setup cifs_fattr data for the directory which is the
309 * junction to the new submount (ie to setup the fake directory
310 * which represents a DFS referral).
Steve Frenchb9a32602008-05-20 21:52:32 +0000311 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000312static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400313cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000314{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400315 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000316
Joe Perchesf96637b2013-05-04 22:12:25 -0500317 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000318
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400319 memset(fattr, 0, sizeof(*fattr));
320 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
321 fattr->cf_uid = cifs_sb->mnt_uid;
322 fattr->cf_gid = cifs_sb->mnt_gid;
323 fattr->cf_atime = CURRENT_TIME;
324 fattr->cf_ctime = CURRENT_TIME;
325 fattr->cf_mtime = CURRENT_TIME;
326 fattr->cf_nlink = 2;
327 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000328}
329
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700330static int
331cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500332{
333 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400334 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500335 FILE_UNIX_BASIC_INFO find_data;
336 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500337 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500338 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700339 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000340 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500341
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400342 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700343 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500344 if (!rc) {
345 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
346 } else if (rc == -EREMOTE) {
347 cifs_create_dfs_fattr(&fattr, inode->i_sb);
348 rc = 0;
349 }
350
351 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400352 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500353 return rc;
354}
355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400357 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400358 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400360 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000361 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400362 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000363 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400364 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Joe Perchesf96637b2013-05-04 22:12:25 -0500367 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000368
Jeff Layton7ffec372010-09-29 19:51:11 -0400369 tlink = cifs_sb_tlink(cifs_sb);
370 if (IS_ERR(tlink))
371 return PTR_ERR(tlink);
372 tcon = tlink_tcon(tlink);
373
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400375 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +0900376 cifs_sb->local_nls, cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -0400377 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400378
379 if (!rc) {
380 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
381 } else if (rc == -EREMOTE) {
382 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700383 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400384 } else {
385 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000386 }
387
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200388 /* check for Minshall+French symlinks */
389 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000390 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
391 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200392 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000393 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200394 }
395
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400396 if (*pinode == NULL) {
397 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400398 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400399 *pinode = cifs_iget(sb, &fattr);
400 if (!*pinode)
401 rc = -ENOMEM;
402 } else {
403 /* we already have inode, update it */
Nakajima Akira7196ac12015-04-22 15:24:44 +0900404
405 /* if uniqueid is different, return error */
406 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
407 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
408 rc = -ESTALE;
409 goto cgiiu_exit;
410 }
411
412 /* if filetype is different, return error */
413 if (unlikely(((*pinode)->i_mode & S_IFMT) !=
414 (fattr.cf_mode & S_IFMT))) {
415 rc = -ESTALE;
416 goto cgiiu_exit;
417 }
418
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400419 cifs_fattr_to_inode(*pinode, &fattr);
420 }
Steve French0e4bbde2008-05-20 19:50:46 +0000421
Nakajima Akira7196ac12015-04-22 15:24:44 +0900422cgiiu_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 return rc;
424}
425
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400426static int
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400427cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400428 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800429{
430 int rc;
Steve Frenchdb8b6312014-09-22 05:13:55 -0500431 __u32 oplock;
Jeff Layton7ffec372010-09-29 19:51:11 -0400432 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000433 struct cifs_tcon *tcon;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400434 struct cifs_fid fid;
435 struct cifs_open_parms oparms;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000436 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800437 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800438 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000439 char *pbuf;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400440 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800441
442 pbuf = buf;
443
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400444 fattr->cf_mode &= ~S_IFMT;
445
446 if (fattr->cf_eof == 0) {
447 fattr->cf_mode |= S_IFIFO;
448 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800449 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400450 } else if (fattr->cf_eof < 8) {
451 fattr->cf_mode |= S_IFREG;
452 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800453 return -EINVAL; /* EOPNOTSUPP? */
454 }
Steve French50c2f752007-07-13 00:33:32 +0000455
Jeff Layton7ffec372010-09-29 19:51:11 -0400456 tlink = cifs_sb_tlink(cifs_sb);
457 if (IS_ERR(tlink))
458 return PTR_ERR(tlink);
459 tcon = tlink_tcon(tlink);
460
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400461 oparms.tcon = tcon;
462 oparms.cifs_sb = cifs_sb;
463 oparms.desired_access = GENERIC_READ;
464 oparms.create_options = CREATE_NOT_DIR;
465 oparms.disposition = FILE_OPEN;
466 oparms.path = path;
467 oparms.fid = &fid;
468 oparms.reconnect = false;
469
Steve Frenchdb8b6312014-09-22 05:13:55 -0500470 if (tcon->ses->server->oplocks)
471 oplock = REQ_OPLOCK;
472 else
473 oplock = 0;
474 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400475 if (rc) {
Steve Frenchdb8b6312014-09-22 05:13:55 -0500476 cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400477 cifs_put_tlink(tlink);
478 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800479 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400480
481 /* Read header */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400482 io_parms.netfid = fid.netfid;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400483 io_parms.pid = current->tgid;
484 io_parms.tcon = tcon;
485 io_parms.offset = 0;
486 io_parms.length = 24;
487
Steve Frenchdb8b6312014-09-22 05:13:55 -0500488 rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
489 &bytes_read, &pbuf, &buf_type);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400490 if ((rc == 0) && (bytes_read >= 8)) {
491 if (memcmp("IntxBLK", pbuf, 8) == 0) {
492 cifs_dbg(FYI, "Block device\n");
493 fattr->cf_mode |= S_IFBLK;
494 fattr->cf_dtype = DT_BLK;
495 if (bytes_read == 24) {
496 /* we have enough to decode dev num */
497 __u64 mjr; /* major */
498 __u64 mnr; /* minor */
499 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
500 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
501 fattr->cf_rdev = MKDEV(mjr, mnr);
502 }
503 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
504 cifs_dbg(FYI, "Char device\n");
505 fattr->cf_mode |= S_IFCHR;
506 fattr->cf_dtype = DT_CHR;
507 if (bytes_read == 24) {
508 /* we have enough to decode dev num */
509 __u64 mjr; /* major */
510 __u64 mnr; /* minor */
511 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
512 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
513 fattr->cf_rdev = MKDEV(mjr, mnr);
514 }
515 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
516 cifs_dbg(FYI, "Symlink\n");
517 fattr->cf_mode |= S_IFLNK;
518 fattr->cf_dtype = DT_LNK;
519 } else {
520 fattr->cf_mode |= S_IFREG; /* file? */
521 fattr->cf_dtype = DT_REG;
522 rc = -EOPNOTSUPP;
523 }
524 } else {
525 fattr->cf_mode |= S_IFREG; /* then it is a file */
526 fattr->cf_dtype = DT_REG;
527 rc = -EOPNOTSUPP; /* or some unknown SFU type */
528 }
Steve Frenchdb8b6312014-09-22 05:13:55 -0500529
530 tcon->ses->server->ops->close(xid, tcon, &fid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400531 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800532 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800533}
534
Steve French9e294f12005-11-17 16:59:21 -0800535#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
536
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400537/*
538 * Fetch mode bits as provided by SFU.
539 *
540 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
541 */
542static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400543 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800544{
Steve French3020a1f2005-11-18 11:31:10 -0800545#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800546 ssize_t rc;
547 char ea_value[4];
548 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400549 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000550 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800551
Jeff Layton7ffec372010-09-29 19:51:11 -0400552 tlink = cifs_sb_tlink(cifs_sb);
553 if (IS_ERR(tlink))
554 return PTR_ERR(tlink);
555 tcon = tlink_tcon(tlink);
556
Steve Frenchd979f3b2014-02-01 23:27:18 -0600557 if (tcon->ses->server->ops->query_all_EAs == NULL) {
558 cifs_put_tlink(tlink);
559 return -EOPNOTSUPP;
560 }
561
562 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
563 "SETFILEBITS", ea_value, 4 /* size of buf */,
564 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -0500565 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -0400566 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000567 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800568 return (int)rc;
569 else if (rc > 3) {
570 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400571 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500572 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
573 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400574 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500575 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800576 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400577
578 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800579#else
580 return -EOPNOTSUPP;
581#endif
Steve French9e294f12005-11-17 16:59:21 -0800582}
583
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400584/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000585static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400586cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400587 struct cifs_sb_info *cifs_sb, bool adjust_tz,
588 bool symlink)
Steve Frenchb9a32602008-05-20 21:52:32 +0000589{
Steve French96daf2b2011-05-27 04:34:02 +0000590 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700591
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400592 memset(fattr, 0, sizeof(*fattr));
593 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
594 if (info->DeletePending)
595 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000596
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400597 if (info->LastAccessTime)
598 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
599 else
600 fattr->cf_atime = CURRENT_TIME;
601
602 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
603 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
604
605 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700606 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
607 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400608 }
609
610 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
611 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500612 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400613
Jim McDonough74d290d2013-09-21 10:36:10 -0500614 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400615
616 if (symlink) {
617 fattr->cf_mode = S_IFLNK;
618 fattr->cf_dtype = DT_LNK;
619 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400620 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
621 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300622 /*
623 * Server can return wrong NumberOfLinks value for directories
624 * when Unix extensions are disabled - fake it.
625 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500626 if (!tcon->unix_ext)
627 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400628 } else {
629 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
630 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400631
Jeff Laytond0c280d2009-07-09 01:46:44 -0400632 /* clear write bits if ATTR_READONLY is set */
633 if (fattr->cf_cifsattrs & ATTR_READONLY)
634 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400635
Jim McDonough74d290d2013-09-21 10:36:10 -0500636 /*
637 * Don't accept zero nlink from non-unix servers unless
638 * delete is pending. Instead mark it as unknown.
639 */
640 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
641 !info->DeletePending) {
642 cifs_dbg(1, "bogus file nlink value %u\n",
Steve French6658b9f2013-07-04 14:38:48 -0500643 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500644 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500645 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300646 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400647
648 fattr->cf_uid = cifs_sb->mnt_uid;
649 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000650}
651
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700652static int
653cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500654{
655 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400656 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500657 FILE_ALL_INFO find_data;
658 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500659 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500660 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700661 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000662 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700663 struct TCP_Server_Info *server = tcon->ses->server;
664
665 if (!server->ops->query_file_info)
666 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500667
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400668 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700669 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400670 switch (rc) {
671 case 0:
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400672 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false,
673 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400674 break;
675 case -EREMOTE:
676 cifs_create_dfs_fattr(&fattr, inode->i_sb);
677 rc = 0;
678 break;
679 case -EOPNOTSUPP:
680 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500681 /*
682 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000683 * for now, just skip revalidating and mark inode for
684 * immediate reval.
685 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500686 rc = 0;
687 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400688 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500689 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400690 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500691
692 /*
693 * don't bother with SFU junk here -- just mark inode as needing
694 * revalidation.
695 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500696 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
697 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
698 cifs_fattr_to_inode(inode, &fattr);
699cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400700 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500701 return rc;
702}
703
Steve Frenchc4bc6582018-03-31 18:13:38 -0500704/* Simple function to return a 64 bit hash of string. Rarely called */
705static __u64 simple_hashstr(const char *str)
706{
Geert Uytterhoevena2b9a0d2018-04-05 14:57:11 +0200707 const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
Steve Frenchc4bc6582018-03-31 18:13:38 -0500708 __u64 hash = 0;
709
710 while (*str)
711 hash = (hash + (__u64) *str++) * hash_mult;
712
713 return hash;
714}
715
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400716int
717cifs_get_inode_info(struct inode **inode, const char *full_path,
718 FILE_ALL_INFO *data, struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600719 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500721 bool validinum = false;
722 __u16 srchflgs;
723 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400724 struct cifs_tcon *tcon;
725 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400726 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400729 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400730 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500731 struct cifs_search_info *srchinf = NULL;
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400732 bool symlink = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
Jeff Layton7ffec372010-09-29 19:51:11 -0400734 tlink = cifs_sb_tlink(cifs_sb);
735 if (IS_ERR(tlink))
736 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400737 tcon = tlink_tcon(tlink);
738 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400739
Joe Perchesf96637b2013-05-04 22:12:25 -0500740 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400742 if ((data == NULL) && (*inode != NULL)) {
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400743 if (CIFS_CACHE_READ(CIFS_I(*inode))) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500744 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400745 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 }
747 }
748
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400749 /* if inode info is not passed, get it from server */
750 if (data == NULL) {
751 if (!server->ops->query_path_info) {
752 rc = -ENOSYS;
753 goto cgii_exit;
754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400756 if (buf == NULL) {
757 rc = -ENOMEM;
758 goto cgii_exit;
759 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400760 data = (FILE_ALL_INFO *)buf;
761 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400762 data, &adjust_tz, &symlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400764
765 if (!rc) {
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400766 cifs_all_info_to_fattr(&fattr, data, cifs_sb, adjust_tz,
767 symlink);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400768 } else if (rc == -EREMOTE) {
769 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000770 rc = 0;
Steve French883f9792018-10-19 00:45:21 -0500771 } else if ((rc == -EACCES) && backup_cred(cifs_sb) &&
772 (strcmp(server->vals->version_string, SMB1_VERSION_STRING)
773 == 0)) {
774 /*
775 * For SMB2 and later the backup intent flag is already
776 * sent if needed on open and there is no path based
777 * FindFirst operation to use to retry with
778 */
779
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500780 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 Frenchc4bc6582018-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 Frenchc4bc6582018-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 Frenchc4bc6582018-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);
1023 if (sb->s_flags & MS_NOATIME)
1024 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 Frenchb5b374ea2014-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 Frenchb5b374ea2014-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 Frenchb5b374ea2014-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
Jeff Layton0d424ad2010-09-20 16:01:35 -07001087 if (rc && tcon->ipc) {
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);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001104 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -08001105 * TODO: This is no longer true
1106 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001107 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001108 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109}
1110
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001111int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001112cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001113 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001114{
Steve French388e57b2008-09-16 23:50:58 +00001115 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001116 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001117 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001118 FILE_BASIC_INFO info_buf;
1119
Steve French1adcb712009-02-25 14:19:56 +00001120 if (attrs == NULL)
1121 return -EINVAL;
1122
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001123 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1124 if (!server->ops->set_file_info)
1125 return -ENOSYS;
1126
Steve French707b0d22018-08-02 20:28:18 -05001127 info_buf.Pad = 0;
1128
Steve French388e57b2008-09-16 23:50:58 +00001129 if (attrs->ia_valid & ATTR_ATIME) {
1130 set_time = true;
1131 info_buf.LastAccessTime =
1132 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1133 } else
1134 info_buf.LastAccessTime = 0;
1135
1136 if (attrs->ia_valid & ATTR_MTIME) {
1137 set_time = true;
1138 info_buf.LastWriteTime =
1139 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1140 } else
1141 info_buf.LastWriteTime = 0;
1142
1143 /*
1144 * Samba throws this field away, but windows may actually use it.
1145 * Do not set ctime unless other time stamps are changed explicitly
1146 * (i.e. by utimes()) since we would then have a mix of client and
1147 * server times.
1148 */
1149 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001150 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001151 info_buf.ChangeTime =
1152 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1153 } else
1154 info_buf.ChangeTime = 0;
1155
1156 info_buf.CreationTime = 0; /* don't change */
1157 info_buf.Attributes = cpu_to_le32(dosattr);
1158
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001159 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001160}
1161
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001162/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001163 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001164 * and rename it to a random name that hopefully won't conflict with
1165 * anything else.
1166 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001167int
1168cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1169 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001170{
1171 int oplock = 0;
1172 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001173 struct cifs_fid fid;
1174 struct cifs_open_parms oparms;
David Howells2b0143b2015-03-17 22:25:59 +00001175 struct inode *inode = d_inode(dentry);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001176 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1177 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001178 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001179 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001180 __u32 dosattr, origattr;
1181 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001182
Jeff Layton7ffec372010-09-29 19:51:11 -04001183 tlink = cifs_sb_tlink(cifs_sb);
1184 if (IS_ERR(tlink))
1185 return PTR_ERR(tlink);
1186 tcon = tlink_tcon(tlink);
1187
Sachin Prabhuc483a982013-03-05 19:25:56 +00001188 /*
1189 * We cannot rename the file if the server doesn't support
1190 * CAP_INFOLEVEL_PASSTHRU
1191 */
1192 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1193 rc = -EBUSY;
1194 goto out;
1195 }
1196
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001197 oparms.tcon = tcon;
1198 oparms.cifs_sb = cifs_sb;
1199 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1200 oparms.create_options = CREATE_NOT_DIR;
1201 oparms.disposition = FILE_OPEN;
1202 oparms.path = full_path;
1203 oparms.fid = &fid;
1204 oparms.reconnect = false;
1205
1206 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001207 if (rc != 0)
1208 goto out;
1209
Steve French32709582008-10-20 00:44:19 +00001210 origattr = cifsInode->cifsAttrs;
1211 if (origattr == 0)
1212 origattr |= ATTR_NORMAL;
1213
1214 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001215 if (dosattr == 0)
1216 dosattr |= ATTR_NORMAL;
1217 dosattr |= ATTR_HIDDEN;
1218
Steve French32709582008-10-20 00:44:19 +00001219 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1220 if (dosattr != origattr) {
1221 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1222 if (info_buf == NULL) {
1223 rc = -ENOMEM;
1224 goto out_close;
1225 }
1226 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001227 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001228 current->tgid);
1229 /* although we would like to mark the file hidden
1230 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001231 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001232 cifsInode->cifsAttrs = dosattr;
1233 else
1234 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001235 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001236
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001237 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001238 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1239 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001240 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001241 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001242 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001243 goto undo_setattr;
1244 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001245
Steve French32709582008-10-20 00:44:19 +00001246 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001247 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001248 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001249 current->tgid);
1250 /*
1251 * some samba versions return -ENOENT when we try to set the
1252 * file disposition here. Likely a samba bug, but work around
1253 * it for now. This means that some cifsXXX files may hang
1254 * around after they shouldn't.
1255 *
1256 * BB: remove this hack after more servers have the fix
1257 */
1258 if (rc == -ENOENT)
1259 rc = 0;
1260 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001261 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001262 goto undo_rename;
1263 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001264 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001265 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001266
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001267out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001268 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001269out:
Steve French32709582008-10-20 00:44:19 +00001270 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001271 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001272 return rc;
Steve French32709582008-10-20 00:44:19 +00001273
1274 /*
1275 * reset everything back to the original state. Don't bother
1276 * dealing with errors here since we can't do anything about
1277 * them anyway.
1278 */
1279undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001280 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001281 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001282undo_setattr:
1283 if (dosattr != origattr) {
1284 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001285 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001286 current->tgid))
1287 cifsInode->cifsAttrs = origattr;
1288 }
1289
1290 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001291}
1292
Steve Frenchb7ca6922012-08-03 08:43:01 -05001293/* copied from fs/nfs/dir.c with small changes */
1294static void
1295cifs_drop_nlink(struct inode *inode)
1296{
1297 spin_lock(&inode->i_lock);
1298 if (inode->i_nlink > 0)
1299 drop_nlink(inode);
1300 spin_unlock(&inode->i_lock);
1301}
Steve Frenchff694522009-04-20 19:45:13 +00001302
1303/*
David Howells2b0143b2015-03-17 22:25:59 +00001304 * If d_inode(dentry) is null (usually meaning the cached dentry
Steve Frenchff694522009-04-20 19:45:13 +00001305 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001306 * if that fails we can not attempt the fall back mechanisms on EACCESS
1307 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001308 * unlink on negative dentries currently.
1309 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001310int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311{
1312 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001313 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00001315 struct inode *inode = d_inode(dentry);
Steve Frenchff694522009-04-20 19:45:13 +00001316 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001317 struct super_block *sb = dir->i_sb;
1318 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001319 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001320 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001321 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001322 struct iattr *attrs = NULL;
1323 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
Joe Perchesf96637b2013-05-04 22:12:25 -05001325 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
Jeff Layton7ffec372010-09-29 19:51:11 -04001327 tlink = cifs_sb_tlink(cifs_sb);
1328 if (IS_ERR(tlink))
1329 return PTR_ERR(tlink);
1330 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001331 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001332
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001333 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Jeff Layton5f0319a2008-09-16 14:05:16 -04001335 /* Unlink can be called from rename so we can not take the
1336 * sb->s_vfs_rename_mutex here */
1337 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301339 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001340 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 }
Steve French2d785a52007-07-15 01:48:57 +00001342
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001343 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1344 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001345 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001346 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001347 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001348 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001349 if ((rc == 0) || (rc == -ENOENT))
1350 goto psx_del_no_retry;
1351 }
1352
Steve French60502472008-10-07 18:42:52 +00001353retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001354 if (!server->ops->unlink) {
1355 rc = -ENOSYS;
1356 goto psx_del_no_retry;
1357 }
1358
1359 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001360
Steve French2d785a52007-07-15 01:48:57 +00001361psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001363 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001364 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001366 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001367 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001368 if (server->ops->rename_pending_delete) {
1369 rc = server->ops->rename_pending_delete(full_path,
1370 dentry, xid);
1371 if (rc == 0)
1372 cifs_drop_nlink(inode);
1373 }
Steve Frenchff694522009-04-20 19:45:13 +00001374 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001375 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1376 if (attrs == NULL) {
1377 rc = -ENOMEM;
1378 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 }
Steve French388e57b2008-09-16 23:50:58 +00001380
1381 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001382 cifs_inode = CIFS_I(inode);
1383 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001384 if (origattr == 0)
1385 origattr |= ATTR_NORMAL;
1386 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001387 if (dosattr == 0)
1388 dosattr |= ATTR_NORMAL;
1389 dosattr |= ATTR_HIDDEN;
1390
1391 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001392 if (rc != 0)
1393 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001394
1395 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 }
Steve French60502472008-10-07 18:42:52 +00001397
1398 /* undo the setattr if we errored out and it's needed */
1399 if (rc != 0 && dosattr != 0)
1400 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1401
Steve French388e57b2008-09-16 23:50:58 +00001402out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001403 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001404 cifs_inode = CIFS_I(inode);
1405 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001406 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001407 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001408 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001409 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001410 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001411 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001412unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001414 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001415 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001416 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 return rc;
1418}
1419
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001420static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001421cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001422 const char *full_path, struct cifs_sb_info *cifs_sb,
1423 struct cifs_tcon *tcon, const unsigned int xid)
1424{
1425 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001426 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001427
1428 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001429 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001430 xid);
1431 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001432 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1433 xid, NULL);
1434
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001435 if (rc)
1436 return rc;
1437
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001438 /*
1439 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001440 * from the server or was set bogus. Also, since this is a brand new
1441 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001442 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001443 if (inode->i_nlink < 2)
1444 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001445 mode &= ~current_umask();
1446 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001447 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001448 mode |= S_ISGID;
1449
1450 if (tcon->unix_ext) {
1451 struct cifs_unix_set_info_args args = {
1452 .mode = mode,
1453 .ctime = NO_CHANGE_64,
1454 .atime = NO_CHANGE_64,
1455 .mtime = NO_CHANGE_64,
1456 .device = 0,
1457 };
1458 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001459 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001460 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001461 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001462 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001463 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001464 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001465 args.uid = INVALID_UID; /* no change */
1466 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001467 }
1468 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1469 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001470 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001471 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001472 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001473 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001474 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001475 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001476 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001477 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1478 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001479
Jeff Layton101b92d2012-09-19 06:22:45 -07001480 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1481 inode->i_uid = current_fsuid();
1482 if (inode->i_mode & S_ISGID)
1483 inode->i_gid = parent->i_gid;
1484 else
1485 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001486 }
1487 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001488 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001489 return rc;
1490}
1491
1492static int
1493cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1494 const char *full_path, struct cifs_sb_info *cifs_sb,
1495 struct cifs_tcon *tcon, const unsigned int xid)
1496{
1497 int rc = 0;
1498 u32 oplock = 0;
1499 FILE_UNIX_BASIC_INFO *info = NULL;
1500 struct inode *newinode = NULL;
1501 struct cifs_fattr fattr;
1502
1503 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1504 if (info == NULL) {
1505 rc = -ENOMEM;
1506 goto posix_mkdir_out;
1507 }
1508
1509 mode &= ~current_umask();
1510 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1511 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001512 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001513 if (rc == -EOPNOTSUPP)
1514 goto posix_mkdir_out;
1515 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001516 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001517 d_drop(dentry);
1518 goto posix_mkdir_out;
1519 }
1520
1521 if (info->Type == cpu_to_le32(-1))
1522 /* no return info, go query for it */
1523 goto posix_mkdir_get_info;
1524 /*
1525 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1526 * need to set uid/gid.
1527 */
1528
1529 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1530 cifs_fill_uniqueid(inode->i_sb, &fattr);
1531 newinode = cifs_iget(inode->i_sb, &fattr);
1532 if (!newinode)
1533 goto posix_mkdir_get_info;
1534
1535 d_instantiate(dentry, newinode);
1536
1537#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001538 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1539 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001540
1541 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001542 cifs_dbg(FYI, "unexpected number of links %d\n",
1543 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001544#endif
1545
1546posix_mkdir_out:
1547 kfree(info);
1548 return rc;
1549posix_mkdir_get_info:
1550 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1551 xid);
1552 goto posix_mkdir_out;
1553}
1554
Al Viro18bb1db2011-07-26 01:41:39 -04001555int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001557 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001558 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001560 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001561 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001562 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001563 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
Joe Perchesf96637b2013-05-04 22:12:25 -05001565 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1566 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001569 tlink = cifs_sb_tlink(cifs_sb);
1570 if (IS_ERR(tlink))
1571 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001572 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001573
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001574 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575
Steve French7f573562005-08-30 11:32:14 -07001576 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301578 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001579 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 }
Steve French50c2f752007-07-13 00:33:32 +00001581
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001582 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1583 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001584 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1585 tcon, xid);
1586 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001587 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001588 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001589
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001590 server = tcon->ses->server;
1591
1592 if (!server->ops->mkdir) {
1593 rc = -ENOSYS;
1594 goto mkdir_out;
1595 }
1596
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001598 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001600 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001602 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001604
1605 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1606 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001607mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001608 /*
1609 * Force revalidate to get parent dir info when needed since cached
1610 * attributes are invalid now.
1611 */
1612 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001614 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001615 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 return rc;
1617}
1618
1619int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1620{
1621 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001622 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001624 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001625 struct cifs_tcon *tcon;
1626 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 char *full_path = NULL;
1628 struct cifsInodeInfo *cifsInode;
1629
Joe Perchesf96637b2013-05-04 22:12:25 -05001630 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001632 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
Steve French7f573562005-08-30 11:32:14 -07001634 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301636 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001637 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 }
1639
Jeff Layton7ffec372010-09-29 19:51:11 -04001640 cifs_sb = CIFS_SB(inode->i_sb);
1641 tlink = cifs_sb_tlink(cifs_sb);
1642 if (IS_ERR(tlink)) {
1643 rc = PTR_ERR(tlink);
1644 goto rmdir_exit;
1645 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001646 tcon = tlink_tcon(tlink);
1647 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001648
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001649 if (!server->ops->rmdir) {
1650 rc = -ENOSYS;
1651 cifs_put_tlink(tlink);
1652 goto rmdir_exit;
1653 }
1654
1655 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001656 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
1658 if (!rc) {
David Howells2b0143b2015-03-17 22:25:59 +00001659 spin_lock(&d_inode(direntry)->i_lock);
1660 i_size_write(d_inode(direntry), 0);
1661 clear_nlink(d_inode(direntry));
1662 spin_unlock(&d_inode(direntry)->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 }
1664
David Howells2b0143b2015-03-17 22:25:59 +00001665 cifsInode = CIFS_I(d_inode(direntry));
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001666 /* force revalidate to go get info when needed */
1667 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001668
1669 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001670 /*
1671 * Force revalidate to get parent dir info when needed since cached
1672 * attributes are invalid now.
1673 */
1674 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001675
David Howells2b0143b2015-03-17 22:25:59 +00001676 d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 current_fs_time(inode->i_sb);
1678
Jeff Layton7ffec372010-09-29 19:51:11 -04001679rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001681 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 return rc;
1683}
1684
Steve Frenchee2fd962008-09-23 18:23:33 +00001685static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001686cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1687 const char *from_path, struct dentry *to_dentry,
1688 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001689{
1690 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001691 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001692 struct cifs_tcon *tcon;
1693 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001694 struct cifs_fid fid;
1695 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001696 int oplock, rc;
1697
Jeff Layton7ffec372010-09-29 19:51:11 -04001698 tlink = cifs_sb_tlink(cifs_sb);
1699 if (IS_ERR(tlink))
1700 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001701 tcon = tlink_tcon(tlink);
1702 server = tcon->ses->server;
1703
1704 if (!server->ops->rename)
1705 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001706
Steve Frenchee2fd962008-09-23 18:23:33 +00001707 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001708 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001709
1710 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001711 * Don't bother with rename by filehandle unless file is busy and
1712 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001713 * rename by filehandle to various Windows servers.
1714 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001715 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001716 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001717
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001718 /* open-file renames don't work across directories */
1719 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001720 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001721
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001722 oparms.tcon = tcon;
1723 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00001724 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001725 oparms.desired_access = DELETE;
1726 oparms.create_options = CREATE_NOT_DIR;
1727 oparms.disposition = FILE_OPEN;
1728 oparms.path = from_path;
1729 oparms.fid = &fid;
1730 oparms.reconnect = false;
1731
1732 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00001733 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001734 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001735 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001736 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001737 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001738 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001739do_rename_exit:
1740 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001741 return rc;
1742}
1743
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001744int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001745cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
1746 struct inode *target_dir, struct dentry *target_dentry,
1747 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001749 char *from_name = NULL;
1750 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001751 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001752 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001753 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001754 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1755 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001756 unsigned int xid;
1757 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001759 if (flags & ~RENAME_NOREPLACE)
1760 return -EINVAL;
1761
Jeff Layton639e7a92010-09-03 11:50:09 -04001762 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001763 tlink = cifs_sb_tlink(cifs_sb);
1764 if (IS_ERR(tlink))
1765 return PTR_ERR(tlink);
1766 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001768 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001769
1770 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001771 * we already have the rename sem so we do not need to
1772 * grab it again here to protect the path integrity
1773 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001774 from_name = build_path_from_dentry(source_dentry);
1775 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 rc = -ENOMEM;
1777 goto cifs_rename_exit;
1778 }
1779
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001780 to_name = build_path_from_dentry(target_dentry);
1781 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001782 rc = -ENOMEM;
1783 goto cifs_rename_exit;
1784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001786 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1787 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001788
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001789 /*
1790 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
1791 */
1792 if (flags & RENAME_NOREPLACE)
1793 goto cifs_rename_exit;
1794
Jeff Layton14121bd2008-10-20 14:45:22 -04001795 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001796 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001797 * Are src and dst hardlinks of same inode? We can only tell
1798 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001799 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001800 info_buf_source =
1801 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1802 GFP_KERNEL);
1803 if (info_buf_source == NULL) {
1804 rc = -ENOMEM;
1805 goto cifs_rename_exit;
1806 }
1807
1808 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001809 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1810 info_buf_source,
1811 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001812 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04001813 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001814 goto unlink_target;
1815
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001816 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1817 info_buf_target,
1818 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001819 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04001820
Jeff Layton8d281ef2008-10-22 13:57:01 -04001821 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001822 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001823 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001824 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001825 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001826 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001827 }
1828 /*
1829 * else ... BB we could add the same check for Windows by
1830 * checking the UniqueId via FILE_INTERNAL_INFO
1831 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001832
Jeff Layton14121bd2008-10-20 14:45:22 -04001833unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001834 /* Try unlinking the target dentry if it's not negative */
David Howells2b0143b2015-03-17 22:25:59 +00001835 if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04001836 if (d_is_dir(target_dentry))
1837 tmprc = cifs_rmdir(target_dir, target_dentry);
1838 else
1839 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001840 if (tmprc)
1841 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001842 rc = cifs_do_rename(xid, source_dentry, from_name,
1843 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 }
1845
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001846 /* force revalidate to go get info when needed */
1847 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1848
1849 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
1850 target_dir->i_mtime = current_fs_time(source_dir->i_sb);
1851
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001853 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001854 kfree(from_name);
1855 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001856 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001857 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 return rc;
1859}
1860
Jeff Laytondf2cf172010-02-12 07:44:16 -05001861static bool
1862cifs_inode_needs_reval(struct inode *inode)
1863{
1864 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301865 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001866
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001867 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001868 return false;
1869
1870 if (!lookupCacheEnabled)
1871 return true;
1872
1873 if (cifs_i->time == 0)
1874 return true;
1875
Jeff Laytona87c9ad2014-03-26 07:24:23 -07001876 if (!cifs_sb->actimeo)
1877 return true;
1878
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301879 if (!time_in_range(jiffies, cifs_i->time,
1880 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001881 return true;
1882
Jeff Laytondb192722010-05-17 14:51:49 -04001883 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301884 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001885 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1886 return true;
1887
Jeff Laytondf2cf172010-02-12 07:44:16 -05001888 return false;
1889}
1890
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301891/*
1892 * Zap the cache. Called when invalid_mapping flag is set.
1893 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001894int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001895cifs_invalidate_mapping(struct inode *inode)
1896{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001897 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001898
Jeff Laytondf2cf172010-02-12 07:44:16 -05001899 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001900 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001901 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001902 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1903 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001904 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001905
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301906 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001907 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001908}
1909
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001910/**
1911 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
1912 * @word: long word containing the bit lock
1913 */
1914static int
Peter Zijlstradfd01f02015-12-13 22:11:16 +01001915cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001916{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001917 freezable_schedule_unsafe();
Peter Zijlstradfd01f02015-12-13 22:11:16 +01001918 if (signal_pending_state(mode, current))
1919 return -ERESTARTSYS;
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001920 return 0;
1921}
1922
Jeff Laytone284e532014-04-30 09:31:46 -04001923int
1924cifs_revalidate_mapping(struct inode *inode)
1925{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001926 int rc;
1927 unsigned long *flags = &CIFS_I(inode)->flags;
1928
NeilBrown74316202014-07-07 15:16:04 +10001929 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
1930 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001931 if (rc)
1932 return rc;
1933
1934 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
1935 rc = cifs_invalidate_mapping(inode);
1936 if (rc)
1937 set_bit(CIFS_INO_INVALID_MAPPING, flags);
1938 }
1939
1940 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07001941 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001942 wake_up_bit(flags, CIFS_INO_LOCK);
1943
1944 return rc;
1945}
1946
1947int
1948cifs_zap_mapping(struct inode *inode)
1949{
1950 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
1951 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04001952}
1953
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001954int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001955{
1956 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001957 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001958 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001959
1960 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001961 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001962
Jeff Layton13cfb732010-09-29 19:51:11 -04001963 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001964 rc = cifs_get_file_info_unix(filp);
1965 else
1966 rc = cifs_get_file_info(filp);
1967
Jeff Laytonabab0952010-02-12 07:44:18 -05001968 return rc;
1969}
1970
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001971int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001973 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001974 int rc = 0;
David Howells2b0143b2015-03-17 22:25:59 +00001975 struct inode *inode = d_inode(dentry);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001976 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001977 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978
Jeff Laytondf2cf172010-02-12 07:44:16 -05001979 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 return -ENOENT;
1981
Jeff Laytondf2cf172010-02-12 07:44:16 -05001982 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001983 return rc;
1984
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001985 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
1987 /* can not safely grab the rename sem here if rename calls revalidate
1988 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001989 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301991 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001992 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001994
Joe Perchesf96637b2013-05-04 22:12:25 -05001995 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1996 full_path, inode, inode->i_count.counter,
Miklos Szeredia00be0e2016-09-16 12:44:21 +02001997 dentry, cifs_get_time(dentry), jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998
Jeff Layton0d424ad2010-09-20 16:01:35 -07001999 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05002000 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
2001 else
2002 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
2003 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002005out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002007 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 return rc;
2009}
2010
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002011int cifs_revalidate_file(struct file *filp)
2012{
2013 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05002014 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002015
2016 rc = cifs_revalidate_file_attr(filp);
2017 if (rc)
2018 return rc;
2019
Jeff Laytone284e532014-04-30 09:31:46 -04002020 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002021}
2022
2023/* revalidate a dentry's inode attributes */
2024int cifs_revalidate_dentry(struct dentry *dentry)
2025{
2026 int rc;
David Howells2b0143b2015-03-17 22:25:59 +00002027 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002028
2029 rc = cifs_revalidate_dentry_attr(dentry);
2030 if (rc)
2031 return rc;
2032
Jeff Laytone284e532014-04-30 09:31:46 -04002033 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002034}
2035
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04002037 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002039 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002040 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howells2b0143b2015-03-17 22:25:59 +00002041 struct inode *inode = d_inode(dentry);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002042 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04002043
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002044 /*
2045 * We need to be sure that all dirty pages are written and the server
2046 * has actual ctime, mtime and file length.
2047 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04002048 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002049 inode->i_mapping->nrpages != 0) {
2050 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00002051 if (rc) {
2052 mapping_set_error(inode->i_mapping, rc);
2053 return rc;
2054 }
Steve French5fe14c82006-11-07 19:26:33 +00002055 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002056
2057 rc = cifs_revalidate_dentry_attr(dentry);
2058 if (rc)
2059 return rc;
2060
2061 generic_fillattr(inode, stat);
2062 stat->blksize = CIFS_MAX_MSGSIZE;
2063 stat->ino = CIFS_I(inode)->uniqueid;
2064
2065 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002066 * If on a multiuser mount without unix extensions or cifsacl being
2067 * enabled, and the admin hasn't overridden them, set the ownership
2068 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002069 */
2070 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05002071 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04002072 !tcon->unix_ext) {
2073 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
2074 stat->uid = current_fsuid();
2075 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
2076 stat->gid = current_fsgid();
2077 }
2078 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079}
2080
2081static int cifs_truncate_page(struct address_space *mapping, loff_t from)
2082{
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002083 pgoff_t index = from >> PAGE_SHIFT;
2084 unsigned offset = from & (PAGE_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 int rc = 0;
2087
2088 page = grab_cache_page(mapping, index);
2089 if (!page)
2090 return -ENOMEM;
2091
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002092 zero_user_segment(page, offset, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 unlock_page(page);
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03002094 put_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 return rc;
2096}
2097
Christoph Hellwig1b947462010-07-18 17:51:21 -04002098static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00002099{
Steve Frenchba6a46a2007-02-26 20:06:29 +00002100 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00002101 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00002102 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04002103
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07002104 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00002105}
2106
Jeff Layton8efdbde2008-07-23 21:28:12 +00002107static int
2108cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002109 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002110{
2111 int rc;
2112 struct cifsFileInfo *open_file;
2113 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2114 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002115 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002116 struct cifs_tcon *tcon = NULL;
2117 struct TCP_Server_Info *server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002118
2119 /*
2120 * To avoid spurious oplock breaks from server, in the case of
2121 * inodes that we already have open, avoid doing path based
2122 * setting of file size if we can do it by handle.
2123 * This keeps our caching token (oplock) and avoids timeouts
2124 * when the local oplock break takes longer to flush
2125 * writebehind data than the SMB timeout for the SetPathInfo
2126 * request would allow
2127 */
Jeff Layton6508d902010-09-29 19:51:11 -04002128 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002129 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002130 tcon = tlink_tcon(open_file->tlink);
2131 server = tcon->ses->server;
2132 if (server->ops->set_file_size)
2133 rc = server->ops->set_file_size(xid, tcon, open_file,
2134 attrs->ia_size, false);
2135 else
2136 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002137 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002138 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002139 } else
2140 rc = -EINVAL;
2141
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002142 if (!rc)
2143 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07002144
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002145 if (tcon == NULL) {
2146 tlink = cifs_sb_tlink(cifs_sb);
2147 if (IS_ERR(tlink))
2148 return PTR_ERR(tlink);
2149 tcon = tlink_tcon(tlink);
2150 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002151 }
2152
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002153 /*
2154 * Set file size by pathname rather than by handle either because no
2155 * valid, writeable file handle for it was found or because there was
2156 * an error setting it by handle.
2157 */
2158 if (server->ops->set_path_size)
2159 rc = server->ops->set_path_size(xid, tcon, full_path,
2160 attrs->ia_size, cifs_sb, false);
2161 else
2162 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002163 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002164
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002165 if (tlink)
2166 cifs_put_tlink(tlink);
2167
2168set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002169 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002170 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002171 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002172 cifs_truncate_page(inode->i_mapping, inode->i_size);
2173 }
2174
2175 return rc;
2176}
2177
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002178static int
2179cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2180{
2181 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002182 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002183 char *full_path = NULL;
David Howells2b0143b2015-03-17 22:25:59 +00002184 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002185 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2186 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002187 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002188 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002189 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002190 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002191
Al Viro35c265e2014-08-19 20:25:34 -04002192 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2193 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002194
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002195 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002196
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002197 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2198 attrs->ia_valid |= ATTR_FORCE;
2199
Jan Kara31051c82016-05-26 16:55:18 +02002200 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002201 if (rc < 0)
2202 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002203
2204 full_path = build_path_from_dentry(direntry);
2205 if (full_path == NULL) {
2206 rc = -ENOMEM;
2207 goto out;
2208 }
2209
Jeff Layton0f4d6342009-03-26 13:35:37 -04002210 /*
2211 * Attempt to flush data before changing attributes. We need to do
2212 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2213 * ownership or mode then we may also need to do this. Here, we take
2214 * the safe way out and just do the flush on all setattr requests. If
2215 * the flush returns error, store it to report later and continue.
2216 *
2217 * BB: This should be smarter. Why bother flushing pages that
2218 * will be truncated anyway? Also, should we error out here if
2219 * the flush returns error?
2220 */
2221 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002222 mapping_set_error(inode->i_mapping, rc);
2223 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002224
2225 if (attrs->ia_valid & ATTR_SIZE) {
2226 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2227 if (rc != 0)
2228 goto out;
2229 }
2230
2231 /* skip mode change if it's just for clearing setuid/setgid */
2232 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2233 attrs->ia_valid &= ~ATTR_MODE;
2234
2235 args = kmalloc(sizeof(*args), GFP_KERNEL);
2236 if (args == NULL) {
2237 rc = -ENOMEM;
2238 goto out;
2239 }
2240
2241 /* set up the struct */
2242 if (attrs->ia_valid & ATTR_MODE)
2243 args->mode = attrs->ia_mode;
2244 else
2245 args->mode = NO_CHANGE_64;
2246
2247 if (attrs->ia_valid & ATTR_UID)
2248 args->uid = attrs->ia_uid;
2249 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002250 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002251
2252 if (attrs->ia_valid & ATTR_GID)
2253 args->gid = attrs->ia_gid;
2254 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002255 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002256
2257 if (attrs->ia_valid & ATTR_ATIME)
2258 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2259 else
2260 args->atime = NO_CHANGE_64;
2261
2262 if (attrs->ia_valid & ATTR_MTIME)
2263 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2264 else
2265 args->mtime = NO_CHANGE_64;
2266
2267 if (attrs->ia_valid & ATTR_CTIME)
2268 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2269 else
2270 args->ctime = NO_CHANGE_64;
2271
2272 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002273 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002274 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002275 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002276 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002277 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002278 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002279 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002280 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002281 tlink = cifs_sb_tlink(cifs_sb);
2282 if (IS_ERR(tlink)) {
2283 rc = PTR_ERR(tlink);
2284 goto out;
2285 }
2286 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002287 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002288 cifs_sb->local_nls,
Nakajima Akirabc8ebdc42015-02-13 15:35:58 +09002289 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -04002290 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002291 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002292
Christoph Hellwig10257742010-06-04 11:30:02 +02002293 if (rc)
2294 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002295
Christoph Hellwig10257742010-06-04 11:30:02 +02002296 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002297 attrs->ia_size != i_size_read(inode))
2298 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002299
2300 setattr_copy(inode, attrs);
2301 mark_inode_dirty(inode);
2302
2303 /* force revalidate when any of these times are set since some
2304 of the fs types (eg ext3, fat) do not have fine enough
2305 time granularity to match protocol, and we do not have a
2306 a way (yet) to query the server fs's time granularity (and
2307 whether it rounds times down).
2308 */
2309 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2310 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002311out:
2312 kfree(args);
2313 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002314 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002315 return rc;
2316}
2317
Jeff Layton0510eeb2008-08-02 07:26:12 -04002318static int
2319cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002321 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002322 kuid_t uid = INVALID_UID;
2323 kgid_t gid = INVALID_GID;
David Howells2b0143b2015-03-17 22:25:59 +00002324 struct inode *inode = d_inode(direntry);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002325 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002326 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 char *full_path = NULL;
2328 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002329 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002330 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002331
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002332 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333
Al Viro35c265e2014-08-19 20:25:34 -04002334 cifs_dbg(FYI, "setattr on file %pd attrs->iavalid 0x%x\n",
2335 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002336
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002337 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2338 attrs->ia_valid |= ATTR_FORCE;
2339
Jan Kara31051c82016-05-26 16:55:18 +02002340 rc = setattr_prepare(direntry, attrs);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002341 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002342 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002343 return rc;
Steve French6473a552005-11-29 20:20:10 -08002344 }
Steve French50c2f752007-07-13 00:33:32 +00002345
Steve French7f573562005-08-30 11:32:14 -07002346 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302348 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002349 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302350 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352
Jeff Layton0f4d6342009-03-26 13:35:37 -04002353 /*
2354 * Attempt to flush data before changing attributes. We need to do
2355 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2356 * ownership or mode then we may also need to do this. Here, we take
2357 * the safe way out and just do the flush on all setattr requests. If
2358 * the flush returns error, store it to report later and continue.
2359 *
2360 * BB: This should be smarter. Why bother flushing pages that
2361 * will be truncated anyway? Also, should we error out here if
2362 * the flush returns error?
2363 */
2364 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002365 mapping_set_error(inode->i_mapping, rc);
2366 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002367
Steve French50531442008-03-14 19:21:31 +00002368 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002369 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2370 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002371 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002373
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002374 if (attrs->ia_valid & ATTR_UID)
2375 uid = attrs->ia_uid;
2376
2377 if (attrs->ia_valid & ATTR_GID)
2378 gid = attrs->ia_gid;
2379
2380#ifdef CONFIG_CIFS_ACL
2381 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002382 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002383 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2384 uid, gid);
2385 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002386 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2387 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002388 goto cifs_setattr_exit;
2389 }
2390 }
2391 } else
2392#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002393 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002394 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395
Jeff Laytond32c4f22007-10-18 03:05:22 -07002396 /* skip mode change if it's just for clearing setuid/setgid */
2397 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2398 attrs->ia_valid &= ~ATTR_MODE;
2399
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002402 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002403#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002404 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002405 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002406 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002407 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002408 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2409 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002410 goto cifs_setattr_exit;
2411 }
2412 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002413#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002414 if (((mode & S_IWUGO) == 0) &&
2415 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002416
2417 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2418
Jeff Layton51328612008-05-22 09:33:34 -04002419 /* fix up mode if we're not using dynperm */
2420 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2421 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2422 } else if ((mode & S_IWUGO) &&
2423 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002424
2425 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2426 /* Attributes of 0 are ignored */
2427 if (dosattr == 0)
2428 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002429
2430 /* reset local inode permissions to normal */
2431 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2432 attrs->ia_mode &= ~(S_IALLUGO);
2433 if (S_ISDIR(inode->i_mode))
2434 attrs->ia_mode |=
2435 cifs_sb->mnt_dir_mode;
2436 else
2437 attrs->ia_mode |=
2438 cifs_sb->mnt_file_mode;
2439 }
2440 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2441 /* ignore mode change - ATTR_READONLY hasn't changed */
2442 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 }
2445
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002446 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2447 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2448 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2449 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
Steve Frenche30dcf32005-09-20 20:49:16 -07002451 /* Even if error on time set, no sense failing the call if
2452 the server would set the time to a reasonable value anyway,
2453 and this check ensures that we are not being called from
2454 sys_utimes in which case we ought to fail the call back to
2455 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002456 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002457 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002458 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 }
2460
2461 /* do not need local check to inode_check_ok since the server does
2462 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002463 if (rc)
2464 goto cifs_setattr_exit;
2465
2466 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002467 attrs->ia_size != i_size_read(inode))
2468 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002469
2470 setattr_copy(inode, attrs);
2471 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002472
Steve Frenche30dcf32005-09-20 20:49:16 -07002473cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002475 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 return rc;
2477}
2478
Jeff Layton0510eeb2008-08-02 07:26:12 -04002479int
2480cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2481{
Al Virofc640052016-04-10 01:33:30 -04002482 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002483 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002484
2485 if (pTcon->unix_ext)
2486 return cifs_setattr_unix(direntry, attrs);
2487
2488 return cifs_setattr_nounix(direntry, attrs);
2489
2490 /* BB: add cifs_setattr_legacy for really old servers */
2491}
2492
Steve French99ee4db2007-02-27 05:35:17 +00002493#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494void cifs_delete_inode(struct inode *inode)
2495{
Joe Perchesf96637b2013-05-04 22:12:25 -05002496 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 /* may have to add back in if and when safe distributed caching of
2498 directories added e.g. via FindNotify */
2499}
Steve French99ee4db2007-02-27 05:35:17 +00002500#endif