blob: c23bdec805c557748d3f205704638bd889c2afa7 [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);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800898 hlist_for_each_entry(dentry, &inode->i_dentry, 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;
Jeff Layton522440e2010-09-29 09:49:54 -0400940 if (S_ISREG(inode->i_mode))
941 inode->i_data.backing_dev_info = sb->s_bdi;
Steve French0ccd4802010-07-16 04:31:02 +0000942#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530943 /* initialize per-inode cache cookie pointer */
944 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000945#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400946 unlock_new_inode(inode);
947 }
948 }
949
950 return inode;
951}
952
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600954struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400956 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700957 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400958 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800959 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000960 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800961
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400962 xid = get_xid();
Jeff Layton0d424ad2010-09-20 16:01:35 -0700963 if (tcon->unix_ext)
Steve Frenchf87d39d2011-05-27 03:50:55 +0000964 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400965 else
Steve Frenchf87d39d2011-05-27 03:50:55 +0000966 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400967
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000968 if (!inode) {
969 inode = ERR_PTR(rc);
970 goto out;
971 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400972
Steve French0ccd4802010-07-16 04:31:02 +0000973#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530974 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700975 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000976#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530977
Jeff Layton0d424ad2010-09-20 16:01:35 -0700978 if (rc && tcon->ipc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500979 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -0500980 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +0000981 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200982 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +0000983 inode->i_op = &cifs_ipc_inode_ops;
984 inode->i_fop = &simple_dir_operations;
985 inode->i_uid = cifs_sb->mnt_uid;
986 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -0500987 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +0000988 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800989 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000990 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000991 }
992
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000993out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400994 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -0800995 * TODO: This is no longer true
996 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400997 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -0800998 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999}
1000
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001001int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001002cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001003 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +00001004{
Steve French388e57b2008-09-16 23:50:58 +00001005 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +00001006 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001007 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +00001008 FILE_BASIC_INFO info_buf;
1009
Steve French1adcb712009-02-25 14:19:56 +00001010 if (attrs == NULL)
1011 return -EINVAL;
1012
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001013 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1014 if (!server->ops->set_file_info)
1015 return -ENOSYS;
1016
Steve French388e57b2008-09-16 23:50:58 +00001017 if (attrs->ia_valid & ATTR_ATIME) {
1018 set_time = true;
1019 info_buf.LastAccessTime =
1020 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1021 } else
1022 info_buf.LastAccessTime = 0;
1023
1024 if (attrs->ia_valid & ATTR_MTIME) {
1025 set_time = true;
1026 info_buf.LastWriteTime =
1027 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1028 } else
1029 info_buf.LastWriteTime = 0;
1030
1031 /*
1032 * Samba throws this field away, but windows may actually use it.
1033 * Do not set ctime unless other time stamps are changed explicitly
1034 * (i.e. by utimes()) since we would then have a mix of client and
1035 * server times.
1036 */
1037 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001038 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001039 info_buf.ChangeTime =
1040 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1041 } else
1042 info_buf.ChangeTime = 0;
1043
1044 info_buf.CreationTime = 0; /* don't change */
1045 info_buf.Attributes = cpu_to_le32(dosattr);
1046
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001047 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001048}
1049
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001050/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001051 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001052 * and rename it to a random name that hopefully won't conflict with
1053 * anything else.
1054 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001055int
1056cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1057 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001058{
1059 int oplock = 0;
1060 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001061 struct cifs_fid fid;
1062 struct cifs_open_parms oparms;
Steve French32709582008-10-20 00:44:19 +00001063 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001064 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1065 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001066 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001067 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001068 __u32 dosattr, origattr;
1069 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001070
Jeff Layton7ffec372010-09-29 19:51:11 -04001071 tlink = cifs_sb_tlink(cifs_sb);
1072 if (IS_ERR(tlink))
1073 return PTR_ERR(tlink);
1074 tcon = tlink_tcon(tlink);
1075
Sachin Prabhuc483a982013-03-05 19:25:56 +00001076 /*
1077 * We cannot rename the file if the server doesn't support
1078 * CAP_INFOLEVEL_PASSTHRU
1079 */
1080 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1081 rc = -EBUSY;
1082 goto out;
1083 }
1084
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001085 oparms.tcon = tcon;
1086 oparms.cifs_sb = cifs_sb;
1087 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1088 oparms.create_options = CREATE_NOT_DIR;
1089 oparms.disposition = FILE_OPEN;
1090 oparms.path = full_path;
1091 oparms.fid = &fid;
1092 oparms.reconnect = false;
1093
1094 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001095 if (rc != 0)
1096 goto out;
1097
Steve French32709582008-10-20 00:44:19 +00001098 origattr = cifsInode->cifsAttrs;
1099 if (origattr == 0)
1100 origattr |= ATTR_NORMAL;
1101
1102 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001103 if (dosattr == 0)
1104 dosattr |= ATTR_NORMAL;
1105 dosattr |= ATTR_HIDDEN;
1106
Steve French32709582008-10-20 00:44:19 +00001107 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1108 if (dosattr != origattr) {
1109 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1110 if (info_buf == NULL) {
1111 rc = -ENOMEM;
1112 goto out_close;
1113 }
1114 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001115 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001116 current->tgid);
1117 /* although we would like to mark the file hidden
1118 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001119 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001120 cifsInode->cifsAttrs = dosattr;
1121 else
1122 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001123 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001124
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001125 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001126 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1127 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001128 cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001129 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001130 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001131 goto undo_setattr;
1132 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001133
Steve French32709582008-10-20 00:44:19 +00001134 /* try to set DELETE_ON_CLOSE */
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001135 if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001136 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001137 current->tgid);
1138 /*
1139 * some samba versions return -ENOENT when we try to set the
1140 * file disposition here. Likely a samba bug, but work around
1141 * it for now. This means that some cifsXXX files may hang
1142 * around after they shouldn't.
1143 *
1144 * BB: remove this hack after more servers have the fix
1145 */
1146 if (rc == -ENOENT)
1147 rc = 0;
1148 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001149 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001150 goto undo_rename;
1151 }
Jeff Laytonaff8d5c2014-04-30 09:31:45 -04001152 set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
Steve French32709582008-10-20 00:44:19 +00001153 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001154
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001155out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001156 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001157out:
Steve French32709582008-10-20 00:44:19 +00001158 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001159 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001160 return rc;
Steve French32709582008-10-20 00:44:19 +00001161
1162 /*
1163 * reset everything back to the original state. Don't bother
1164 * dealing with errors here since we can't do anything about
1165 * them anyway.
1166 */
1167undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001168 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001169 cifs_sb->local_nls, cifs_remap(cifs_sb));
Steve French32709582008-10-20 00:44:19 +00001170undo_setattr:
1171 if (dosattr != origattr) {
1172 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001173 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001174 current->tgid))
1175 cifsInode->cifsAttrs = origattr;
1176 }
1177
1178 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001179}
1180
Steve Frenchb7ca6922012-08-03 08:43:01 -05001181/* copied from fs/nfs/dir.c with small changes */
1182static void
1183cifs_drop_nlink(struct inode *inode)
1184{
1185 spin_lock(&inode->i_lock);
1186 if (inode->i_nlink > 0)
1187 drop_nlink(inode);
1188 spin_unlock(&inode->i_lock);
1189}
Steve Frenchff694522009-04-20 19:45:13 +00001190
1191/*
1192 * If dentry->d_inode is null (usually meaning the cached dentry
1193 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001194 * if that fails we can not attempt the fall back mechanisms on EACCESS
1195 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001196 * unlink on negative dentries currently.
1197 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001198int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199{
1200 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001201 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001203 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001204 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001205 struct super_block *sb = dir->i_sb;
1206 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001207 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001208 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001209 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001210 struct iattr *attrs = NULL;
1211 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
Joe Perchesf96637b2013-05-04 22:12:25 -05001213 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Jeff Layton7ffec372010-09-29 19:51:11 -04001215 tlink = cifs_sb_tlink(cifs_sb);
1216 if (IS_ERR(tlink))
1217 return PTR_ERR(tlink);
1218 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001219 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001220
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001221 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
Jeff Layton5f0319a2008-09-16 14:05:16 -04001223 /* Unlink can be called from rename so we can not take the
1224 * sb->s_vfs_rename_mutex here */
1225 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301227 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001228 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 }
Steve French2d785a52007-07-15 01:48:57 +00001230
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001231 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1232 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001233 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001234 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001235 cifs_remap(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05001236 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001237 if ((rc == 0) || (rc == -ENOENT))
1238 goto psx_del_no_retry;
1239 }
1240
Steve French60502472008-10-07 18:42:52 +00001241retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001242 if (!server->ops->unlink) {
1243 rc = -ENOSYS;
1244 goto psx_del_no_retry;
1245 }
1246
1247 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001248
Steve French2d785a52007-07-15 01:48:57 +00001249psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001251 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001252 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001254 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001255 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001256 if (server->ops->rename_pending_delete) {
1257 rc = server->ops->rename_pending_delete(full_path,
1258 dentry, xid);
1259 if (rc == 0)
1260 cifs_drop_nlink(inode);
1261 }
Steve Frenchff694522009-04-20 19:45:13 +00001262 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001263 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1264 if (attrs == NULL) {
1265 rc = -ENOMEM;
1266 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 }
Steve French388e57b2008-09-16 23:50:58 +00001268
1269 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001270 cifs_inode = CIFS_I(inode);
1271 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001272 if (origattr == 0)
1273 origattr |= ATTR_NORMAL;
1274 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001275 if (dosattr == 0)
1276 dosattr |= ATTR_NORMAL;
1277 dosattr |= ATTR_HIDDEN;
1278
1279 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001280 if (rc != 0)
1281 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001282
1283 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 }
Steve French60502472008-10-07 18:42:52 +00001285
1286 /* undo the setattr if we errored out and it's needed */
1287 if (rc != 0 && dosattr != 0)
1288 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1289
Steve French388e57b2008-09-16 23:50:58 +00001290out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001291 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001292 cifs_inode = CIFS_I(inode);
1293 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001294 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001295 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001296 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001297 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001298 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001299 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001300unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001302 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001303 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001304 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 return rc;
1306}
1307
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001308static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001309cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001310 const char *full_path, struct cifs_sb_info *cifs_sb,
1311 struct cifs_tcon *tcon, const unsigned int xid)
1312{
1313 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001314 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001315
1316 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001317 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001318 xid);
1319 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001320 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1321 xid, NULL);
1322
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001323 if (rc)
1324 return rc;
1325
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001326 /*
1327 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001328 * from the server or was set bogus. Also, since this is a brand new
1329 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001330 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001331 if (inode->i_nlink < 2)
1332 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001333 mode &= ~current_umask();
1334 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001335 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001336 mode |= S_ISGID;
1337
1338 if (tcon->unix_ext) {
1339 struct cifs_unix_set_info_args args = {
1340 .mode = mode,
1341 .ctime = NO_CHANGE_64,
1342 .atime = NO_CHANGE_64,
1343 .mtime = NO_CHANGE_64,
1344 .device = 0,
1345 };
1346 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001347 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001348 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001349 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001350 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001351 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001352 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001353 args.uid = INVALID_UID; /* no change */
1354 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001355 }
1356 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1357 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001358 cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001359 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001360 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001361 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001362 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001363 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001364 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001365 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1366 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001367
Jeff Layton101b92d2012-09-19 06:22:45 -07001368 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1369 inode->i_uid = current_fsuid();
1370 if (inode->i_mode & S_ISGID)
1371 inode->i_gid = parent->i_gid;
1372 else
1373 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001374 }
1375 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001376 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001377 return rc;
1378}
1379
1380static int
1381cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1382 const char *full_path, struct cifs_sb_info *cifs_sb,
1383 struct cifs_tcon *tcon, const unsigned int xid)
1384{
1385 int rc = 0;
1386 u32 oplock = 0;
1387 FILE_UNIX_BASIC_INFO *info = NULL;
1388 struct inode *newinode = NULL;
1389 struct cifs_fattr fattr;
1390
1391 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1392 if (info == NULL) {
1393 rc = -ENOMEM;
1394 goto posix_mkdir_out;
1395 }
1396
1397 mode &= ~current_umask();
1398 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1399 NULL /* netfid */, info, &oplock, full_path,
Steve French2baa2682014-09-27 02:19:01 -05001400 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001401 if (rc == -EOPNOTSUPP)
1402 goto posix_mkdir_out;
1403 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001404 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001405 d_drop(dentry);
1406 goto posix_mkdir_out;
1407 }
1408
1409 if (info->Type == cpu_to_le32(-1))
1410 /* no return info, go query for it */
1411 goto posix_mkdir_get_info;
1412 /*
1413 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1414 * need to set uid/gid.
1415 */
1416
1417 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1418 cifs_fill_uniqueid(inode->i_sb, &fattr);
1419 newinode = cifs_iget(inode->i_sb, &fattr);
1420 if (!newinode)
1421 goto posix_mkdir_get_info;
1422
1423 d_instantiate(dentry, newinode);
1424
1425#ifdef CONFIG_CIFS_DEBUG2
Al Viro35c265e2014-08-19 20:25:34 -04001426 cifs_dbg(FYI, "instantiated dentry %p %pd to inode %p\n",
1427 dentry, dentry, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001428
1429 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001430 cifs_dbg(FYI, "unexpected number of links %d\n",
1431 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001432#endif
1433
1434posix_mkdir_out:
1435 kfree(info);
1436 return rc;
1437posix_mkdir_get_info:
1438 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1439 xid);
1440 goto posix_mkdir_out;
1441}
1442
Al Viro18bb1db2011-07-26 01:41:39 -04001443int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001445 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001446 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001448 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001449 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001450 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001451 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
Joe Perchesf96637b2013-05-04 22:12:25 -05001453 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1454 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001457 tlink = cifs_sb_tlink(cifs_sb);
1458 if (IS_ERR(tlink))
1459 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001460 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001461
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001462 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
Steve French7f573562005-08-30 11:32:14 -07001464 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301466 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001467 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 }
Steve French50c2f752007-07-13 00:33:32 +00001469
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001470 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1471 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001472 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1473 tcon, xid);
1474 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001475 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001476 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001477
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001478 server = tcon->ses->server;
1479
1480 if (!server->ops->mkdir) {
1481 rc = -ENOSYS;
1482 goto mkdir_out;
1483 }
1484
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001486 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001488 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001490 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001492
1493 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1494 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001495mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001496 /*
1497 * Force revalidate to get parent dir info when needed since cached
1498 * attributes are invalid now.
1499 */
1500 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001502 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001503 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 return rc;
1505}
1506
1507int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1508{
1509 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001510 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001512 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001513 struct cifs_tcon *tcon;
1514 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 char *full_path = NULL;
1516 struct cifsInodeInfo *cifsInode;
1517
Joe Perchesf96637b2013-05-04 22:12:25 -05001518 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001520 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
Steve French7f573562005-08-30 11:32:14 -07001522 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301524 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001525 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 }
1527
Jeff Layton7ffec372010-09-29 19:51:11 -04001528 cifs_sb = CIFS_SB(inode->i_sb);
1529 tlink = cifs_sb_tlink(cifs_sb);
1530 if (IS_ERR(tlink)) {
1531 rc = PTR_ERR(tlink);
1532 goto rmdir_exit;
1533 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001534 tcon = tlink_tcon(tlink);
1535 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001536
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001537 if (!server->ops->rmdir) {
1538 rc = -ENOSYS;
1539 cifs_put_tlink(tlink);
1540 goto rmdir_exit;
1541 }
1542
1543 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001544 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545
1546 if (!rc) {
Steve French3677db12007-02-26 16:46:11 +00001547 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001548 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001549 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001550 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 }
1552
1553 cifsInode = CIFS_I(direntry->d_inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001554 /* force revalidate to go get info when needed */
1555 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001556
1557 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001558 /*
1559 * Force revalidate to get parent dir info when needed since cached
1560 * attributes are invalid now.
1561 */
1562 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001563
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1565 current_fs_time(inode->i_sb);
1566
Jeff Layton7ffec372010-09-29 19:51:11 -04001567rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001569 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 return rc;
1571}
1572
Steve Frenchee2fd962008-09-23 18:23:33 +00001573static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001574cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1575 const char *from_path, struct dentry *to_dentry,
1576 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001577{
1578 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001579 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001580 struct cifs_tcon *tcon;
1581 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001582 struct cifs_fid fid;
1583 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001584 int oplock, rc;
1585
Jeff Layton7ffec372010-09-29 19:51:11 -04001586 tlink = cifs_sb_tlink(cifs_sb);
1587 if (IS_ERR(tlink))
1588 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001589 tcon = tlink_tcon(tlink);
1590 server = tcon->ses->server;
1591
1592 if (!server->ops->rename)
1593 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001594
Steve Frenchee2fd962008-09-23 18:23:33 +00001595 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001596 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001597
1598 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001599 * Don't bother with rename by filehandle unless file is busy and
1600 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001601 * rename by filehandle to various Windows servers.
1602 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001603 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001604 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001605
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001606 /* open-file renames don't work across directories */
1607 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001608 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001609
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001610 oparms.tcon = tcon;
1611 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00001612 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001613 oparms.desired_access = DELETE;
1614 oparms.create_options = CREATE_NOT_DIR;
1615 oparms.disposition = FILE_OPEN;
1616 oparms.path = from_path;
1617 oparms.fid = &fid;
1618 oparms.reconnect = false;
1619
1620 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00001621 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001622 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001623 (const char *) to_dentry->d_name.name,
Steve French2baa2682014-09-27 02:19:01 -05001624 cifs_sb->local_nls, cifs_remap(cifs_sb));
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001625 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001626 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001627do_rename_exit:
1628 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001629 return rc;
1630}
1631
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001632int
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001633cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
1634 struct inode *target_dir, struct dentry *target_dentry,
1635 unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001637 char *from_name = NULL;
1638 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001639 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001640 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001641 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001642 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1643 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001644 unsigned int xid;
1645 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001647 if (flags & ~RENAME_NOREPLACE)
1648 return -EINVAL;
1649
Jeff Layton639e7a92010-09-03 11:50:09 -04001650 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001651 tlink = cifs_sb_tlink(cifs_sb);
1652 if (IS_ERR(tlink))
1653 return PTR_ERR(tlink);
1654 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001656 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001657
1658 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001659 * we already have the rename sem so we do not need to
1660 * grab it again here to protect the path integrity
1661 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001662 from_name = build_path_from_dentry(source_dentry);
1663 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 rc = -ENOMEM;
1665 goto cifs_rename_exit;
1666 }
1667
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001668 to_name = build_path_from_dentry(target_dentry);
1669 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001670 rc = -ENOMEM;
1671 goto cifs_rename_exit;
1672 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001674 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1675 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001676
Miklos Szeredi7c33d592014-07-23 15:15:36 +02001677 /*
1678 * No-replace is the natural behavior for CIFS, so skip unlink hacks.
1679 */
1680 if (flags & RENAME_NOREPLACE)
1681 goto cifs_rename_exit;
1682
Jeff Layton14121bd2008-10-20 14:45:22 -04001683 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001684 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001685 * Are src and dst hardlinks of same inode? We can only tell
1686 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001687 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001688 info_buf_source =
1689 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1690 GFP_KERNEL);
1691 if (info_buf_source == NULL) {
1692 rc = -ENOMEM;
1693 goto cifs_rename_exit;
1694 }
1695
1696 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001697 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1698 info_buf_source,
1699 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001700 cifs_remap(cifs_sb));
Jeff Layton8d281ef2008-10-22 13:57:01 -04001701 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001702 goto unlink_target;
1703
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001704 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1705 info_buf_target,
1706 cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05001707 cifs_remap(cifs_sb));
Jeff Layton14121bd2008-10-20 14:45:22 -04001708
Jeff Layton8d281ef2008-10-22 13:57:01 -04001709 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001710 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001711 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001712 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001713 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001714 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001715 }
1716 /*
1717 * else ... BB we could add the same check for Windows by
1718 * checking the UniqueId via FILE_INTERNAL_INFO
1719 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001720
Jeff Layton14121bd2008-10-20 14:45:22 -04001721unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001722 /* Try unlinking the target dentry if it's not negative */
1723 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Pavel Shilovskya07d3222014-08-22 13:32:09 +04001724 if (d_is_dir(target_dentry))
1725 tmprc = cifs_rmdir(target_dir, target_dentry);
1726 else
1727 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001728 if (tmprc)
1729 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001730 rc = cifs_do_rename(xid, source_dentry, from_name,
1731 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 }
1733
Pavel Shilovskyb46799a2014-08-18 20:49:58 +04001734 /* force revalidate to go get info when needed */
1735 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1736
1737 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
1738 target_dir->i_mtime = current_fs_time(source_dir->i_sb);
1739
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001741 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001742 kfree(from_name);
1743 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001744 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001745 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 return rc;
1747}
1748
Jeff Laytondf2cf172010-02-12 07:44:16 -05001749static bool
1750cifs_inode_needs_reval(struct inode *inode)
1751{
1752 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301753 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001754
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001755 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001756 return false;
1757
1758 if (!lookupCacheEnabled)
1759 return true;
1760
1761 if (cifs_i->time == 0)
1762 return true;
1763
Jeff Laytona87c9ad2014-03-26 07:24:23 -07001764 if (!cifs_sb->actimeo)
1765 return true;
1766
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301767 if (!time_in_range(jiffies, cifs_i->time,
1768 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001769 return true;
1770
Jeff Laytondb192722010-05-17 14:51:49 -04001771 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301772 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001773 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1774 return true;
1775
Jeff Laytondf2cf172010-02-12 07:44:16 -05001776 return false;
1777}
1778
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301779/*
1780 * Zap the cache. Called when invalid_mapping flag is set.
1781 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001782int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001783cifs_invalidate_mapping(struct inode *inode)
1784{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001785 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001786
Jeff Laytondf2cf172010-02-12 07:44:16 -05001787 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001788 rc = invalidate_inode_pages2(inode->i_mapping);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001789 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05001790 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1791 __func__, inode);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001792 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001793
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301794 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001795 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001796}
1797
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001798/**
1799 * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
1800 * @word: long word containing the bit lock
1801 */
1802static int
NeilBrownc1221322014-07-07 15:16:04 +10001803cifs_wait_bit_killable(struct wait_bit_key *key)
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001804{
1805 if (fatal_signal_pending(current))
1806 return -ERESTARTSYS;
1807 freezable_schedule_unsafe();
1808 return 0;
1809}
1810
Jeff Laytone284e532014-04-30 09:31:46 -04001811int
1812cifs_revalidate_mapping(struct inode *inode)
1813{
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001814 int rc;
1815 unsigned long *flags = &CIFS_I(inode)->flags;
1816
NeilBrown74316202014-07-07 15:16:04 +10001817 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
1818 TASK_KILLABLE);
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001819 if (rc)
1820 return rc;
1821
1822 if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
1823 rc = cifs_invalidate_mapping(inode);
1824 if (rc)
1825 set_bit(CIFS_INO_INVALID_MAPPING, flags);
1826 }
1827
1828 clear_bit_unlock(CIFS_INO_LOCK, flags);
Linus Torvaldsb1cce802014-06-09 19:08:43 -07001829 smp_mb__after_atomic();
Jeff Layton4f73c7d2014-04-30 09:31:47 -04001830 wake_up_bit(flags, CIFS_INO_LOCK);
1831
1832 return rc;
1833}
1834
1835int
1836cifs_zap_mapping(struct inode *inode)
1837{
1838 set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
1839 return cifs_revalidate_mapping(inode);
Jeff Laytone284e532014-04-30 09:31:46 -04001840}
1841
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001842int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001843{
1844 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001845 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001846 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001847
1848 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001849 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001850
Jeff Layton13cfb732010-09-29 19:51:11 -04001851 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001852 rc = cifs_get_file_info_unix(filp);
1853 else
1854 rc = cifs_get_file_info(filp);
1855
Jeff Laytonabab0952010-02-12 07:44:18 -05001856 return rc;
1857}
1858
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001859int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001861 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001862 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001863 struct inode *inode = dentry->d_inode;
1864 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001865 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Jeff Laytondf2cf172010-02-12 07:44:16 -05001867 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 return -ENOENT;
1869
Jeff Laytondf2cf172010-02-12 07:44:16 -05001870 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001871 return rc;
1872
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001873 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874
1875 /* can not safely grab the rename sem here if rename calls revalidate
1876 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001877 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301879 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001880 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001882
Joe Perchesf96637b2013-05-04 22:12:25 -05001883 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1884 full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001885 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886
Jeff Layton0d424ad2010-09-20 16:01:35 -07001887 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001888 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1889 else
1890 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1891 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001893out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001895 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 return rc;
1897}
1898
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001899int cifs_revalidate_file(struct file *filp)
1900{
1901 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001902 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001903
1904 rc = cifs_revalidate_file_attr(filp);
1905 if (rc)
1906 return rc;
1907
Jeff Laytone284e532014-04-30 09:31:46 -04001908 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001909}
1910
1911/* revalidate a dentry's inode attributes */
1912int cifs_revalidate_dentry(struct dentry *dentry)
1913{
1914 int rc;
1915 struct inode *inode = dentry->d_inode;
1916
1917 rc = cifs_revalidate_dentry_attr(dentry);
1918 if (rc)
1919 return rc;
1920
Jeff Laytone284e532014-04-30 09:31:46 -04001921 return cifs_revalidate_mapping(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001922}
1923
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001925 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001927 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001928 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001929 struct inode *inode = dentry->d_inode;
1930 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001931
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001932 /*
1933 * We need to be sure that all dirty pages are written and the server
1934 * has actual ctime, mtime and file length.
1935 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001936 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001937 inode->i_mapping->nrpages != 0) {
1938 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001939 if (rc) {
1940 mapping_set_error(inode->i_mapping, rc);
1941 return rc;
1942 }
Steve French5fe14c82006-11-07 19:26:33 +00001943 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001944
1945 rc = cifs_revalidate_dentry_attr(dentry);
1946 if (rc)
1947 return rc;
1948
1949 generic_fillattr(inode, stat);
1950 stat->blksize = CIFS_MAX_MSGSIZE;
1951 stat->ino = CIFS_I(inode)->uniqueid;
1952
1953 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001954 * If on a multiuser mount without unix extensions or cifsacl being
1955 * enabled, and the admin hasn't overridden them, set the ownership
1956 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001957 */
1958 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001959 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001960 !tcon->unix_ext) {
1961 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1962 stat->uid = current_fsuid();
1963 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1964 stat->gid = current_fsgid();
1965 }
1966 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967}
1968
1969static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1970{
1971 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1972 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1973 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 int rc = 0;
1975
1976 page = grab_cache_page(mapping, index);
1977 if (!page)
1978 return -ENOMEM;
1979
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001980 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 unlock_page(page);
1982 page_cache_release(page);
1983 return rc;
1984}
1985
Christoph Hellwig1b947462010-07-18 17:51:21 -04001986static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001987{
Steve Frenchba6a46a2007-02-26 20:06:29 +00001988 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00001989 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001990 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001991
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001992 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00001993}
1994
Jeff Layton8efdbde2008-07-23 21:28:12 +00001995static int
1996cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001997 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00001998{
1999 int rc;
2000 struct cifsFileInfo *open_file;
2001 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2002 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002003 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002004 struct cifs_tcon *tcon = NULL;
2005 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04002006 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002007
2008 /*
2009 * To avoid spurious oplock breaks from server, in the case of
2010 * inodes that we already have open, avoid doing path based
2011 * setting of file size if we can do it by handle.
2012 * This keeps our caching token (oplock) and avoids timeouts
2013 * when the local oplock break takes longer to flush
2014 * writebehind data than the SMB timeout for the SetPathInfo
2015 * request would allow
2016 */
Jeff Layton6508d902010-09-29 19:51:11 -04002017 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002018 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002019 tcon = tlink_tcon(open_file->tlink);
2020 server = tcon->ses->server;
2021 if (server->ops->set_file_size)
2022 rc = server->ops->set_file_size(xid, tcon, open_file,
2023 attrs->ia_size, false);
2024 else
2025 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002026 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05002027 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002028 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
2029 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04002030
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002031 io_parms.netfid = open_file->fid.netfid;
2032 io_parms.pid = open_file->pid;
2033 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04002034 io_parms.offset = 0;
2035 io_parms.length = attrs->ia_size;
2036 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
2037 NULL, NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05002038 cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002039 }
2040 } else
2041 rc = -EINVAL;
2042
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002043 if (!rc)
2044 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07002045
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002046 if (tcon == NULL) {
2047 tlink = cifs_sb_tlink(cifs_sb);
2048 if (IS_ERR(tlink))
2049 return PTR_ERR(tlink);
2050 tcon = tlink_tcon(tlink);
2051 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00002052 }
2053
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002054 /*
2055 * Set file size by pathname rather than by handle either because no
2056 * valid, writeable file handle for it was found or because there was
2057 * an error setting it by handle.
2058 */
2059 if (server->ops->set_path_size)
2060 rc = server->ops->set_path_size(xid, tcon, full_path,
2061 attrs->ia_size, cifs_sb, false);
2062 else
2063 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002064 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002065 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
2066 __u16 netfid;
2067 int oplock = 0;
2068
2069 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
2070 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
2071 &oplock, NULL, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05002072 cifs_remap(cifs_sb));
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002073 if (rc == 0) {
2074 unsigned int bytes_written;
2075
2076 io_parms.netfid = netfid;
2077 io_parms.pid = current->tgid;
2078 io_parms.tcon = tcon;
2079 io_parms.offset = 0;
2080 io_parms.length = attrs->ia_size;
2081 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
2082 NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05002083 cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002084 CIFSSMBClose(xid, tcon, netfid);
2085 }
2086 }
2087 if (tlink)
2088 cifs_put_tlink(tlink);
2089
2090set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002091 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002092 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002093 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002094 cifs_truncate_page(inode->i_mapping, inode->i_size);
2095 }
2096
2097 return rc;
2098}
2099
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002100static int
2101cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2102{
2103 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002104 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002105 char *full_path = NULL;
2106 struct inode *inode = direntry->d_inode;
2107 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2108 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002109 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002110 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002111 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002112 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002113
Al Viro35c265e2014-08-19 20:25:34 -04002114 cifs_dbg(FYI, "setattr_unix on file %pd attrs->ia_valid=0x%x\n",
2115 direntry, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002116
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002117 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002118
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002119 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2120 attrs->ia_valid |= ATTR_FORCE;
2121
2122 rc = inode_change_ok(inode, attrs);
2123 if (rc < 0)
2124 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002125
2126 full_path = build_path_from_dentry(direntry);
2127 if (full_path == NULL) {
2128 rc = -ENOMEM;
2129 goto out;
2130 }
2131
Jeff Layton0f4d6342009-03-26 13:35:37 -04002132 /*
2133 * Attempt to flush data before changing attributes. We need to do
2134 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2135 * ownership or mode then we may also need to do this. Here, we take
2136 * the safe way out and just do the flush on all setattr requests. If
2137 * the flush returns error, store it to report later and continue.
2138 *
2139 * BB: This should be smarter. Why bother flushing pages that
2140 * will be truncated anyway? Also, should we error out here if
2141 * the flush returns error?
2142 */
2143 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002144 mapping_set_error(inode->i_mapping, rc);
2145 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002146
2147 if (attrs->ia_valid & ATTR_SIZE) {
2148 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2149 if (rc != 0)
2150 goto out;
2151 }
2152
2153 /* skip mode change if it's just for clearing setuid/setgid */
2154 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2155 attrs->ia_valid &= ~ATTR_MODE;
2156
2157 args = kmalloc(sizeof(*args), GFP_KERNEL);
2158 if (args == NULL) {
2159 rc = -ENOMEM;
2160 goto out;
2161 }
2162
2163 /* set up the struct */
2164 if (attrs->ia_valid & ATTR_MODE)
2165 args->mode = attrs->ia_mode;
2166 else
2167 args->mode = NO_CHANGE_64;
2168
2169 if (attrs->ia_valid & ATTR_UID)
2170 args->uid = attrs->ia_uid;
2171 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002172 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002173
2174 if (attrs->ia_valid & ATTR_GID)
2175 args->gid = attrs->ia_gid;
2176 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002177 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002178
2179 if (attrs->ia_valid & ATTR_ATIME)
2180 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2181 else
2182 args->atime = NO_CHANGE_64;
2183
2184 if (attrs->ia_valid & ATTR_MTIME)
2185 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2186 else
2187 args->mtime = NO_CHANGE_64;
2188
2189 if (attrs->ia_valid & ATTR_CTIME)
2190 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2191 else
2192 args->ctime = NO_CHANGE_64;
2193
2194 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002195 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002196 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002197 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002198 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002199 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002200 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002201 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002202 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002203 tlink = cifs_sb_tlink(cifs_sb);
2204 if (IS_ERR(tlink)) {
2205 rc = PTR_ERR(tlink);
2206 goto out;
2207 }
2208 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002209 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002210 cifs_sb->local_nls,
2211 cifs_sb->mnt_cifs_flags &
2212 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002213 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002214 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002215
Christoph Hellwig10257742010-06-04 11:30:02 +02002216 if (rc)
2217 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002218
Christoph Hellwig10257742010-06-04 11:30:02 +02002219 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002220 attrs->ia_size != i_size_read(inode))
2221 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002222
2223 setattr_copy(inode, attrs);
2224 mark_inode_dirty(inode);
2225
2226 /* force revalidate when any of these times are set since some
2227 of the fs types (eg ext3, fat) do not have fine enough
2228 time granularity to match protocol, and we do not have a
2229 a way (yet) to query the server fs's time granularity (and
2230 whether it rounds times down).
2231 */
2232 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2233 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002234out:
2235 kfree(args);
2236 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002237 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002238 return rc;
2239}
2240
Jeff Layton0510eeb2008-08-02 07:26:12 -04002241static int
2242cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002244 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002245 kuid_t uid = INVALID_UID;
2246 kgid_t gid = INVALID_GID;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002247 struct inode *inode = direntry->d_inode;
2248 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002249 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 char *full_path = NULL;
2251 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002252 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002253 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002254
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002255 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256
Al Viro35c265e2014-08-19 20:25:34 -04002257 cifs_dbg(FYI, "setattr on file %pd attrs->iavalid 0x%x\n",
2258 direntry, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002259
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002260 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2261 attrs->ia_valid |= ATTR_FORCE;
2262
2263 rc = inode_change_ok(inode, attrs);
2264 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002265 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002266 return rc;
Steve French6473a552005-11-29 20:20:10 -08002267 }
Steve French50c2f752007-07-13 00:33:32 +00002268
Steve French7f573562005-08-30 11:32:14 -07002269 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302271 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002272 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302273 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
Jeff Layton0f4d6342009-03-26 13:35:37 -04002276 /*
2277 * Attempt to flush data before changing attributes. We need to do
2278 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2279 * ownership or mode then we may also need to do this. Here, we take
2280 * the safe way out and just do the flush on all setattr requests. If
2281 * the flush returns error, store it to report later and continue.
2282 *
2283 * BB: This should be smarter. Why bother flushing pages that
2284 * will be truncated anyway? Also, should we error out here if
2285 * the flush returns error?
2286 */
2287 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002288 mapping_set_error(inode->i_mapping, rc);
2289 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002290
Steve French50531442008-03-14 19:21:31 +00002291 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002292 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2293 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002294 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002296
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002297 if (attrs->ia_valid & ATTR_UID)
2298 uid = attrs->ia_uid;
2299
2300 if (attrs->ia_valid & ATTR_GID)
2301 gid = attrs->ia_gid;
2302
2303#ifdef CONFIG_CIFS_ACL
2304 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002305 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002306 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2307 uid, gid);
2308 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002309 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2310 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002311 goto cifs_setattr_exit;
2312 }
2313 }
2314 } else
2315#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002316 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002317 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318
Jeff Laytond32c4f22007-10-18 03:05:22 -07002319 /* skip mode change if it's just for clearing setuid/setgid */
2320 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2321 attrs->ia_valid &= ~ATTR_MODE;
2322
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002325 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002326#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002327 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002328 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002329 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002330 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002331 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2332 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002333 goto cifs_setattr_exit;
2334 }
2335 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002336#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002337 if (((mode & S_IWUGO) == 0) &&
2338 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002339
2340 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2341
Jeff Layton51328612008-05-22 09:33:34 -04002342 /* fix up mode if we're not using dynperm */
2343 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2344 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2345 } else if ((mode & S_IWUGO) &&
2346 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002347
2348 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2349 /* Attributes of 0 are ignored */
2350 if (dosattr == 0)
2351 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002352
2353 /* reset local inode permissions to normal */
2354 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2355 attrs->ia_mode &= ~(S_IALLUGO);
2356 if (S_ISDIR(inode->i_mode))
2357 attrs->ia_mode |=
2358 cifs_sb->mnt_dir_mode;
2359 else
2360 attrs->ia_mode |=
2361 cifs_sb->mnt_file_mode;
2362 }
2363 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2364 /* ignore mode change - ATTR_READONLY hasn't changed */
2365 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 }
2368
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002369 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2370 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2371 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2372 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
Steve Frenche30dcf32005-09-20 20:49:16 -07002374 /* Even if error on time set, no sense failing the call if
2375 the server would set the time to a reasonable value anyway,
2376 and this check ensures that we are not being called from
2377 sys_utimes in which case we ought to fail the call back to
2378 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002379 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002380 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002381 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 }
2383
2384 /* do not need local check to inode_check_ok since the server does
2385 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002386 if (rc)
2387 goto cifs_setattr_exit;
2388
2389 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002390 attrs->ia_size != i_size_read(inode))
2391 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002392
2393 setattr_copy(inode, attrs);
2394 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002395
Steve Frenche30dcf32005-09-20 20:49:16 -07002396cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002398 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 return rc;
2400}
2401
Jeff Layton0510eeb2008-08-02 07:26:12 -04002402int
2403cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2404{
2405 struct inode *inode = direntry->d_inode;
2406 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002407 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002408
2409 if (pTcon->unix_ext)
2410 return cifs_setattr_unix(direntry, attrs);
2411
2412 return cifs_setattr_nounix(direntry, attrs);
2413
2414 /* BB: add cifs_setattr_legacy for really old servers */
2415}
2416
Steve French99ee4db2007-02-27 05:35:17 +00002417#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418void cifs_delete_inode(struct inode *inode)
2419{
Joe Perchesf96637b2013-05-04 22:12:25 -05002420 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 /* may have to add back in if and when safe distributed caching of
2422 directories added e.g. via FindNotify */
2423}
Steve French99ee4db2007-02-27 05:35:17 +00002424#endif