blob: 2d4f37235ed0fa360782ae237c89fccccbf8b719 [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 <
Christoph Hellwig70eff552008-02-15 20:55:05 +000062 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
63 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,
Steve French737b7582005-04-28 22:41:06 -0700376 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
377 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400378 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400379
380 if (!rc) {
381 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
382 } else if (rc == -EREMOTE) {
383 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700384 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400385 } else {
386 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000387 }
388
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200389 /* check for Minshall+French symlinks */
390 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000391 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
392 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200393 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000394 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200395 }
396
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400397 if (*pinode == NULL) {
398 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400399 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400400 *pinode = cifs_iget(sb, &fattr);
401 if (!*pinode)
402 rc = -ENOMEM;
403 } else {
404 /* we already have inode, update it */
405 cifs_fattr_to_inode(*pinode, &fattr);
406 }
Steve French0e4bbde2008-05-20 19:50:46 +0000407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 return rc;
409}
410
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400411static int
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400412cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400413 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800414{
415 int rc;
Steve Frenchdb8b6312014-09-22 05:13:55 -0500416 __u32 oplock;
Jeff Layton7ffec372010-09-29 19:51:11 -0400417 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000418 struct cifs_tcon *tcon;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400419 struct cifs_fid fid;
420 struct cifs_open_parms oparms;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000421 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800422 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800423 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000424 char *pbuf;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400425 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800426
427 pbuf = buf;
428
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400429 fattr->cf_mode &= ~S_IFMT;
430
431 if (fattr->cf_eof == 0) {
432 fattr->cf_mode |= S_IFIFO;
433 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800434 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400435 } else if (fattr->cf_eof < 8) {
436 fattr->cf_mode |= S_IFREG;
437 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800438 return -EINVAL; /* EOPNOTSUPP? */
439 }
Steve French50c2f752007-07-13 00:33:32 +0000440
Jeff Layton7ffec372010-09-29 19:51:11 -0400441 tlink = cifs_sb_tlink(cifs_sb);
442 if (IS_ERR(tlink))
443 return PTR_ERR(tlink);
444 tcon = tlink_tcon(tlink);
445
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400446 oparms.tcon = tcon;
447 oparms.cifs_sb = cifs_sb;
448 oparms.desired_access = GENERIC_READ;
449 oparms.create_options = CREATE_NOT_DIR;
450 oparms.disposition = FILE_OPEN;
451 oparms.path = path;
452 oparms.fid = &fid;
453 oparms.reconnect = false;
454
Steve Frenchdb8b6312014-09-22 05:13:55 -0500455 if (tcon->ses->server->oplocks)
456 oplock = REQ_OPLOCK;
457 else
458 oplock = 0;
459 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400460 if (rc) {
Steve Frenchdb8b6312014-09-22 05:13:55 -0500461 cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400462 cifs_put_tlink(tlink);
463 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800464 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400465
466 /* Read header */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400467 io_parms.netfid = fid.netfid;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400468 io_parms.pid = current->tgid;
469 io_parms.tcon = tcon;
470 io_parms.offset = 0;
471 io_parms.length = 24;
472
Steve Frenchdb8b6312014-09-22 05:13:55 -0500473 rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
474 &bytes_read, &pbuf, &buf_type);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400475 if ((rc == 0) && (bytes_read >= 8)) {
476 if (memcmp("IntxBLK", pbuf, 8) == 0) {
477 cifs_dbg(FYI, "Block device\n");
478 fattr->cf_mode |= S_IFBLK;
479 fattr->cf_dtype = DT_BLK;
480 if (bytes_read == 24) {
481 /* we have enough to decode dev num */
482 __u64 mjr; /* major */
483 __u64 mnr; /* minor */
484 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
485 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
486 fattr->cf_rdev = MKDEV(mjr, mnr);
487 }
488 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
489 cifs_dbg(FYI, "Char device\n");
490 fattr->cf_mode |= S_IFCHR;
491 fattr->cf_dtype = DT_CHR;
492 if (bytes_read == 24) {
493 /* we have enough to decode dev num */
494 __u64 mjr; /* major */
495 __u64 mnr; /* minor */
496 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
497 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
498 fattr->cf_rdev = MKDEV(mjr, mnr);
499 }
500 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
501 cifs_dbg(FYI, "Symlink\n");
502 fattr->cf_mode |= S_IFLNK;
503 fattr->cf_dtype = DT_LNK;
504 } else {
505 fattr->cf_mode |= S_IFREG; /* file? */
506 fattr->cf_dtype = DT_REG;
507 rc = -EOPNOTSUPP;
508 }
509 } else {
510 fattr->cf_mode |= S_IFREG; /* then it is a file */
511 fattr->cf_dtype = DT_REG;
512 rc = -EOPNOTSUPP; /* or some unknown SFU type */
513 }
Steve Frenchdb8b6312014-09-22 05:13:55 -0500514
515 tcon->ses->server->ops->close(xid, tcon, &fid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400516 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800517 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800518}
519
Steve French9e294f12005-11-17 16:59:21 -0800520#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
521
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400522/*
523 * Fetch mode bits as provided by SFU.
524 *
525 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
526 */
527static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400528 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800529{
Steve French3020a1f2005-11-18 11:31:10 -0800530#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800531 ssize_t rc;
532 char ea_value[4];
533 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400534 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000535 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800536
Jeff Layton7ffec372010-09-29 19:51:11 -0400537 tlink = cifs_sb_tlink(cifs_sb);
538 if (IS_ERR(tlink))
539 return PTR_ERR(tlink);
540 tcon = tlink_tcon(tlink);
541
Steve Frenchd979f3b2014-02-01 23:27:18 -0600542 if (tcon->ses->server->ops->query_all_EAs == NULL) {
543 cifs_put_tlink(tlink);
544 return -EOPNOTSUPP;
545 }
546
547 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
548 "SETFILEBITS", ea_value, 4 /* size of buf */,
549 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -0500550 cifs_remap(cifs_sb));
Jeff Layton7ffec372010-09-29 19:51:11 -0400551 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000552 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800553 return (int)rc;
554 else if (rc > 3) {
555 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400556 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500557 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
558 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400559 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500560 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800561 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400562
563 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800564#else
565 return -EOPNOTSUPP;
566#endif
Steve French9e294f12005-11-17 16:59:21 -0800567}
568
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400569/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000570static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400571cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400572 struct cifs_sb_info *cifs_sb, bool adjust_tz,
573 bool symlink)
Steve Frenchb9a32602008-05-20 21:52:32 +0000574{
Steve French96daf2b2011-05-27 04:34:02 +0000575 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700576
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400577 memset(fattr, 0, sizeof(*fattr));
578 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
579 if (info->DeletePending)
580 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000581
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400582 if (info->LastAccessTime)
583 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
584 else
585 fattr->cf_atime = CURRENT_TIME;
586
587 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
588 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
589
590 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700591 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
592 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400593 }
594
595 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
596 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500597 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400598
Jim McDonough74d290d2013-09-21 10:36:10 -0500599 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400600
601 if (symlink) {
602 fattr->cf_mode = S_IFLNK;
603 fattr->cf_dtype = DT_LNK;
604 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400605 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
606 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300607 /*
608 * Server can return wrong NumberOfLinks value for directories
609 * when Unix extensions are disabled - fake it.
610 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500611 if (!tcon->unix_ext)
612 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400613 } else {
614 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
615 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400616
Jeff Laytond0c280d2009-07-09 01:46:44 -0400617 /* clear write bits if ATTR_READONLY is set */
618 if (fattr->cf_cifsattrs & ATTR_READONLY)
619 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400620
Jim McDonough74d290d2013-09-21 10:36:10 -0500621 /*
622 * Don't accept zero nlink from non-unix servers unless
623 * delete is pending. Instead mark it as unknown.
624 */
625 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
626 !info->DeletePending) {
627 cifs_dbg(1, "bogus file nlink value %u\n",
Steve French6658b9f2013-07-04 14:38:48 -0500628 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500629 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500630 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300631 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400632
633 fattr->cf_uid = cifs_sb->mnt_uid;
634 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000635}
636
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700637static int
638cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500639{
640 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400641 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500642 FILE_ALL_INFO find_data;
643 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500644 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500645 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700646 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000647 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700648 struct TCP_Server_Info *server = tcon->ses->server;
649
650 if (!server->ops->query_file_info)
651 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500652
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400653 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700654 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400655 switch (rc) {
656 case 0:
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400657 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false,
658 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400659 break;
660 case -EREMOTE:
661 cifs_create_dfs_fattr(&fattr, inode->i_sb);
662 rc = 0;
663 break;
664 case -EOPNOTSUPP:
665 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500666 /*
667 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000668 * for now, just skip revalidating and mark inode for
669 * immediate reval.
670 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500671 rc = 0;
672 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400673 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500674 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400675 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500676
677 /*
678 * don't bother with SFU junk here -- just mark inode as needing
679 * revalidation.
680 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500681 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
682 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
683 cifs_fattr_to_inode(inode, &fattr);
684cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400685 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500686 return rc;
687}
688
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400689int
690cifs_get_inode_info(struct inode **inode, const char *full_path,
691 FILE_ALL_INFO *data, struct super_block *sb, int xid,
Steve French42eacf92014-02-10 14:08:16 -0600692 const struct cifs_fid *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500694 bool validinum = false;
695 __u16 srchflgs;
696 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400697 struct cifs_tcon *tcon;
698 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400699 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400702 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400703 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500704 struct cifs_search_info *srchinf = NULL;
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400705 bool symlink = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Jeff Layton7ffec372010-09-29 19:51:11 -0400707 tlink = cifs_sb_tlink(cifs_sb);
708 if (IS_ERR(tlink))
709 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400710 tcon = tlink_tcon(tlink);
711 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400712
Joe Perchesf96637b2013-05-04 22:12:25 -0500713 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400715 if ((data == NULL) && (*inode != NULL)) {
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400716 if (CIFS_CACHE_READ(CIFS_I(*inode))) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500717 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400718 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 }
720 }
721
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400722 /* if inode info is not passed, get it from server */
723 if (data == NULL) {
724 if (!server->ops->query_path_info) {
725 rc = -ENOSYS;
726 goto cgii_exit;
727 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400729 if (buf == NULL) {
730 rc = -ENOMEM;
731 goto cgii_exit;
732 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400733 data = (FILE_ALL_INFO *)buf;
734 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400735 data, &adjust_tz, &symlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400737
738 if (!rc) {
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400739 cifs_all_info_to_fattr(&fattr, data, cifs_sb, adjust_tz,
740 symlink);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400741 } else if (rc == -EREMOTE) {
742 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000743 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500744 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
745 srchinf = kzalloc(sizeof(struct cifs_search_info),
746 GFP_KERNEL);
747 if (srchinf == NULL) {
748 rc = -ENOMEM;
749 goto cgii_exit;
750 }
751
752 srchinf->endOfSearch = false;
753 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
754
755 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
756 CIFS_SEARCH_CLOSE_AT_END |
757 CIFS_SEARCH_BACKUP_SEARCH;
758
759 rc = CIFSFindFirst(xid, tcon, full_path,
760 cifs_sb, NULL, srchflgs, srchinf, false);
761 if (!rc) {
762 data =
763 (FILE_ALL_INFO *)srchinf->srch_entries_start;
764
765 cifs_dir_info_to_fattr(&fattr,
766 (FILE_DIRECTORY_INFO *)data, cifs_sb);
767 fattr.cf_uniqueid = le64_to_cpu(
768 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
769 validinum = true;
770
771 cifs_buf_release(srchinf->ntwrk_buf_start);
772 }
773 kfree(srchinf);
774 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000775 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400777 /*
778 * If an inode wasn't passed in, then get the inode number
779 *
780 * Is an i_ino of zero legal? Can we use that to check if the server
781 * supports returning inode numbers? Are there other sanity checks we
782 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400783 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400784 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000785 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500786 if (validinum == false) {
787 if (server->ops->get_srv_inum)
788 tmprc = server->ops->get_srv_inum(xid,
789 tcon, cifs_sb, full_path,
790 &fattr.cf_uniqueid, data);
791 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500792 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
793 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500794 fattr.cf_uniqueid = iunique(sb, ROOT_I);
795 cifs_autodisable_serverino(cifs_sb);
796 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500797 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500798 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400799 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500800 } else
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400801 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000802
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400803 /* query for SFU type info if supported and needed */
804 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
805 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
806 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
807 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500808 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000809 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000810
Jeff Layton79df1ba2010-12-06 12:52:08 -0500811#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000812 /* fill in 0777 bits from ACL */
813 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400814 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600815 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500816 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
817 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600818 goto cgii_exit;
819 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000820 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500821#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400822
823 /* fill in remaining high mode bits e.g. SUID, VTX */
824 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
825 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
826
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200827 /* check for Minshall+French symlinks */
828 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000829 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
830 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200831 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000832 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200833 }
834
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400835 if (!*inode) {
836 *inode = cifs_iget(sb, &fattr);
837 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400838 rc = -ENOMEM;
839 } else {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400840 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000841 }
842
Igor Mammedov79626702008-03-09 03:44:18 +0000843cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400845 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 return rc;
847}
848
Steve French7f8ed422007-09-28 22:28:55 +0000849static const struct inode_operations cifs_ipc_inode_ops = {
850 .lookup = cifs_lookup,
851};
852
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400853static int
854cifs_find_inode(struct inode *inode, void *opaque)
855{
856 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
857
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400858 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400859 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
860 return 0;
861
Jeff Layton20054bd2011-01-07 11:30:27 -0500862 /* use createtime like an i_generation field */
863 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
864 return 0;
865
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400866 /* don't match inode of different type */
867 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
868 return 0;
869
Jeff Layton5acfec22010-08-02 17:43:54 -0400870 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400871 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400872 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400873
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400874 return 1;
875}
876
877static int
878cifs_init_inode(struct inode *inode, void *opaque)
879{
880 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
881
882 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500883 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400884 return 0;
885}
886
Jeff Layton5acfec22010-08-02 17:43:54 -0400887/*
888 * walk dentry list for an inode and report whether it has aliases that
889 * are hashed. We use this to determine if a directory inode can actually
890 * be used.
891 */
892static bool
893inode_has_hashed_dentries(struct inode *inode)
894{
895 struct dentry *dentry;
896
Nick Piggin873feea2011-01-07 17:50:06 +1100897 spin_lock(&inode->i_lock);
Al Viro946e51f2014-10-26 19:19:16 -0400898 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400899 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100900 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400901 return true;
902 }
903 }
Nick Piggin873feea2011-01-07 17:50:06 +1100904 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400905 return false;
906}
907
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400908/* Given fattrs, get a corresponding inode */
909struct inode *
910cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
911{
912 unsigned long hash;
913 struct inode *inode;
914
Jeff Layton3d694382010-05-11 14:59:55 -0400915retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -0500916 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400917
918 /* hash down to 32-bits on 32-bit arch */
919 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
920
921 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400922 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400923 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400924 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400925 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400926
927 if (inode_has_hashed_dentries(inode)) {
928 cifs_autodisable_serverino(CIFS_SB(sb));
929 iput(inode);
930 fattr->cf_uniqueid = iunique(sb, ROOT_I);
931 goto retry_iget5_locked;
932 }
Jeff Layton3d694382010-05-11 14:59:55 -0400933 }
934
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400935 cifs_fattr_to_inode(inode, fattr);
936 if (sb->s_flags & MS_NOATIME)
937 inode->i_flags |= S_NOATIME | S_NOCMTIME;
938 if (inode->i_state & I_NEW) {
939 inode->i_ino = hash;
Steve French0ccd4802010-07-16 04:31:02 +0000940#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530941 /* initialize per-inode cache cookie pointer */
942 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000943#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400944 unlock_new_inode(inode);
945 }
946 }
947
948 return inode;
949}
950
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600952struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400954 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700955 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400956 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800957 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000958 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800959
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400960 xid = get_xid();
Steve Frenchb5b374ea2014-10-06 01:01:03 -0500961 if (tcon->unix_ext) {
Steve Frenchf87d39d2011-05-27 03:50:55 +0000962 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Steve Frenchb5b374ea2014-10-06 01:01:03 -0500963 /* some servers mistakenly claim POSIX support */
964 if (rc != -EOPNOTSUPP)
965 goto iget_no_retry;
966 cifs_dbg(VFS, "server does not support POSIX extensions");
967 tcon->unix_ext = false;
968 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400969
Steve Frenchb5b374ea2014-10-06 01:01:03 -0500970 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
971
972iget_no_retry:
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000973 if (!inode) {
974 inode = ERR_PTR(rc);
975 goto out;
976 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400977
Steve French0ccd4802010-07-16 04:31:02 +0000978#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530979 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700980 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000981#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530982
Jeff Layton0d424ad2010-09-20 16:01:35 -0700983 if (rc && tcon->ipc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500984 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -0500985 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +0000986 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200987 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +0000988 inode->i_op = &cifs_ipc_inode_ops;
989 inode->i_fop = &simple_dir_operations;
990 inode->i_uid = cifs_sb->mnt_uid;
991 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -0500992 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +0000993 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800994 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000995 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000996 }
997
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000998out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400999 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -08001000 * TODO: This is no longer true
1001 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001002 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -08001003 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004}
1005
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001006int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001007cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001008 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001009{
Steve French388e57b2008-09-16 23:50:58 +00001010 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001011 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001012 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001013 FILE_BASIC_INFO info_buf;
1014
Steve French1adcb712009-02-25 14:19:56 +00001015 if (attrs == NULL)
1016 return -EINVAL;
1017
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001018 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1019 if (!server->ops->set_file_info)
1020 return -ENOSYS;
1021
Steve French388e57b2008-09-16 23:50:58 +00001022 if (attrs->ia_valid & ATTR_ATIME) {
1023 set_time = true;
1024 info_buf.LastAccessTime =
1025 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1026 } else
1027 info_buf.LastAccessTime = 0;
1028
1029 if (attrs->ia_valid & ATTR_MTIME) {
1030 set_time = true;
1031 info_buf.LastWriteTime =
1032 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1033 } else
1034 info_buf.LastWriteTime = 0;
1035
1036 /*
1037 * Samba throws this field away, but windows may actually use it.
1038 * Do not set ctime unless other time stamps are changed explicitly
1039 * (i.e. by utimes()) since we would then have a mix of client and
1040 * server times.
1041 */
1042 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001043 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001044 info_buf.ChangeTime =
1045 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1046 } else
1047 info_buf.ChangeTime = 0;
1048
1049 info_buf.CreationTime = 0; /* don't change */
1050 info_buf.Attributes = cpu_to_le32(dosattr);
1051
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001052 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001053}
1054
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001055/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001056 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001057 * and rename it to a random name that hopefully won't conflict with
1058 * anything else.
1059 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001060int
1061cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1062 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001063{
1064 int oplock = 0;
1065 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001066 struct cifs_fid fid;
1067 struct cifs_open_parms oparms;
Steve French32709582008-10-20 00:44:19 +00001068 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001069 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1070 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001071 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001072 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001073 __u32 dosattr, origattr;
1074 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001075
Jeff Layton7ffec372010-09-29 19:51:11 -04001076 tlink = cifs_sb_tlink(cifs_sb);
1077 if (IS_ERR(tlink))
1078 return PTR_ERR(tlink);
1079 tcon = tlink_tcon(tlink);
1080
Sachin Prabhuc483a982013-03-05 19:25:56 +00001081 /*
1082 * We cannot rename the file if the server doesn't support
1083 * CAP_INFOLEVEL_PASSTHRU
1084 */
1085 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1086 rc = -EBUSY;
1087 goto out;
1088 }
1089
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001090 oparms.tcon = tcon;
1091 oparms.cifs_sb = cifs_sb;
1092 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1093 oparms.create_options = CREATE_NOT_DIR;
1094 oparms.disposition = FILE_OPEN;
1095 oparms.path = full_path;
1096 oparms.fid = &fid;
1097 oparms.reconnect = false;
1098
1099 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001100 if (rc != 0)
1101 goto out;
1102
Steve French32709582008-10-20 00:44:19 +00001103 origattr = cifsInode->cifsAttrs;
1104 if (origattr == 0)
1105 origattr |= ATTR_NORMAL;
1106
1107 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001108 if (dosattr == 0)
1109 dosattr |= ATTR_NORMAL;
1110 dosattr |= ATTR_HIDDEN;
1111
Steve French32709582008-10-20 00:44:19 +00001112 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1113 if (dosattr != origattr) {
1114 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1115 if (info_buf == NULL) {
1116 rc = -ENOMEM;
1117 goto out_close;
1118 }
1119 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001120 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001121 current->tgid);
1122 /* although we would like to mark the file hidden
1123 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001124 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001125 cifsInode->cifsAttrs = dosattr;
1126 else
1127 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001128 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001129
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001130 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001131 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1132 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001133 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001134 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001135 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001136 goto undo_setattr;
1137 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001138
Steve French32709582008-10-20 00:44:19 +00001139 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001140 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001141 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001142 current->tgid);
1143 /*
1144 * some samba versions return -ENOENT when we try to set the
1145 * file disposition here. Likely a samba bug, but work around
1146 * it for now. This means that some cifsXXX files may hang
1147 * around after they shouldn't.
1148 *
1149 * BB: remove this hack after more servers have the fix
1150 */
1151 if (rc == -ENOENT)
1152 rc = 0;
1153 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001154 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001155 goto undo_rename;
1156 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001157 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001158 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001159
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001160out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001161 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001162out:
Steve French32709582008-10-20 00:44:19 +00001163 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001164 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001165 return rc;
Steve French32709582008-10-20 00:44:19 +00001166
1167 /*
1168 * reset everything back to the original state. Don't bother
1169 * dealing with errors here since we can't do anything about
1170 * them anyway.
1171 */
1172undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001173 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001174 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001175undo_setattr:
1176 if (dosattr != origattr) {
1177 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001178 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001179 current->tgid))
1180 cifsInode->cifsAttrs = origattr;
1181 }
1182
1183 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001184}
1185
Steve Frenchb7ca6922012-08-03 08:43:01 -05001186/* copied from fs/nfs/dir.c with small changes */
1187static void
1188cifs_drop_nlink(struct inode *inode)
1189{
1190 spin_lock(&inode->i_lock);
1191 if (inode->i_nlink > 0)
1192 drop_nlink(inode);
1193 spin_unlock(&inode->i_lock);
1194}
Steve Frenchff694522009-04-20 19:45:13 +00001195
1196/*
1197 * If dentry->d_inode is null (usually meaning the cached dentry
1198 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001199 * if that fails we can not attempt the fall back mechanisms on EACCESS
1200 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001201 * unlink on negative dentries currently.
1202 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001203int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204{
1205 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001206 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001208 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001209 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001210 struct super_block *sb = dir->i_sb;
1211 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001212 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001213 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001214 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001215 struct iattr *attrs = NULL;
1216 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
Joe Perchesf96637b2013-05-04 22:12:25 -05001218 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
Jeff Layton7ffec372010-09-29 19:51:11 -04001220 tlink = cifs_sb_tlink(cifs_sb);
1221 if (IS_ERR(tlink))
1222 return PTR_ERR(tlink);
1223 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001224 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001225
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001226 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Jeff Layton5f0319a2008-09-16 14:05:16 -04001228 /* Unlink can be called from rename so we can not take the
1229 * sb->s_vfs_rename_mutex here */
1230 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301232 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001233 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 }
Steve French2d785a52007-07-15 01:48:57 +00001235
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001236 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1237 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001238 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001239 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001240 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001241 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001242 if ((rc == 0) || (rc == -ENOENT))
1243 goto psx_del_no_retry;
1244 }
1245
Steve French60502472008-10-07 18:42:52 +00001246retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001247 if (!server->ops->unlink) {
1248 rc = -ENOSYS;
1249 goto psx_del_no_retry;
1250 }
1251
1252 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001253
Steve French2d785a52007-07-15 01:48:57 +00001254psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001256 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001257 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001259 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001260 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001261 if (server->ops->rename_pending_delete) {
1262 rc = server->ops->rename_pending_delete(full_path,
1263 dentry, xid);
1264 if (rc == 0)
1265 cifs_drop_nlink(inode);
1266 }
Steve Frenchff694522009-04-20 19:45:13 +00001267 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001268 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1269 if (attrs == NULL) {
1270 rc = -ENOMEM;
1271 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 }
Steve French388e57b2008-09-16 23:50:58 +00001273
1274 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001275 cifs_inode = CIFS_I(inode);
1276 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001277 if (origattr == 0)
1278 origattr |= ATTR_NORMAL;
1279 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001280 if (dosattr == 0)
1281 dosattr |= ATTR_NORMAL;
1282 dosattr |= ATTR_HIDDEN;
1283
1284 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001285 if (rc != 0)
1286 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001287
1288 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 }
Steve French60502472008-10-07 18:42:52 +00001290
1291 /* undo the setattr if we errored out and it's needed */
1292 if (rc != 0 && dosattr != 0)
1293 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1294
Steve French388e57b2008-09-16 23:50:58 +00001295out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001296 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001297 cifs_inode = CIFS_I(inode);
1298 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001299 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001300 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001301 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001302 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001303 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001304 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001305unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001307 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001308 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001309 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 return rc;
1311}
1312
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001313static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001314cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001315 const char *full_path, struct cifs_sb_info *cifs_sb,
1316 struct cifs_tcon *tcon, const unsigned int xid)
1317{
1318 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001319 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001320
1321 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001322 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001323 xid);
1324 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001325 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1326 xid, NULL);
1327
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001328 if (rc)
1329 return rc;
1330
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001331 /*
1332 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001333 * from the server or was set bogus. Also, since this is a brand new
1334 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001335 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001336 if (inode->i_nlink < 2)
1337 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001338 mode &= ~current_umask();
1339 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001340 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001341 mode |= S_ISGID;
1342
1343 if (tcon->unix_ext) {
1344 struct cifs_unix_set_info_args args = {
1345 .mode = mode,
1346 .ctime = NO_CHANGE_64,
1347 .atime = NO_CHANGE_64,
1348 .mtime = NO_CHANGE_64,
1349 .device = 0,
1350 };
1351 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001352 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001353 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001354 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001355 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001356 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001357 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001358 args.uid = INVALID_UID; /* no change */
1359 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001360 }
1361 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1362 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001363 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001364 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001365 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001366 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001367 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001368 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001369 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001370 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1371 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001372
Jeff Layton101b92d2012-09-19 06:22:45 -07001373 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1374 inode->i_uid = current_fsuid();
1375 if (inode->i_mode & S_ISGID)
1376 inode->i_gid = parent->i_gid;
1377 else
1378 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001379 }
1380 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001381 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001382 return rc;
1383}
1384
1385static int
1386cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1387 const char *full_path, struct cifs_sb_info *cifs_sb,
1388 struct cifs_tcon *tcon, const unsigned int xid)
1389{
1390 int rc = 0;
1391 u32 oplock = 0;
1392 FILE_UNIX_BASIC_INFO *info = NULL;
1393 struct inode *newinode = NULL;
1394 struct cifs_fattr fattr;
1395
1396 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1397 if (info == NULL) {
1398 rc = -ENOMEM;
1399 goto posix_mkdir_out;
1400 }
1401
1402 mode &= ~current_umask();
1403 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1404 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001405 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001406 if (rc == -EOPNOTSUPP)
1407 goto posix_mkdir_out;
1408 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001409 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001410 d_drop(dentry);
1411 goto posix_mkdir_out;
1412 }
1413
1414 if (info->Type == cpu_to_le32(-1))
1415 /* no return info, go query for it */
1416 goto posix_mkdir_get_info;
1417 /*
1418 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1419 * need to set uid/gid.
1420 */
1421
1422 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1423 cifs_fill_uniqueid(inode->i_sb, &fattr);
1424 newinode = cifs_iget(inode->i_sb, &fattr);
1425 if (!newinode)
1426 goto posix_mkdir_get_info;
1427
1428 d_instantiate(dentry, newinode);
1429
1430#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001431 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1432 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001433
1434 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001435 cifs_dbg(FYI, "unexpected number of links %d\n",
1436 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001437#endif
1438
1439posix_mkdir_out:
1440 kfree(info);
1441 return rc;
1442posix_mkdir_get_info:
1443 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1444 xid);
1445 goto posix_mkdir_out;
1446}
1447
Al Viro18bb1db2011-07-26 01:41:39 -04001448int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001450 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001451 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001453 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001454 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001455 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001456 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
Joe Perchesf96637b2013-05-04 22:12:25 -05001458 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1459 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001462 tlink = cifs_sb_tlink(cifs_sb);
1463 if (IS_ERR(tlink))
1464 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001465 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001466
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001467 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Steve French7f573562005-08-30 11:32:14 -07001469 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301471 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001472 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 }
Steve French50c2f752007-07-13 00:33:32 +00001474
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001475 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1476 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001477 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1478 tcon, xid);
1479 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001480 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001481 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001482
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001483 server = tcon->ses->server;
1484
1485 if (!server->ops->mkdir) {
1486 rc = -ENOSYS;
1487 goto mkdir_out;
1488 }
1489
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001491 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001493 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001495 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001497
1498 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1499 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001500mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001501 /*
1502 * Force revalidate to get parent dir info when needed since cached
1503 * attributes are invalid now.
1504 */
1505 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001507 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001508 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 return rc;
1510}
1511
1512int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1513{
1514 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001515 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001517 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001518 struct cifs_tcon *tcon;
1519 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 char *full_path = NULL;
1521 struct cifsInodeInfo *cifsInode;
1522
Joe Perchesf96637b2013-05-04 22:12:25 -05001523 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001525 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
Steve French7f573562005-08-30 11:32:14 -07001527 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301529 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001530 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 }
1532
Jeff Layton7ffec372010-09-29 19:51:11 -04001533 cifs_sb = CIFS_SB(inode->i_sb);
1534 tlink = cifs_sb_tlink(cifs_sb);
1535 if (IS_ERR(tlink)) {
1536 rc = PTR_ERR(tlink);
1537 goto rmdir_exit;
1538 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001539 tcon = tlink_tcon(tlink);
1540 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001541
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001542 if (!server->ops->rmdir) {
1543 rc = -ENOSYS;
1544 cifs_put_tlink(tlink);
1545 goto rmdir_exit;
1546 }
1547
1548 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001549 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
1551 if (!rc) {
Steve French3677db12007-02-26 16:46:11 +00001552 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001553 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001554 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001555 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 }
1557
1558 cifsInode = CIFS_I(direntry->d_inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001559 /* force revalidate to go get info when needed */
1560 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001561
1562 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001563 /*
1564 * Force revalidate to get parent dir info when needed since cached
1565 * attributes are invalid now.
1566 */
1567 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001568
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1570 current_fs_time(inode->i_sb);
1571
Jeff Layton7ffec372010-09-29 19:51:11 -04001572rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001574 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 return rc;
1576}
1577
Steve Frenchee2fd962008-09-23 18:23:33 +00001578static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001579cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1580 const char *from_path, struct dentry *to_dentry,
1581 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001582{
1583 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001584 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001585 struct cifs_tcon *tcon;
1586 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001587 struct cifs_fid fid;
1588 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001589 int oplock, rc;
1590
Jeff Layton7ffec372010-09-29 19:51:11 -04001591 tlink = cifs_sb_tlink(cifs_sb);
1592 if (IS_ERR(tlink))
1593 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001594 tcon = tlink_tcon(tlink);
1595 server = tcon->ses->server;
1596
1597 if (!server->ops->rename)
1598 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001599
Steve Frenchee2fd962008-09-23 18:23:33 +00001600 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001601 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001602
1603 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001604 * Don't bother with rename by filehandle unless file is busy and
1605 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001606 * rename by filehandle to various Windows servers.
1607 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001608 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001609 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001610
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001611 /* open-file renames don't work across directories */
1612 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001613 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001614
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001615 oparms.tcon = tcon;
1616 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00001617 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001618 oparms.desired_access = DELETE;
1619 oparms.create_options = CREATE_NOT_DIR;
1620 oparms.disposition = FILE_OPEN;
1621 oparms.path = from_path;
1622 oparms.fid = &fid;
1623 oparms.reconnect = false;
1624
1625 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00001626 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001627 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001628 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001629 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001630 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001631 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001632do_rename_exit:
1633 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001634 return rc;
1635}
1636
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001637int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001638cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
1639 struct inode *target_dir, struct dentry *target_dentry,
1640 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001642 char *from_name = NULL;
1643 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001644 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001645 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001646 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001647 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1648 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001649 unsigned int xid;
1650 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001652 if (flags & ~RENAME_NOREPLACE)
1653 return -EINVAL;
1654
Jeff Layton639e7a92010-09-03 11:50:09 -04001655 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001656 tlink = cifs_sb_tlink(cifs_sb);
1657 if (IS_ERR(tlink))
1658 return PTR_ERR(tlink);
1659 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001661 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001662
1663 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001664 * we already have the rename sem so we do not need to
1665 * grab it again here to protect the path integrity
1666 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001667 from_name = build_path_from_dentry(source_dentry);
1668 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 rc = -ENOMEM;
1670 goto cifs_rename_exit;
1671 }
1672
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001673 to_name = build_path_from_dentry(target_dentry);
1674 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001675 rc = -ENOMEM;
1676 goto cifs_rename_exit;
1677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001679 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1680 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001681
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001682 /*
1683 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
1684 */
1685 if (flags & RENAME_NOREPLACE)
1686 goto cifs_rename_exit;
1687
Jeff Layton14121bd2008-10-20 14:45:22 -04001688 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001689 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001690 * Are src and dst hardlinks of same inode? We can only tell
1691 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001692 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001693 info_buf_source =
1694 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1695 GFP_KERNEL);
1696 if (info_buf_source == NULL) {
1697 rc = -ENOMEM;
1698 goto cifs_rename_exit;
1699 }
1700
1701 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001702 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1703 info_buf_source,
1704 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001705 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04001706 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001707 goto unlink_target;
1708
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001709 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1710 info_buf_target,
1711 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001712 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04001713
Jeff Layton8d281ef2008-10-22 13:57:01 -04001714 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001715 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001716 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001717 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001718 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001719 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001720 }
1721 /*
1722 * else ... BB we could add the same check for Windows by
1723 * checking the UniqueId via FILE_INTERNAL_INFO
1724 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001725
Jeff Layton14121bd2008-10-20 14:45:22 -04001726unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001727 /* Try unlinking the target dentry if it's not negative */
1728 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04001729 if (d_is_dir(target_dentry))
1730 tmprc = cifs_rmdir(target_dir, target_dentry);
1731 else
1732 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001733 if (tmprc)
1734 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001735 rc = cifs_do_rename(xid, source_dentry, from_name,
1736 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 }
1738
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001739 /* force revalidate to go get info when needed */
1740 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1741
1742 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
1743 target_dir->i_mtime = current_fs_time(source_dir->i_sb);
1744
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001746 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001747 kfree(from_name);
1748 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001749 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001750 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 return rc;
1752}
1753
Jeff Laytondf2cf172010-02-12 07:44:16 -05001754static bool
1755cifs_inode_needs_reval(struct inode *inode)
1756{
1757 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301758 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001759
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001760 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001761 return false;
1762
1763 if (!lookupCacheEnabled)
1764 return true;
1765
1766 if (cifs_i->time == 0)
1767 return true;
1768
Jeff Laytona87c9ad2014-03-26 07:24:23 -07001769 if (!cifs_sb->actimeo)
1770 return true;
1771
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301772 if (!time_in_range(jiffies, cifs_i->time,
1773 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001774 return true;
1775
Jeff Laytondb192722010-05-17 14:51:49 -04001776 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301777 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001778 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1779 return true;
1780
Jeff Laytondf2cf172010-02-12 07:44:16 -05001781 return false;
1782}
1783
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301784/*
1785 * Zap the cache. Called when invalid_mapping flag is set.
1786 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001787int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001788cifs_invalidate_mapping(struct inode *inode)
1789{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001790 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001791
Jeff Laytondf2cf172010-02-12 07:44:16 -05001792 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001793 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001794 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001795 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1796 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001797 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001798
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301799 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001800 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001801}
1802
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001803/**
1804 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
1805 * @word: long word containing the bit lock
1806 */
1807static int
NeilBrownc1221322014-07-07 15:16:04 +10001808cifs_wait_bit_killable(struct wait_bit_key *key)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001809{
1810 if (fatal_signal_pending(current))
1811 return -ERESTARTSYS;
1812 freezable_schedule_unsafe();
1813 return 0;
1814}
1815
Jeff Laytone284e532014-04-30 09:31:46 -04001816int
1817cifs_revalidate_mapping(struct inode *inode)
1818{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001819 int rc;
1820 unsigned long *flags = &CIFS_I(inode)->flags;
1821
NeilBrown74316202014-07-07 15:16:04 +10001822 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
1823 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001824 if (rc)
1825 return rc;
1826
1827 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
1828 rc = cifs_invalidate_mapping(inode);
1829 if (rc)
1830 set_bit(CIFS_INO_INVALID_MAPPING, flags);
1831 }
1832
1833 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07001834 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001835 wake_up_bit(flags, CIFS_INO_LOCK);
1836
1837 return rc;
1838}
1839
1840int
1841cifs_zap_mapping(struct inode *inode)
1842{
1843 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
1844 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04001845}
1846
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001847int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001848{
1849 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001850 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001851 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001852
1853 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001854 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001855
Jeff Layton13cfb732010-09-29 19:51:11 -04001856 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001857 rc = cifs_get_file_info_unix(filp);
1858 else
1859 rc = cifs_get_file_info(filp);
1860
Jeff Laytonabab0952010-02-12 07:44:18 -05001861 return rc;
1862}
1863
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001864int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001866 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001867 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001868 struct inode *inode = dentry->d_inode;
1869 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001870 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Jeff Laytondf2cf172010-02-12 07:44:16 -05001872 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 return -ENOENT;
1874
Jeff Laytondf2cf172010-02-12 07:44:16 -05001875 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001876 return rc;
1877
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001878 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879
1880 /* can not safely grab the rename sem here if rename calls revalidate
1881 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001882 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301884 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001885 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001887
Joe Perchesf96637b2013-05-04 22:12:25 -05001888 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1889 full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001890 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891
Jeff Layton0d424ad2010-09-20 16:01:35 -07001892 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001893 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1894 else
1895 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1896 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001898out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001900 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 return rc;
1902}
1903
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001904int cifs_revalidate_file(struct file *filp)
1905{
1906 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001907 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001908
1909 rc = cifs_revalidate_file_attr(filp);
1910 if (rc)
1911 return rc;
1912
Jeff Laytone284e532014-04-30 09:31:46 -04001913 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001914}
1915
1916/* revalidate a dentry's inode attributes */
1917int cifs_revalidate_dentry(struct dentry *dentry)
1918{
1919 int rc;
1920 struct inode *inode = dentry->d_inode;
1921
1922 rc = cifs_revalidate_dentry_attr(dentry);
1923 if (rc)
1924 return rc;
1925
Jeff Laytone284e532014-04-30 09:31:46 -04001926 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001927}
1928
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001930 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001932 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001933 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001934 struct inode *inode = dentry->d_inode;
1935 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001936
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001937 /*
1938 * We need to be sure that all dirty pages are written and the server
1939 * has actual ctime, mtime and file length.
1940 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001941 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001942 inode->i_mapping->nrpages != 0) {
1943 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001944 if (rc) {
1945 mapping_set_error(inode->i_mapping, rc);
1946 return rc;
1947 }
Steve French5fe14c82006-11-07 19:26:33 +00001948 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001949
1950 rc = cifs_revalidate_dentry_attr(dentry);
1951 if (rc)
1952 return rc;
1953
1954 generic_fillattr(inode, stat);
1955 stat->blksize = CIFS_MAX_MSGSIZE;
1956 stat->ino = CIFS_I(inode)->uniqueid;
1957
1958 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001959 * If on a multiuser mount without unix extensions or cifsacl being
1960 * enabled, and the admin hasn't overridden them, set the ownership
1961 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001962 */
1963 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001964 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001965 !tcon->unix_ext) {
1966 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1967 stat->uid = current_fsuid();
1968 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1969 stat->gid = current_fsgid();
1970 }
1971 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972}
1973
1974static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1975{
1976 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1977 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1978 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 int rc = 0;
1980
1981 page = grab_cache_page(mapping, index);
1982 if (!page)
1983 return -ENOMEM;
1984
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001985 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 unlock_page(page);
1987 page_cache_release(page);
1988 return rc;
1989}
1990
Christoph Hellwig1b947462010-07-18 17:51:21 -04001991static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001992{
Steve Frenchba6a46a2007-02-26 20:06:29 +00001993 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00001994 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001995 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001996
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001997 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00001998}
1999
Jeff Layton8efdbde2008-07-23 21:28:12 +00002000static int
2001cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002002 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00002003{
2004 int rc;
2005 struct cifsFileInfo *open_file;
2006 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2007 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002008 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002009 struct cifs_tcon *tcon = NULL;
2010 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04002011 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002012
2013 /*
2014 * To avoid spurious oplock breaks from server, in the case of
2015 * inodes that we already have open, avoid doing path based
2016 * setting of file size if we can do it by handle.
2017 * This keeps our caching token (oplock) and avoids timeouts
2018 * when the local oplock break takes longer to flush
2019 * writebehind data than the SMB timeout for the SetPathInfo
2020 * request would allow
2021 */
Jeff Layton6508d902010-09-29 19:51:11 -04002022 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002023 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002024 tcon = tlink_tcon(open_file->tlink);
2025 server = tcon->ses->server;
2026 if (server->ops->set_file_size)
2027 rc = server->ops->set_file_size(xid, tcon, open_file,
2028 attrs->ia_size, false);
2029 else
2030 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002031 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002032 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002033 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
2034 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04002035
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002036 io_parms.netfid = open_file->fid.netfid;
2037 io_parms.pid = open_file->pid;
2038 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04002039 io_parms.offset = 0;
2040 io_parms.length = attrs->ia_size;
2041 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
2042 NULL, NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05002043 cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002044 }
2045 } else
2046 rc = -EINVAL;
2047
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002048 if (!rc)
2049 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07002050
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002051 if (tcon == NULL) {
2052 tlink = cifs_sb_tlink(cifs_sb);
2053 if (IS_ERR(tlink))
2054 return PTR_ERR(tlink);
2055 tcon = tlink_tcon(tlink);
2056 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002057 }
2058
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002059 /*
2060 * Set file size by pathname rather than by handle either because no
2061 * valid, writeable file handle for it was found or because there was
2062 * an error setting it by handle.
2063 */
2064 if (server->ops->set_path_size)
2065 rc = server->ops->set_path_size(xid, tcon, full_path,
2066 attrs->ia_size, cifs_sb, false);
2067 else
2068 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002069 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002070 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
2071 __u16 netfid;
2072 int oplock = 0;
2073
2074 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
2075 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
2076 &oplock, NULL, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002077 cifs_remap(cifs_sb));
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002078 if (rc == 0) {
2079 unsigned int bytes_written;
2080
2081 io_parms.netfid = netfid;
2082 io_parms.pid = current->tgid;
2083 io_parms.tcon = tcon;
2084 io_parms.offset = 0;
2085 io_parms.length = attrs->ia_size;
2086 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
2087 NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05002088 cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002089 CIFSSMBClose(xid, tcon, netfid);
2090 }
2091 }
2092 if (tlink)
2093 cifs_put_tlink(tlink);
2094
2095set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002096 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002097 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002098 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002099 cifs_truncate_page(inode->i_mapping, inode->i_size);
2100 }
2101
2102 return rc;
2103}
2104
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002105static int
2106cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2107{
2108 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002109 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002110 char *full_path = NULL;
2111 struct inode *inode = direntry->d_inode;
2112 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2113 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002114 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002115 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002116 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002117 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002118
Al Viro35c265e2014-08-19 20:25:34 -04002119 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2120 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002121
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002122 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002123
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002124 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2125 attrs->ia_valid |= ATTR_FORCE;
2126
2127 rc = inode_change_ok(inode, attrs);
2128 if (rc < 0)
2129 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002130
2131 full_path = build_path_from_dentry(direntry);
2132 if (full_path == NULL) {
2133 rc = -ENOMEM;
2134 goto out;
2135 }
2136
Jeff Layton0f4d6342009-03-26 13:35:37 -04002137 /*
2138 * Attempt to flush data before changing attributes. We need to do
2139 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2140 * ownership or mode then we may also need to do this. Here, we take
2141 * the safe way out and just do the flush on all setattr requests. If
2142 * the flush returns error, store it to report later and continue.
2143 *
2144 * BB: This should be smarter. Why bother flushing pages that
2145 * will be truncated anyway? Also, should we error out here if
2146 * the flush returns error?
2147 */
2148 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002149 mapping_set_error(inode->i_mapping, rc);
2150 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002151
2152 if (attrs->ia_valid & ATTR_SIZE) {
2153 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2154 if (rc != 0)
2155 goto out;
2156 }
2157
2158 /* skip mode change if it's just for clearing setuid/setgid */
2159 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2160 attrs->ia_valid &= ~ATTR_MODE;
2161
2162 args = kmalloc(sizeof(*args), GFP_KERNEL);
2163 if (args == NULL) {
2164 rc = -ENOMEM;
2165 goto out;
2166 }
2167
2168 /* set up the struct */
2169 if (attrs->ia_valid & ATTR_MODE)
2170 args->mode = attrs->ia_mode;
2171 else
2172 args->mode = NO_CHANGE_64;
2173
2174 if (attrs->ia_valid & ATTR_UID)
2175 args->uid = attrs->ia_uid;
2176 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002177 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002178
2179 if (attrs->ia_valid & ATTR_GID)
2180 args->gid = attrs->ia_gid;
2181 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002182 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002183
2184 if (attrs->ia_valid & ATTR_ATIME)
2185 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2186 else
2187 args->atime = NO_CHANGE_64;
2188
2189 if (attrs->ia_valid & ATTR_MTIME)
2190 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2191 else
2192 args->mtime = NO_CHANGE_64;
2193
2194 if (attrs->ia_valid & ATTR_CTIME)
2195 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2196 else
2197 args->ctime = NO_CHANGE_64;
2198
2199 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002200 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002201 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002202 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002203 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002204 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002205 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002206 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002207 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002208 tlink = cifs_sb_tlink(cifs_sb);
2209 if (IS_ERR(tlink)) {
2210 rc = PTR_ERR(tlink);
2211 goto out;
2212 }
2213 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002214 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002215 cifs_sb->local_nls,
2216 cifs_sb->mnt_cifs_flags &
2217 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002218 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002219 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002220
Christoph Hellwig10257742010-06-04 11:30:02 +02002221 if (rc)
2222 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002223
Christoph Hellwig10257742010-06-04 11:30:02 +02002224 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002225 attrs->ia_size != i_size_read(inode))
2226 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002227
2228 setattr_copy(inode, attrs);
2229 mark_inode_dirty(inode);
2230
2231 /* force revalidate when any of these times are set since some
2232 of the fs types (eg ext3, fat) do not have fine enough
2233 time granularity to match protocol, and we do not have a
2234 a way (yet) to query the server fs's time granularity (and
2235 whether it rounds times down).
2236 */
2237 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2238 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002239out:
2240 kfree(args);
2241 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002242 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002243 return rc;
2244}
2245
Jeff Layton0510eeb2008-08-02 07:26:12 -04002246static int
2247cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002249 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002250 kuid_t uid = INVALID_UID;
2251 kgid_t gid = INVALID_GID;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002252 struct inode *inode = direntry->d_inode;
2253 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002254 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 char *full_path = NULL;
2256 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002257 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002258 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002259
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002260 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261
Al Viro35c265e2014-08-19 20:25:34 -04002262 cifs_dbg(FYI, "setattr on file %pd attrs->iavalid 0x%x\n",
2263 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002264
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002265 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2266 attrs->ia_valid |= ATTR_FORCE;
2267
2268 rc = inode_change_ok(inode, attrs);
2269 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002270 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002271 return rc;
Steve French6473a552005-11-29 20:20:10 -08002272 }
Steve French50c2f752007-07-13 00:33:32 +00002273
Steve French7f573562005-08-30 11:32:14 -07002274 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302276 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002277 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302278 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280
Jeff Layton0f4d6342009-03-26 13:35:37 -04002281 /*
2282 * Attempt to flush data before changing attributes. We need to do
2283 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2284 * ownership or mode then we may also need to do this. Here, we take
2285 * the safe way out and just do the flush on all setattr requests. If
2286 * the flush returns error, store it to report later and continue.
2287 *
2288 * BB: This should be smarter. Why bother flushing pages that
2289 * will be truncated anyway? Also, should we error out here if
2290 * the flush returns error?
2291 */
2292 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002293 mapping_set_error(inode->i_mapping, rc);
2294 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002295
Steve French50531442008-03-14 19:21:31 +00002296 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002297 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2298 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002299 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002301
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002302 if (attrs->ia_valid & ATTR_UID)
2303 uid = attrs->ia_uid;
2304
2305 if (attrs->ia_valid & ATTR_GID)
2306 gid = attrs->ia_gid;
2307
2308#ifdef CONFIG_CIFS_ACL
2309 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002310 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002311 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2312 uid, gid);
2313 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002314 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2315 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002316 goto cifs_setattr_exit;
2317 }
2318 }
2319 } else
2320#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002321 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002322 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323
Jeff Laytond32c4f22007-10-18 03:05:22 -07002324 /* skip mode change if it's just for clearing setuid/setgid */
2325 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2326 attrs->ia_valid &= ~ATTR_MODE;
2327
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002330 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002331#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002332 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002333 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002334 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002335 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002336 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2337 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002338 goto cifs_setattr_exit;
2339 }
2340 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002341#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002342 if (((mode & S_IWUGO) == 0) &&
2343 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002344
2345 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2346
Jeff Layton51328612008-05-22 09:33:34 -04002347 /* fix up mode if we're not using dynperm */
2348 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2349 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2350 } else if ((mode & S_IWUGO) &&
2351 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002352
2353 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2354 /* Attributes of 0 are ignored */
2355 if (dosattr == 0)
2356 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002357
2358 /* reset local inode permissions to normal */
2359 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2360 attrs->ia_mode &= ~(S_IALLUGO);
2361 if (S_ISDIR(inode->i_mode))
2362 attrs->ia_mode |=
2363 cifs_sb->mnt_dir_mode;
2364 else
2365 attrs->ia_mode |=
2366 cifs_sb->mnt_file_mode;
2367 }
2368 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2369 /* ignore mode change - ATTR_READONLY hasn't changed */
2370 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 }
2373
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002374 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2375 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2376 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2377 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Steve Frenche30dcf32005-09-20 20:49:16 -07002379 /* Even if error on time set, no sense failing the call if
2380 the server would set the time to a reasonable value anyway,
2381 and this check ensures that we are not being called from
2382 sys_utimes in which case we ought to fail the call back to
2383 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002384 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002385 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002386 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 }
2388
2389 /* do not need local check to inode_check_ok since the server does
2390 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002391 if (rc)
2392 goto cifs_setattr_exit;
2393
2394 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002395 attrs->ia_size != i_size_read(inode))
2396 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002397
2398 setattr_copy(inode, attrs);
2399 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002400
Steve Frenche30dcf32005-09-20 20:49:16 -07002401cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002403 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 return rc;
2405}
2406
Jeff Layton0510eeb2008-08-02 07:26:12 -04002407int
2408cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2409{
2410 struct inode *inode = direntry->d_inode;
2411 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002412 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002413
2414 if (pTcon->unix_ext)
2415 return cifs_setattr_unix(direntry, attrs);
2416
2417 return cifs_setattr_nounix(direntry, attrs);
2418
2419 /* BB: add cifs_setattr_legacy for really old servers */
2420}
2421
Steve French99ee4db2007-02-27 05:35:17 +00002422#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423void cifs_delete_inode(struct inode *inode)
2424{
Joe Perchesf96637b2013-05-04 22:12:25 -05002425 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 /* may have to add back in if and when safe distributed caching of
2427 directories added e.g. via FindNotify */
2428}
Steve French99ee4db2007-02-27 05:35:17 +00002429#endif