blob: 867b7cdc794a221a6eb21257d20bdc3f9e516248 [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>
25#include <asm/div64.h>
26#include "cifsfs.h"
27#include "cifspdu.h"
28#include "cifsglob.h"
29#include "cifsproto.h"
30#include "cifs_debug.h"
31#include "cifs_fs_sb.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053032#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
Christoph Hellwig70eff552008-02-15 20:55:05 +000034
David Howells01c64fe2011-01-14 18:45:47 +000035static void cifs_set_ops(struct inode *inode)
Christoph Hellwig70eff552008-02-15 20:55:05 +000036{
37 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
38
39 switch (inode->i_mode & S_IFMT) {
40 case S_IFREG:
41 inode->i_op = &cifs_file_inode_ops;
42 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
43 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
44 inode->i_fop = &cifs_file_direct_nobrl_ops;
45 else
46 inode->i_fop = &cifs_file_direct_ops;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +030047 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
48 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
49 inode->i_fop = &cifs_file_strict_nobrl_ops;
50 else
51 inode->i_fop = &cifs_file_strict_ops;
Christoph Hellwig70eff552008-02-15 20:55:05 +000052 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
53 inode->i_fop = &cifs_file_nobrl_ops;
54 else { /* not direct, send byte range locks */
55 inode->i_fop = &cifs_file_ops;
56 }
57
Christoph Hellwig70eff552008-02-15 20:55:05 +000058 /* check if server can support readpages */
Jeff Layton0d424ad2010-09-20 16:01:35 -070059 if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
Christoph Hellwig70eff552008-02-15 20:55:05 +000060 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
61 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
62 else
63 inode->i_data.a_ops = &cifs_addr_ops;
64 break;
65 case S_IFDIR:
Steve Frenchbc5b6e22008-03-11 21:07:48 +000066#ifdef CONFIG_CIFS_DFS_UPCALL
David Howells01c64fe2011-01-14 18:45:47 +000067 if (IS_AUTOMOUNT(inode)) {
Igor Mammedov79626702008-03-09 03:44:18 +000068 inode->i_op = &cifs_dfs_referral_inode_operations;
69 } else {
Steve Frenchbc5b6e22008-03-11 21:07:48 +000070#else /* NO DFS support, treat as a directory */
71 {
72#endif
Igor Mammedov79626702008-03-09 03:44:18 +000073 inode->i_op = &cifs_dir_inode_ops;
74 inode->i_fop = &cifs_dir_ops;
75 }
Christoph Hellwig70eff552008-02-15 20:55:05 +000076 break;
77 case S_IFLNK:
78 inode->i_op = &cifs_symlink_inode_ops;
79 break;
80 default:
81 init_special_inode(inode, inode->i_mode, inode->i_rdev);
82 break;
83 }
84}
85
Jeff Laytondf2cf172010-02-12 07:44:16 -050086/* check inode attributes against fattr. If they don't match, tag the
87 * inode for cache invalidation
88 */
89static void
90cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
91{
92 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
93
Joe Perchesf96637b2013-05-04 22:12:25 -050094 cifs_dbg(FYI, "%s: revalidating inode %llu\n",
95 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -050096
97 if (inode->i_state & I_NEW) {
Joe Perchesf96637b2013-05-04 22:12:25 -050098 cifs_dbg(FYI, "%s: inode %llu is new\n",
99 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500100 return;
101 }
102
103 /* don't bother with revalidation if we have an oplock */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400104 if (CIFS_CACHE_READ(cifs_i)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500105 cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
106 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500107 return;
108 }
109
110 /* revalidate if mtime or size have changed */
111 if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
112 cifs_i->server_eof == fattr->cf_eof) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500113 cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
114 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500115 return;
116 }
117
Joe Perchesf96637b2013-05-04 22:12:25 -0500118 cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
119 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500120 cifs_i->invalid_mapping = true;
121}
122
Jim McDonough74d290d2013-09-21 10:36:10 -0500123/*
124 * copy nlink to the inode, unless it wasn't provided. Provide
125 * sane values if we don't have an existing one and none was provided
126 */
127static void
128cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
129{
130 /*
131 * if we're in a situation where we can't trust what we
132 * got from the server (readdir, some non-unix cases)
133 * fake reasonable values
134 */
135 if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
136 /* only provide fake values on a new inode */
137 if (inode->i_state & I_NEW) {
138 if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
139 set_nlink(inode, 2);
140 else
141 set_nlink(inode, 1);
142 }
143 return;
144 }
145
146 /* we trust the server, so update it */
147 set_nlink(inode, fattr->cf_nlink);
148}
149
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400150/* populate an inode with info from a cifs_fattr struct */
151void
152cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
Christoph Hellwig75f12982008-02-25 20:25:21 +0000153{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400154 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400155 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000156
Jeff Laytondf2cf172010-02-12 07:44:16 -0500157 cifs_revalidate_cache(inode, fattr);
158
Steve Frenchb7ca6922012-08-03 08:43:01 -0500159 spin_lock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400160 inode->i_atime = fattr->cf_atime;
161 inode->i_mtime = fattr->cf_mtime;
162 inode->i_ctime = fattr->cf_ctime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400163 inode->i_rdev = fattr->cf_rdev;
Jim McDonough74d290d2013-09-21 10:36:10 -0500164 cifs_nlink_fattr_to_inode(inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400165 inode->i_uid = fattr->cf_uid;
166 inode->i_gid = fattr->cf_gid;
167
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400168 /* if dynperm is set, don't clobber existing mode */
169 if (inode->i_state & I_NEW ||
170 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
171 inode->i_mode = fattr->cf_mode;
172
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400173 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400174
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400175 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
176 cifs_i->time = 0;
177 else
178 cifs_i->time = jiffies;
179
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400180 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000181
Jeff Layton835a36c2010-02-10 16:21:33 -0500182 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000183 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400184 * Can't safely change the file size here if the client is writing to
185 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000186 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400187 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
188 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000189
190 /*
191 * i_blocks is not related to (i_size / i_blksize),
192 * but instead 512 byte (2**9) size is required for
193 * calculating num blocks.
194 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400195 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000196 }
197 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400198
David Howells01c64fe2011-01-14 18:45:47 +0000199 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
200 inode->i_flags |= S_AUTOMOUNT;
Jeff Laytonc2b93e02013-05-07 11:28:31 -0400201 if (inode->i_state & I_NEW)
202 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000203}
204
Jeff Layton4065c802010-05-17 07:18:58 -0400205void
206cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
207{
208 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
209
210 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
211 return;
212
213 fattr->cf_uniqueid = iunique(sb, ROOT_I);
214}
215
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400216/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
217void
218cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
219 struct cifs_sb_info *cifs_sb)
220{
221 memset(fattr, 0, sizeof(*fattr));
222 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
223 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
224 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
225
226 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
227 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
228 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
229 fattr->cf_mode = le64_to_cpu(info->Permissions);
230
231 /*
232 * Since we set the inode type below we need to mask off
233 * to avoid strange results if bits set above.
234 */
235 fattr->cf_mode &= ~S_IFMT;
236 switch (le32_to_cpu(info->Type)) {
237 case UNIX_FILE:
238 fattr->cf_mode |= S_IFREG;
239 fattr->cf_dtype = DT_REG;
240 break;
241 case UNIX_SYMLINK:
242 fattr->cf_mode |= S_IFLNK;
243 fattr->cf_dtype = DT_LNK;
244 break;
245 case UNIX_DIR:
246 fattr->cf_mode |= S_IFDIR;
247 fattr->cf_dtype = DT_DIR;
248 break;
249 case UNIX_CHARDEV:
250 fattr->cf_mode |= S_IFCHR;
251 fattr->cf_dtype = DT_CHR;
252 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
253 le64_to_cpu(info->DevMinor) & MINORMASK);
254 break;
255 case UNIX_BLOCKDEV:
256 fattr->cf_mode |= S_IFBLK;
257 fattr->cf_dtype = DT_BLK;
258 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
259 le64_to_cpu(info->DevMinor) & MINORMASK);
260 break;
261 case UNIX_FIFO:
262 fattr->cf_mode |= S_IFIFO;
263 fattr->cf_dtype = DT_FIFO;
264 break;
265 case UNIX_SOCKET:
266 fattr->cf_mode |= S_IFSOCK;
267 fattr->cf_dtype = DT_SOCK;
268 break;
269 default:
270 /* safest to call it a file if we do not know */
271 fattr->cf_mode |= S_IFREG;
272 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500273 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400274 break;
275 }
276
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800277 fattr->cf_uid = cifs_sb->mnt_uid;
278 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
279 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800280 if (id < ((uid_t)-1)) {
281 kuid_t uid = make_kuid(&init_user_ns, id);
282 if (uid_valid(uid))
283 fattr->cf_uid = uid;
284 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800285 }
286
287 fattr->cf_gid = cifs_sb->mnt_gid;
288 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
289 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800290 if (id < ((gid_t)-1)) {
291 kgid_t gid = make_kgid(&init_user_ns, id);
292 if (gid_valid(gid))
293 fattr->cf_gid = gid;
294 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800295 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400296
297 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
298}
Steve Frenchb9a32602008-05-20 21:52:32 +0000299
300/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400301 * Fill a cifs_fattr struct with fake inode info.
302 *
303 * Needed to setup cifs_fattr data for the directory which is the
304 * junction to the new submount (ie to setup the fake directory
305 * which represents a DFS referral).
Steve Frenchb9a32602008-05-20 21:52:32 +0000306 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000307static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400308cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000309{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400310 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000311
Joe Perchesf96637b2013-05-04 22:12:25 -0500312 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000313
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400314 memset(fattr, 0, sizeof(*fattr));
315 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
316 fattr->cf_uid = cifs_sb->mnt_uid;
317 fattr->cf_gid = cifs_sb->mnt_gid;
318 fattr->cf_atime = CURRENT_TIME;
319 fattr->cf_ctime = CURRENT_TIME;
320 fattr->cf_mtime = CURRENT_TIME;
321 fattr->cf_nlink = 2;
322 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000323}
324
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700325static int
326cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500327{
328 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400329 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500330 FILE_UNIX_BASIC_INFO find_data;
331 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500332 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500333 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700334 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000335 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500336
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400337 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700338 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500339 if (!rc) {
340 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
341 } else if (rc == -EREMOTE) {
342 cifs_create_dfs_fattr(&fattr, inode->i_sb);
343 rc = 0;
344 }
345
346 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400347 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500348 return rc;
349}
350
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400352 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400353 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400355 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000356 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400357 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000358 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400359 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
Joe Perchesf96637b2013-05-04 22:12:25 -0500362 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000363
Jeff Layton7ffec372010-09-29 19:51:11 -0400364 tlink = cifs_sb_tlink(cifs_sb);
365 if (IS_ERR(tlink))
366 return PTR_ERR(tlink);
367 tcon = tlink_tcon(tlink);
368
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400370 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Steve French737b7582005-04-28 22:41:06 -0700371 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
372 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400373 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400374
375 if (!rc) {
376 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
377 } else if (rc == -EREMOTE) {
378 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700379 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400380 } else {
381 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000382 }
383
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200384 /* check for Minshall+French symlinks */
385 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
386 int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
387 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500388 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200389 }
390
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400391 if (*pinode == NULL) {
392 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400393 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400394 *pinode = cifs_iget(sb, &fattr);
395 if (!*pinode)
396 rc = -ENOMEM;
397 } else {
398 /* we already have inode, update it */
399 cifs_fattr_to_inode(*pinode, &fattr);
400 }
Steve French0e4bbde2008-05-20 19:50:46 +0000401
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 return rc;
403}
404
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400405static int
406cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400407 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800408{
409 int rc;
Steve French4b18f2a2008-04-29 00:06:05 +0000410 int oplock = 0;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800411 __u16 netfid;
Jeff Layton7ffec372010-09-29 19:51:11 -0400412 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000413 struct cifs_tcon *tcon;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000414 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800415 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800416 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000417 char *pbuf;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800418
419 pbuf = buf;
420
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400421 fattr->cf_mode &= ~S_IFMT;
422
423 if (fattr->cf_eof == 0) {
424 fattr->cf_mode |= S_IFIFO;
425 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800426 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400427 } else if (fattr->cf_eof < 8) {
428 fattr->cf_mode |= S_IFREG;
429 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800430 return -EINVAL; /* EOPNOTSUPP? */
431 }
Steve French50c2f752007-07-13 00:33:32 +0000432
Jeff Layton7ffec372010-09-29 19:51:11 -0400433 tlink = cifs_sb_tlink(cifs_sb);
434 if (IS_ERR(tlink))
435 return PTR_ERR(tlink);
436 tcon = tlink_tcon(tlink);
437
438 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800439 CREATE_NOT_DIR, &netfid, &oplock, NULL,
440 cifs_sb->local_nls,
441 cifs_sb->mnt_cifs_flags &
442 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000443 if (rc == 0) {
Steve Frenchec637e32005-12-12 20:53:18 -0800444 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800445 /* Read header */
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000446 io_parms.netfid = netfid;
447 io_parms.pid = current->tgid;
448 io_parms.tcon = tcon;
449 io_parms.offset = 0;
450 io_parms.length = 24;
451 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
452 &buf_type);
Steve French4523cc32007-04-30 20:13:06 +0000453 if ((rc == 0) && (bytes_read >= 8)) {
454 if (memcmp("IntxBLK", pbuf, 8) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500455 cifs_dbg(FYI, "Block device\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400456 fattr->cf_mode |= S_IFBLK;
457 fattr->cf_dtype = DT_BLK;
Steve French4523cc32007-04-30 20:13:06 +0000458 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800459 /* we have enough to decode dev num */
460 __u64 mjr; /* major */
461 __u64 mnr; /* minor */
462 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
463 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400464 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve French86c96b42005-11-18 20:25:31 -0800465 }
Steve French4523cc32007-04-30 20:13:06 +0000466 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500467 cifs_dbg(FYI, "Char device\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400468 fattr->cf_mode |= S_IFCHR;
469 fattr->cf_dtype = DT_CHR;
Steve French4523cc32007-04-30 20:13:06 +0000470 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800471 /* we have enough to decode dev num */
472 __u64 mjr; /* major */
473 __u64 mnr; /* minor */
474 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
475 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400476 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000477 }
Steve French4523cc32007-04-30 20:13:06 +0000478 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500479 cifs_dbg(FYI, "Symlink\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400480 fattr->cf_mode |= S_IFLNK;
481 fattr->cf_dtype = DT_LNK;
Steve French86c96b42005-11-18 20:25:31 -0800482 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400483 fattr->cf_mode |= S_IFREG; /* file? */
484 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000485 rc = -EOPNOTSUPP;
Steve French86c96b42005-11-18 20:25:31 -0800486 }
Steve French3020a1f2005-11-18 11:31:10 -0800487 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400488 fattr->cf_mode |= S_IFREG; /* then it is a file */
489 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000490 rc = -EOPNOTSUPP; /* or some unknown SFU type */
491 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400492 CIFSSMBClose(xid, tcon, netfid);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800493 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400494 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800495 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800496}
497
Steve French9e294f12005-11-17 16:59:21 -0800498#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
499
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400500/*
501 * Fetch mode bits as provided by SFU.
502 *
503 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
504 */
505static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400506 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800507{
Steve French3020a1f2005-11-18 11:31:10 -0800508#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800509 ssize_t rc;
510 char ea_value[4];
511 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400512 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000513 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800514
Jeff Layton7ffec372010-09-29 19:51:11 -0400515 tlink = cifs_sb_tlink(cifs_sb);
516 if (IS_ERR(tlink))
517 return PTR_ERR(tlink);
518 tcon = tlink_tcon(tlink);
519
520 rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400521 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
522 cifs_sb->mnt_cifs_flags &
523 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400524 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000525 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800526 return (int)rc;
527 else if (rc > 3) {
528 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400529 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500530 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
531 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400532 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500533 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800534 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400535
536 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800537#else
538 return -EOPNOTSUPP;
539#endif
Steve French9e294f12005-11-17 16:59:21 -0800540}
541
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400542/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000543static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400544cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
545 struct cifs_sb_info *cifs_sb, bool adjust_tz)
Steve Frenchb9a32602008-05-20 21:52:32 +0000546{
Steve French96daf2b2011-05-27 04:34:02 +0000547 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700548
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400549 memset(fattr, 0, sizeof(*fattr));
550 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
551 if (info->DeletePending)
552 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000553
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400554 if (info->LastAccessTime)
555 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
556 else
557 fattr->cf_atime = CURRENT_TIME;
558
559 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
560 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
561
562 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700563 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
564 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400565 }
566
567 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
568 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500569 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400570
Jim McDonough74d290d2013-09-21 10:36:10 -0500571 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400572 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
573 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
574 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300575 /*
576 * Server can return wrong NumberOfLinks value for directories
577 * when Unix extensions are disabled - fake it.
578 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500579 if (!tcon->unix_ext)
580 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Pavel Shilovskyb42bf882013-08-14 19:25:21 +0400581 } else if (fattr->cf_cifsattrs & ATTR_REPARSE) {
582 fattr->cf_mode = S_IFLNK;
583 fattr->cf_dtype = DT_LNK;
584 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400585 } else {
586 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
587 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400588
Jeff Laytond0c280d2009-07-09 01:46:44 -0400589 /* clear write bits if ATTR_READONLY is set */
590 if (fattr->cf_cifsattrs & ATTR_READONLY)
591 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400592
Jim McDonough74d290d2013-09-21 10:36:10 -0500593 /*
594 * Don't accept zero nlink from non-unix servers unless
595 * delete is pending. Instead mark it as unknown.
596 */
597 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
598 !info->DeletePending) {
599 cifs_dbg(1, "bogus file nlink value %u\n",
Steve French6658b9f2013-07-04 14:38:48 -0500600 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500601 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500602 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300603 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400604
605 fattr->cf_uid = cifs_sb->mnt_uid;
606 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000607}
608
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700609static int
610cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500611{
612 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400613 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500614 FILE_ALL_INFO find_data;
615 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500616 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500617 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700618 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000619 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700620 struct TCP_Server_Info *server = tcon->ses->server;
621
622 if (!server->ops->query_file_info)
623 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500624
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400625 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700626 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400627 switch (rc) {
628 case 0:
629 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
630 break;
631 case -EREMOTE:
632 cifs_create_dfs_fattr(&fattr, inode->i_sb);
633 rc = 0;
634 break;
635 case -EOPNOTSUPP:
636 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500637 /*
638 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000639 * for now, just skip revalidating and mark inode for
640 * immediate reval.
641 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500642 rc = 0;
643 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400644 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500645 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400646 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500647
648 /*
649 * don't bother with SFU junk here -- just mark inode as needing
650 * revalidation.
651 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500652 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
653 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
654 cifs_fattr_to_inode(inode, &fattr);
655cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400656 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500657 return rc;
658}
659
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400660int
661cifs_get_inode_info(struct inode **inode, const char *full_path,
662 FILE_ALL_INFO *data, struct super_block *sb, int xid,
663 const __u16 *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500665 bool validinum = false;
666 __u16 srchflgs;
667 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400668 struct cifs_tcon *tcon;
669 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400670 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400673 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400674 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500675 struct cifs_search_info *srchinf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
Jeff Layton7ffec372010-09-29 19:51:11 -0400677 tlink = cifs_sb_tlink(cifs_sb);
678 if (IS_ERR(tlink))
679 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400680 tcon = tlink_tcon(tlink);
681 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400682
Joe Perchesf96637b2013-05-04 22:12:25 -0500683 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400685 if ((data == NULL) && (*inode != NULL)) {
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400686 if (CIFS_CACHE_READ(CIFS_I(*inode))) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500687 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400688 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 }
690 }
691
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400692 /* if inode info is not passed, get it from server */
693 if (data == NULL) {
694 if (!server->ops->query_path_info) {
695 rc = -ENOSYS;
696 goto cgii_exit;
697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400699 if (buf == NULL) {
700 rc = -ENOMEM;
701 goto cgii_exit;
702 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400703 data = (FILE_ALL_INFO *)buf;
704 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
705 data, &adjust_tz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400707
708 if (!rc) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400709 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb,
710 adjust_tz);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400711 } else if (rc == -EREMOTE) {
712 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000713 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500714 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
715 srchinf = kzalloc(sizeof(struct cifs_search_info),
716 GFP_KERNEL);
717 if (srchinf == NULL) {
718 rc = -ENOMEM;
719 goto cgii_exit;
720 }
721
722 srchinf->endOfSearch = false;
723 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
724
725 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
726 CIFS_SEARCH_CLOSE_AT_END |
727 CIFS_SEARCH_BACKUP_SEARCH;
728
729 rc = CIFSFindFirst(xid, tcon, full_path,
730 cifs_sb, NULL, srchflgs, srchinf, false);
731 if (!rc) {
732 data =
733 (FILE_ALL_INFO *)srchinf->srch_entries_start;
734
735 cifs_dir_info_to_fattr(&fattr,
736 (FILE_DIRECTORY_INFO *)data, cifs_sb);
737 fattr.cf_uniqueid = le64_to_cpu(
738 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
739 validinum = true;
740
741 cifs_buf_release(srchinf->ntwrk_buf_start);
742 }
743 kfree(srchinf);
744 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000745 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400747 /*
748 * If an inode wasn't passed in, then get the inode number
749 *
750 * Is an i_ino of zero legal? Can we use that to check if the server
751 * supports returning inode numbers? Are there other sanity checks we
752 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400753 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400754 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000755 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500756 if (validinum == false) {
757 if (server->ops->get_srv_inum)
758 tmprc = server->ops->get_srv_inum(xid,
759 tcon, cifs_sb, full_path,
760 &fattr.cf_uniqueid, data);
761 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500762 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
763 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500764 fattr.cf_uniqueid = iunique(sb, ROOT_I);
765 cifs_autodisable_serverino(cifs_sb);
766 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500767 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500768 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400769 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500770 } else
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400771 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000772
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400773 /* query for SFU type info if supported and needed */
774 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
775 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
776 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
777 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500778 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000779 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000780
Jeff Layton79df1ba2010-12-06 12:52:08 -0500781#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000782 /* fill in 0777 bits from ACL */
783 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400784 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600785 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500786 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
787 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600788 goto cgii_exit;
789 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000790 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500791#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400792
793 /* fill in remaining high mode bits e.g. SUID, VTX */
794 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
795 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
796
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200797 /* check for Minshall+French symlinks */
798 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
799 tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
800 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500801 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200802 }
803
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400804 if (!*inode) {
805 *inode = cifs_iget(sb, &fattr);
806 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400807 rc = -ENOMEM;
808 } else {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400809 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000810 }
811
Igor Mammedov79626702008-03-09 03:44:18 +0000812cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400814 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 return rc;
816}
817
Steve French7f8ed422007-09-28 22:28:55 +0000818static const struct inode_operations cifs_ipc_inode_ops = {
819 .lookup = cifs_lookup,
820};
821
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400822static int
823cifs_find_inode(struct inode *inode, void *opaque)
824{
825 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
826
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400827 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400828 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
829 return 0;
830
Jeff Layton20054bd2011-01-07 11:30:27 -0500831 /* use createtime like an i_generation field */
832 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
833 return 0;
834
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400835 /* don't match inode of different type */
836 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
837 return 0;
838
Jeff Layton5acfec22010-08-02 17:43:54 -0400839 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400840 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400841 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400842
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400843 return 1;
844}
845
846static int
847cifs_init_inode(struct inode *inode, void *opaque)
848{
849 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
850
851 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500852 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400853 return 0;
854}
855
Jeff Layton5acfec22010-08-02 17:43:54 -0400856/*
857 * walk dentry list for an inode and report whether it has aliases that
858 * are hashed. We use this to determine if a directory inode can actually
859 * be used.
860 */
861static bool
862inode_has_hashed_dentries(struct inode *inode)
863{
864 struct dentry *dentry;
865
Nick Piggin873feea2011-01-07 17:50:06 +1100866 spin_lock(&inode->i_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800867 hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400868 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100869 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400870 return true;
871 }
872 }
Nick Piggin873feea2011-01-07 17:50:06 +1100873 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400874 return false;
875}
876
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400877/* Given fattrs, get a corresponding inode */
878struct inode *
879cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
880{
881 unsigned long hash;
882 struct inode *inode;
883
Jeff Layton3d694382010-05-11 14:59:55 -0400884retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -0500885 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400886
887 /* hash down to 32-bits on 32-bit arch */
888 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
889
890 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400891 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400892 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400893 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400894 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400895
896 if (inode_has_hashed_dentries(inode)) {
897 cifs_autodisable_serverino(CIFS_SB(sb));
898 iput(inode);
899 fattr->cf_uniqueid = iunique(sb, ROOT_I);
900 goto retry_iget5_locked;
901 }
Jeff Layton3d694382010-05-11 14:59:55 -0400902 }
903
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400904 cifs_fattr_to_inode(inode, fattr);
905 if (sb->s_flags & MS_NOATIME)
906 inode->i_flags |= S_NOATIME | S_NOCMTIME;
907 if (inode->i_state & I_NEW) {
908 inode->i_ino = hash;
Jeff Layton522440e2010-09-29 09:49:54 -0400909 if (S_ISREG(inode->i_mode))
910 inode->i_data.backing_dev_info = sb->s_bdi;
Steve French0ccd4802010-07-16 04:31:02 +0000911#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530912 /* initialize per-inode cache cookie pointer */
913 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000914#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400915 unlock_new_inode(inode);
916 }
917 }
918
919 return inode;
920}
921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600923struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400925 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700926 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400927 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800928 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000929 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800930
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400931 xid = get_xid();
Jeff Layton0d424ad2010-09-20 16:01:35 -0700932 if (tcon->unix_ext)
Steve Frenchf87d39d2011-05-27 03:50:55 +0000933 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400934 else
Steve Frenchf87d39d2011-05-27 03:50:55 +0000935 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400936
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000937 if (!inode) {
938 inode = ERR_PTR(rc);
939 goto out;
940 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400941
Steve French0ccd4802010-07-16 04:31:02 +0000942#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530943 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700944 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000945#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530946
Jeff Layton0d424ad2010-09-20 16:01:35 -0700947 if (rc && tcon->ipc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500948 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -0500949 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +0000950 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200951 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +0000952 inode->i_op = &cifs_ipc_inode_ops;
953 inode->i_fop = &simple_dir_operations;
954 inode->i_uid = cifs_sb->mnt_uid;
955 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -0500956 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +0000957 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800958 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000959 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000960 }
961
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000962out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400963 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -0800964 * TODO: This is no longer true
965 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400966 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -0800967 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968}
969
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700970int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400971cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700972 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +0000973{
Steve French388e57b2008-09-16 23:50:58 +0000974 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +0000975 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700976 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +0000977 FILE_BASIC_INFO info_buf;
978
Steve French1adcb712009-02-25 14:19:56 +0000979 if (attrs == NULL)
980 return -EINVAL;
981
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700982 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
983 if (!server->ops->set_file_info)
984 return -ENOSYS;
985
Steve French388e57b2008-09-16 23:50:58 +0000986 if (attrs->ia_valid & ATTR_ATIME) {
987 set_time = true;
988 info_buf.LastAccessTime =
989 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
990 } else
991 info_buf.LastAccessTime = 0;
992
993 if (attrs->ia_valid & ATTR_MTIME) {
994 set_time = true;
995 info_buf.LastWriteTime =
996 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
997 } else
998 info_buf.LastWriteTime = 0;
999
1000 /*
1001 * Samba throws this field away, but windows may actually use it.
1002 * Do not set ctime unless other time stamps are changed explicitly
1003 * (i.e. by utimes()) since we would then have a mix of client and
1004 * server times.
1005 */
1006 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001007 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001008 info_buf.ChangeTime =
1009 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1010 } else
1011 info_buf.ChangeTime = 0;
1012
1013 info_buf.CreationTime = 0; /* don't change */
1014 info_buf.Attributes = cpu_to_le32(dosattr);
1015
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001016 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001017}
1018
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001019/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001020 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001021 * and rename it to a random name that hopefully won't conflict with
1022 * anything else.
1023 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001024int
1025cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1026 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001027{
1028 int oplock = 0;
1029 int rc;
1030 __u16 netfid;
Steve French32709582008-10-20 00:44:19 +00001031 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001032 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1033 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001034 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001035 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001036 __u32 dosattr, origattr;
1037 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001038
Jeff Layton7ffec372010-09-29 19:51:11 -04001039 tlink = cifs_sb_tlink(cifs_sb);
1040 if (IS_ERR(tlink))
1041 return PTR_ERR(tlink);
1042 tcon = tlink_tcon(tlink);
1043
Sachin Prabhuc483a982013-03-05 19:25:56 +00001044 /*
1045 * We cannot rename the file if the server doesn't support
1046 * CAP_INFOLEVEL_PASSTHRU
1047 */
1048 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1049 rc = -EBUSY;
1050 goto out;
1051 }
1052
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001053 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001054 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001055 &netfid, &oplock, NULL, cifs_sb->local_nls,
1056 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1057 if (rc != 0)
1058 goto out;
1059
Steve French32709582008-10-20 00:44:19 +00001060 origattr = cifsInode->cifsAttrs;
1061 if (origattr == 0)
1062 origattr |= ATTR_NORMAL;
1063
1064 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001065 if (dosattr == 0)
1066 dosattr |= ATTR_NORMAL;
1067 dosattr |= ATTR_HIDDEN;
1068
Steve French32709582008-10-20 00:44:19 +00001069 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1070 if (dosattr != origattr) {
1071 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1072 if (info_buf == NULL) {
1073 rc = -ENOMEM;
1074 goto out_close;
1075 }
1076 info_buf->Attributes = cpu_to_le32(dosattr);
1077 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1078 current->tgid);
1079 /* although we would like to mark the file hidden
1080 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001081 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001082 cifsInode->cifsAttrs = dosattr;
1083 else
1084 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001085 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001086
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001087 /* rename the file */
1088 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001089 cifs_sb->mnt_cifs_flags &
1090 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French32709582008-10-20 00:44:19 +00001091 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001092 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001093 goto undo_setattr;
1094 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001095
Steve French32709582008-10-20 00:44:19 +00001096 /* try to set DELETE_ON_CLOSE */
1097 if (!cifsInode->delete_pending) {
1098 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
1099 current->tgid);
1100 /*
1101 * some samba versions return -ENOENT when we try to set the
1102 * file disposition here. Likely a samba bug, but work around
1103 * it for now. This means that some cifsXXX files may hang
1104 * around after they shouldn't.
1105 *
1106 * BB: remove this hack after more servers have the fix
1107 */
1108 if (rc == -ENOENT)
1109 rc = 0;
1110 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001111 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001112 goto undo_rename;
1113 }
1114 cifsInode->delete_pending = true;
1115 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001116
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001117out_close:
1118 CIFSSMBClose(xid, tcon, netfid);
1119out:
Steve French32709582008-10-20 00:44:19 +00001120 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001121 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001122 return rc;
Steve French32709582008-10-20 00:44:19 +00001123
1124 /*
1125 * reset everything back to the original state. Don't bother
1126 * dealing with errors here since we can't do anything about
1127 * them anyway.
1128 */
1129undo_rename:
1130 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
1131 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1132 CIFS_MOUNT_MAP_SPECIAL_CHR);
1133undo_setattr:
1134 if (dosattr != origattr) {
1135 info_buf->Attributes = cpu_to_le32(origattr);
1136 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1137 current->tgid))
1138 cifsInode->cifsAttrs = origattr;
1139 }
1140
1141 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001142}
1143
Steve Frenchb7ca6922012-08-03 08:43:01 -05001144/* copied from fs/nfs/dir.c with small changes */
1145static void
1146cifs_drop_nlink(struct inode *inode)
1147{
1148 spin_lock(&inode->i_lock);
1149 if (inode->i_nlink > 0)
1150 drop_nlink(inode);
1151 spin_unlock(&inode->i_lock);
1152}
Steve Frenchff694522009-04-20 19:45:13 +00001153
1154/*
1155 * If dentry->d_inode is null (usually meaning the cached dentry
1156 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001157 * if that fails we can not attempt the fall back mechanisms on EACCESS
1158 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001159 * unlink on negative dentries currently.
1160 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001161int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162{
1163 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001164 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001166 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001167 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001168 struct super_block *sb = dir->i_sb;
1169 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001170 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001171 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001172 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001173 struct iattr *attrs = NULL;
1174 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
Joe Perchesf96637b2013-05-04 22:12:25 -05001176 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
Jeff Layton7ffec372010-09-29 19:51:11 -04001178 tlink = cifs_sb_tlink(cifs_sb);
1179 if (IS_ERR(tlink))
1180 return PTR_ERR(tlink);
1181 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001182 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001183
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001184 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
Jeff Layton5f0319a2008-09-16 14:05:16 -04001186 /* Unlink can be called from rename so we can not take the
1187 * sb->s_vfs_rename_mutex here */
1188 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301190 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001191 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 }
Steve French2d785a52007-07-15 01:48:57 +00001193
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001194 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1195 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001196 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001197 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1198 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesf96637b2013-05-04 22:12:25 -05001199 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001200 if ((rc == 0) || (rc == -ENOENT))
1201 goto psx_del_no_retry;
1202 }
1203
Steve French60502472008-10-07 18:42:52 +00001204retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001205 if (!server->ops->unlink) {
1206 rc = -ENOSYS;
1207 goto psx_del_no_retry;
1208 }
1209
1210 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001211
Steve French2d785a52007-07-15 01:48:57 +00001212psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001214 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001215 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001217 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001218 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001219 if (server->ops->rename_pending_delete) {
1220 rc = server->ops->rename_pending_delete(full_path,
1221 dentry, xid);
1222 if (rc == 0)
1223 cifs_drop_nlink(inode);
1224 }
Steve Frenchff694522009-04-20 19:45:13 +00001225 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001226 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1227 if (attrs == NULL) {
1228 rc = -ENOMEM;
1229 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 }
Steve French388e57b2008-09-16 23:50:58 +00001231
1232 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001233 cifs_inode = CIFS_I(inode);
1234 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001235 if (origattr == 0)
1236 origattr |= ATTR_NORMAL;
1237 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001238 if (dosattr == 0)
1239 dosattr |= ATTR_NORMAL;
1240 dosattr |= ATTR_HIDDEN;
1241
1242 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001243 if (rc != 0)
1244 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001245
1246 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 }
Steve French60502472008-10-07 18:42:52 +00001248
1249 /* undo the setattr if we errored out and it's needed */
1250 if (rc != 0 && dosattr != 0)
1251 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1252
Steve French388e57b2008-09-16 23:50:58 +00001253out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001254 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001255 cifs_inode = CIFS_I(inode);
1256 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001257 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001258 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001259 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001260 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001261 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001262 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001263unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001265 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001266 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001267 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 return rc;
1269}
1270
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001271static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001272cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001273 const char *full_path, struct cifs_sb_info *cifs_sb,
1274 struct cifs_tcon *tcon, const unsigned int xid)
1275{
1276 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001277 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001278
1279 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001280 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001281 xid);
1282 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001283 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1284 xid, NULL);
1285
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001286 if (rc)
1287 return rc;
1288
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001289 /*
1290 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001291 * from the server or was set bogus. Also, since this is a brand new
1292 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001293 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001294 if (inode->i_nlink < 2)
1295 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001296 mode &= ~current_umask();
1297 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001298 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001299 mode |= S_ISGID;
1300
1301 if (tcon->unix_ext) {
1302 struct cifs_unix_set_info_args args = {
1303 .mode = mode,
1304 .ctime = NO_CHANGE_64,
1305 .atime = NO_CHANGE_64,
1306 .mtime = NO_CHANGE_64,
1307 .device = 0,
1308 };
1309 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001310 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001311 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001312 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001313 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001314 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001315 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001316 args.uid = INVALID_UID; /* no change */
1317 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001318 }
1319 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1320 cifs_sb->local_nls,
1321 cifs_sb->mnt_cifs_flags &
1322 CIFS_MOUNT_MAP_SPECIAL_CHR);
1323 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001324 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001325 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001326 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001327 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001328 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001329 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1330 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001331
Jeff Layton101b92d2012-09-19 06:22:45 -07001332 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1333 inode->i_uid = current_fsuid();
1334 if (inode->i_mode & S_ISGID)
1335 inode->i_gid = parent->i_gid;
1336 else
1337 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001338 }
1339 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001340 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001341 return rc;
1342}
1343
1344static int
1345cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1346 const char *full_path, struct cifs_sb_info *cifs_sb,
1347 struct cifs_tcon *tcon, const unsigned int xid)
1348{
1349 int rc = 0;
1350 u32 oplock = 0;
1351 FILE_UNIX_BASIC_INFO *info = NULL;
1352 struct inode *newinode = NULL;
1353 struct cifs_fattr fattr;
1354
1355 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1356 if (info == NULL) {
1357 rc = -ENOMEM;
1358 goto posix_mkdir_out;
1359 }
1360
1361 mode &= ~current_umask();
1362 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1363 NULL /* netfid */, info, &oplock, full_path,
1364 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1365 CIFS_MOUNT_MAP_SPECIAL_CHR);
1366 if (rc == -EOPNOTSUPP)
1367 goto posix_mkdir_out;
1368 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001369 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001370 d_drop(dentry);
1371 goto posix_mkdir_out;
1372 }
1373
1374 if (info->Type == cpu_to_le32(-1))
1375 /* no return info, go query for it */
1376 goto posix_mkdir_get_info;
1377 /*
1378 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1379 * need to set uid/gid.
1380 */
1381
1382 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1383 cifs_fill_uniqueid(inode->i_sb, &fattr);
1384 newinode = cifs_iget(inode->i_sb, &fattr);
1385 if (!newinode)
1386 goto posix_mkdir_get_info;
1387
1388 d_instantiate(dentry, newinode);
1389
1390#ifdef CONFIG_CIFS_DEBUG2
Joe Perchesf96637b2013-05-04 22:12:25 -05001391 cifs_dbg(FYI, "instantiated dentry %p %s to inode %p\n",
1392 dentry, dentry->d_name.name, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001393
1394 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001395 cifs_dbg(FYI, "unexpected number of links %d\n",
1396 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001397#endif
1398
1399posix_mkdir_out:
1400 kfree(info);
1401 return rc;
1402posix_mkdir_get_info:
1403 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1404 xid);
1405 goto posix_mkdir_out;
1406}
1407
Al Viro18bb1db2011-07-26 01:41:39 -04001408int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001410 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001411 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001413 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001414 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001415 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001416 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
Joe Perchesf96637b2013-05-04 22:12:25 -05001418 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1419 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001422 tlink = cifs_sb_tlink(cifs_sb);
1423 if (IS_ERR(tlink))
1424 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001425 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001426
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001427 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
Steve French7f573562005-08-30 11:32:14 -07001429 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301431 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001432 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 }
Steve French50c2f752007-07-13 00:33:32 +00001434
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001435 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1436 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001437 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1438 tcon, xid);
1439 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001440 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001441 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001442
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001443 server = tcon->ses->server;
1444
1445 if (!server->ops->mkdir) {
1446 rc = -ENOSYS;
1447 goto mkdir_out;
1448 }
1449
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001451 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001453 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001455 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001457
1458 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1459 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001460mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001461 /*
1462 * Force revalidate to get parent dir info when needed since cached
1463 * attributes are invalid now.
1464 */
1465 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001467 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001468 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 return rc;
1470}
1471
1472int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1473{
1474 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001475 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001477 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001478 struct cifs_tcon *tcon;
1479 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 char *full_path = NULL;
1481 struct cifsInodeInfo *cifsInode;
1482
Joe Perchesf96637b2013-05-04 22:12:25 -05001483 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001485 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
Steve French7f573562005-08-30 11:32:14 -07001487 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301489 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001490 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 }
1492
Jeff Layton7ffec372010-09-29 19:51:11 -04001493 cifs_sb = CIFS_SB(inode->i_sb);
1494 tlink = cifs_sb_tlink(cifs_sb);
1495 if (IS_ERR(tlink)) {
1496 rc = PTR_ERR(tlink);
1497 goto rmdir_exit;
1498 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001499 tcon = tlink_tcon(tlink);
1500 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001501
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001502 if (!server->ops->rmdir) {
1503 rc = -ENOSYS;
1504 cifs_put_tlink(tlink);
1505 goto rmdir_exit;
1506 }
1507
1508 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001509 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510
1511 if (!rc) {
Steve French3677db12007-02-26 16:46:11 +00001512 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001513 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001514 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001515 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 }
1517
1518 cifsInode = CIFS_I(direntry->d_inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001519 /* force revalidate to go get info when needed */
1520 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001521
1522 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001523 /*
1524 * Force revalidate to get parent dir info when needed since cached
1525 * attributes are invalid now.
1526 */
1527 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001528
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1530 current_fs_time(inode->i_sb);
1531
Jeff Layton7ffec372010-09-29 19:51:11 -04001532rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001534 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 return rc;
1536}
1537
Steve Frenchee2fd962008-09-23 18:23:33 +00001538static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001539cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1540 const char *from_path, struct dentry *to_dentry,
1541 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001542{
1543 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001544 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001545 struct cifs_tcon *tcon;
1546 struct TCP_Server_Info *server;
Steve Frenchee2fd962008-09-23 18:23:33 +00001547 __u16 srcfid;
1548 int oplock, rc;
1549
Jeff Layton7ffec372010-09-29 19:51:11 -04001550 tlink = cifs_sb_tlink(cifs_sb);
1551 if (IS_ERR(tlink))
1552 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001553 tcon = tlink_tcon(tlink);
1554 server = tcon->ses->server;
1555
1556 if (!server->ops->rename)
1557 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001558
Steve Frenchee2fd962008-09-23 18:23:33 +00001559 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001560 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001561
1562 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001563 * Don't bother with rename by filehandle unless file is busy and
1564 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001565 * rename by filehandle to various Windows servers.
1566 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001567 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001568 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001569
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001570 /* open-file renames don't work across directories */
1571 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001572 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001573
Steve Frenchee2fd962008-09-23 18:23:33 +00001574 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001575 rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE,
Steve Frenchee2fd962008-09-23 18:23:33 +00001576 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1577 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1578 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchee2fd962008-09-23 18:23:33 +00001579 if (rc == 0) {
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001580 rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001581 (const char *) to_dentry->d_name.name,
1582 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1583 CIFS_MOUNT_MAP_SPECIAL_CHR);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001584 CIFSSMBClose(xid, tcon, srcfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001585 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001586do_rename_exit:
1587 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001588 return rc;
1589}
1590
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001591int
1592cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1593 struct inode *target_dir, struct dentry *target_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001595 char *from_name = NULL;
1596 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001597 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001598 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001599 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001600 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1601 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001602 unsigned int xid;
1603 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
Jeff Layton639e7a92010-09-03 11:50:09 -04001605 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001606 tlink = cifs_sb_tlink(cifs_sb);
1607 if (IS_ERR(tlink))
1608 return PTR_ERR(tlink);
1609 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001611 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001612
1613 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001614 * we already have the rename sem so we do not need to
1615 * grab it again here to protect the path integrity
1616 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001617 from_name = build_path_from_dentry(source_dentry);
1618 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 rc = -ENOMEM;
1620 goto cifs_rename_exit;
1621 }
1622
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001623 to_name = build_path_from_dentry(target_dentry);
1624 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001625 rc = -ENOMEM;
1626 goto cifs_rename_exit;
1627 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001629 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1630 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001631
Jeff Layton14121bd2008-10-20 14:45:22 -04001632 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001633 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001634 * Are src and dst hardlinks of same inode? We can only tell
1635 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001636 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001637 info_buf_source =
1638 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1639 GFP_KERNEL);
1640 if (info_buf_source == NULL) {
1641 rc = -ENOMEM;
1642 goto cifs_rename_exit;
1643 }
1644
1645 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001646 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1647 info_buf_source,
1648 cifs_sb->local_nls,
1649 cifs_sb->mnt_cifs_flags &
1650 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton8d281ef2008-10-22 13:57:01 -04001651 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001652 goto unlink_target;
1653
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001654 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1655 info_buf_target,
1656 cifs_sb->local_nls,
1657 cifs_sb->mnt_cifs_flags &
1658 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton14121bd2008-10-20 14:45:22 -04001659
Jeff Layton8d281ef2008-10-22 13:57:01 -04001660 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001661 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001662 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001663 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001664 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001665 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001666 }
1667 /*
1668 * else ... BB we could add the same check for Windows by
1669 * checking the UniqueId via FILE_INTERNAL_INFO
1670 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001671
Jeff Layton14121bd2008-10-20 14:45:22 -04001672unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001673 /* Try unlinking the target dentry if it's not negative */
1674 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Jeff Layton8d281ef2008-10-22 13:57:01 -04001675 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001676 if (tmprc)
1677 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001678 rc = cifs_do_rename(xid, source_dentry, from_name,
1679 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 }
1681
1682cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001683 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001684 kfree(from_name);
1685 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001686 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001687 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 return rc;
1689}
1690
Jeff Laytondf2cf172010-02-12 07:44:16 -05001691static bool
1692cifs_inode_needs_reval(struct inode *inode)
1693{
1694 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301695 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001696
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001697 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001698 return false;
1699
1700 if (!lookupCacheEnabled)
1701 return true;
1702
1703 if (cifs_i->time == 0)
1704 return true;
1705
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301706 if (!time_in_range(jiffies, cifs_i->time,
1707 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001708 return true;
1709
Jeff Laytondb192722010-05-17 14:51:49 -04001710 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301711 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001712 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1713 return true;
1714
Jeff Laytondf2cf172010-02-12 07:44:16 -05001715 return false;
1716}
1717
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301718/*
1719 * Zap the cache. Called when invalid_mapping flag is set.
1720 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001721int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001722cifs_invalidate_mapping(struct inode *inode)
1723{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001724 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001725 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1726
1727 cifs_i->invalid_mapping = false;
1728
Jeff Laytondf2cf172010-02-12 07:44:16 -05001729 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001730 rc = invalidate_inode_pages2(inode->i_mapping);
1731 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001732 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1733 __func__, inode);
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001734 cifs_i->invalid_mapping = true;
1735 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001736 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001737
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301738 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001739 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001740}
1741
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001742int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001743{
1744 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001745 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001746 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001747
1748 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001749 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001750
Jeff Layton13cfb732010-09-29 19:51:11 -04001751 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001752 rc = cifs_get_file_info_unix(filp);
1753 else
1754 rc = cifs_get_file_info(filp);
1755
Jeff Laytonabab0952010-02-12 07:44:18 -05001756 return rc;
1757}
1758
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001759int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001761 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001762 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001763 struct inode *inode = dentry->d_inode;
1764 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001765 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766
Jeff Laytondf2cf172010-02-12 07:44:16 -05001767 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 return -ENOENT;
1769
Jeff Laytondf2cf172010-02-12 07:44:16 -05001770 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001771 return rc;
1772
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001773 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774
1775 /* can not safely grab the rename sem here if rename calls revalidate
1776 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001777 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301779 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001780 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001782
Joe Perchesf96637b2013-05-04 22:12:25 -05001783 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1784 full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001785 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786
Jeff Layton0d424ad2010-09-20 16:01:35 -07001787 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001788 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1789 else
1790 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1791 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001793out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001795 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 return rc;
1797}
1798
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001799int cifs_revalidate_file(struct file *filp)
1800{
1801 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001802 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001803
1804 rc = cifs_revalidate_file_attr(filp);
1805 if (rc)
1806 return rc;
1807
1808 if (CIFS_I(inode)->invalid_mapping)
1809 rc = cifs_invalidate_mapping(inode);
1810 return rc;
1811}
1812
1813/* revalidate a dentry's inode attributes */
1814int cifs_revalidate_dentry(struct dentry *dentry)
1815{
1816 int rc;
1817 struct inode *inode = dentry->d_inode;
1818
1819 rc = cifs_revalidate_dentry_attr(dentry);
1820 if (rc)
1821 return rc;
1822
1823 if (CIFS_I(inode)->invalid_mapping)
1824 rc = cifs_invalidate_mapping(inode);
1825 return rc;
1826}
1827
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001829 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001831 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001832 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001833 struct inode *inode = dentry->d_inode;
1834 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001835
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001836 /*
1837 * We need to be sure that all dirty pages are written and the server
1838 * has actual ctime, mtime and file length.
1839 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001840 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001841 inode->i_mapping->nrpages != 0) {
1842 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001843 if (rc) {
1844 mapping_set_error(inode->i_mapping, rc);
1845 return rc;
1846 }
Steve French5fe14c82006-11-07 19:26:33 +00001847 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001848
1849 rc = cifs_revalidate_dentry_attr(dentry);
1850 if (rc)
1851 return rc;
1852
1853 generic_fillattr(inode, stat);
1854 stat->blksize = CIFS_MAX_MSGSIZE;
1855 stat->ino = CIFS_I(inode)->uniqueid;
1856
1857 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001858 * If on a multiuser mount without unix extensions or cifsacl being
1859 * enabled, and the admin hasn't overridden them, set the ownership
1860 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001861 */
1862 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001863 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001864 !tcon->unix_ext) {
1865 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1866 stat->uid = current_fsuid();
1867 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1868 stat->gid = current_fsgid();
1869 }
1870 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871}
1872
1873static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1874{
1875 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1876 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1877 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 int rc = 0;
1879
1880 page = grab_cache_page(mapping, index);
1881 if (!page)
1882 return -ENOMEM;
1883
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001884 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 unlock_page(page);
1886 page_cache_release(page);
1887 return rc;
1888}
1889
Christoph Hellwig1b947462010-07-18 17:51:21 -04001890static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001891{
Steve Frenchba6a46a2007-02-26 20:06:29 +00001892 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00001893 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001894 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001895
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001896 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00001897}
1898
Jeff Layton8efdbde2008-07-23 21:28:12 +00001899static int
1900cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001901 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00001902{
1903 int rc;
1904 struct cifsFileInfo *open_file;
1905 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1906 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001907 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001908 struct cifs_tcon *tcon = NULL;
1909 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001910 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001911
1912 /*
1913 * To avoid spurious oplock breaks from server, in the case of
1914 * inodes that we already have open, avoid doing path based
1915 * setting of file size if we can do it by handle.
1916 * This keeps our caching token (oplock) and avoids timeouts
1917 * when the local oplock break takes longer to flush
1918 * writebehind data than the SMB timeout for the SetPathInfo
1919 * request would allow
1920 */
Jeff Layton6508d902010-09-29 19:51:11 -04001921 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001922 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001923 tcon = tlink_tcon(open_file->tlink);
1924 server = tcon->ses->server;
1925 if (server->ops->set_file_size)
1926 rc = server->ops->set_file_size(xid, tcon, open_file,
1927 attrs->ia_size, false);
1928 else
1929 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001930 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05001931 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001932 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1933 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001934
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001935 io_parms.netfid = open_file->fid.netfid;
1936 io_parms.pid = open_file->pid;
1937 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001938 io_parms.offset = 0;
1939 io_parms.length = attrs->ia_size;
1940 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1941 NULL, NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001942 cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001943 }
1944 } else
1945 rc = -EINVAL;
1946
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001947 if (!rc)
1948 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07001949
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001950 if (tcon == NULL) {
1951 tlink = cifs_sb_tlink(cifs_sb);
1952 if (IS_ERR(tlink))
1953 return PTR_ERR(tlink);
1954 tcon = tlink_tcon(tlink);
1955 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001956 }
1957
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001958 /*
1959 * Set file size by pathname rather than by handle either because no
1960 * valid, writeable file handle for it was found or because there was
1961 * an error setting it by handle.
1962 */
1963 if (server->ops->set_path_size)
1964 rc = server->ops->set_path_size(xid, tcon, full_path,
1965 attrs->ia_size, cifs_sb, false);
1966 else
1967 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05001968 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001969 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1970 __u16 netfid;
1971 int oplock = 0;
1972
1973 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
1974 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
1975 &oplock, NULL, cifs_sb->local_nls,
1976 cifs_sb->mnt_cifs_flags &
1977 CIFS_MOUNT_MAP_SPECIAL_CHR);
1978 if (rc == 0) {
1979 unsigned int bytes_written;
1980
1981 io_parms.netfid = netfid;
1982 io_parms.pid = current->tgid;
1983 io_parms.tcon = tcon;
1984 io_parms.offset = 0;
1985 io_parms.length = attrs->ia_size;
1986 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
1987 NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001988 cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001989 CIFSSMBClose(xid, tcon, netfid);
1990 }
1991 }
1992 if (tlink)
1993 cifs_put_tlink(tlink);
1994
1995set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00001996 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001997 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04001998 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001999 cifs_truncate_page(inode->i_mapping, inode->i_size);
2000 }
2001
2002 return rc;
2003}
2004
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002005static int
2006cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2007{
2008 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002009 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002010 char *full_path = NULL;
2011 struct inode *inode = direntry->d_inode;
2012 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2013 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002014 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002015 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002016 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002017 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002018
Joe Perchesf96637b2013-05-04 22:12:25 -05002019 cifs_dbg(FYI, "setattr_unix on file %s attrs->ia_valid=0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002020 direntry->d_name.name, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002021
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002022 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002023
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002024 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2025 attrs->ia_valid |= ATTR_FORCE;
2026
2027 rc = inode_change_ok(inode, attrs);
2028 if (rc < 0)
2029 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002030
2031 full_path = build_path_from_dentry(direntry);
2032 if (full_path == NULL) {
2033 rc = -ENOMEM;
2034 goto out;
2035 }
2036
Jeff Layton0f4d6342009-03-26 13:35:37 -04002037 /*
2038 * Attempt to flush data before changing attributes. We need to do
2039 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2040 * ownership or mode then we may also need to do this. Here, we take
2041 * the safe way out and just do the flush on all setattr requests. If
2042 * the flush returns error, store it to report later and continue.
2043 *
2044 * BB: This should be smarter. Why bother flushing pages that
2045 * will be truncated anyway? Also, should we error out here if
2046 * the flush returns error?
2047 */
2048 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002049 mapping_set_error(inode->i_mapping, rc);
2050 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002051
2052 if (attrs->ia_valid & ATTR_SIZE) {
2053 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2054 if (rc != 0)
2055 goto out;
2056 }
2057
2058 /* skip mode change if it's just for clearing setuid/setgid */
2059 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2060 attrs->ia_valid &= ~ATTR_MODE;
2061
2062 args = kmalloc(sizeof(*args), GFP_KERNEL);
2063 if (args == NULL) {
2064 rc = -ENOMEM;
2065 goto out;
2066 }
2067
2068 /* set up the struct */
2069 if (attrs->ia_valid & ATTR_MODE)
2070 args->mode = attrs->ia_mode;
2071 else
2072 args->mode = NO_CHANGE_64;
2073
2074 if (attrs->ia_valid & ATTR_UID)
2075 args->uid = attrs->ia_uid;
2076 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002077 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002078
2079 if (attrs->ia_valid & ATTR_GID)
2080 args->gid = attrs->ia_gid;
2081 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002082 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002083
2084 if (attrs->ia_valid & ATTR_ATIME)
2085 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2086 else
2087 args->atime = NO_CHANGE_64;
2088
2089 if (attrs->ia_valid & ATTR_MTIME)
2090 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2091 else
2092 args->mtime = NO_CHANGE_64;
2093
2094 if (attrs->ia_valid & ATTR_CTIME)
2095 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2096 else
2097 args->ctime = NO_CHANGE_64;
2098
2099 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002100 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002101 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002102 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002103 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002104 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002105 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002106 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002107 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002108 tlink = cifs_sb_tlink(cifs_sb);
2109 if (IS_ERR(tlink)) {
2110 rc = PTR_ERR(tlink);
2111 goto out;
2112 }
2113 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002114 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002115 cifs_sb->local_nls,
2116 cifs_sb->mnt_cifs_flags &
2117 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002118 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002119 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002120
Christoph Hellwig10257742010-06-04 11:30:02 +02002121 if (rc)
2122 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002123
Christoph Hellwig10257742010-06-04 11:30:02 +02002124 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002125 attrs->ia_size != i_size_read(inode))
2126 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002127
2128 setattr_copy(inode, attrs);
2129 mark_inode_dirty(inode);
2130
2131 /* force revalidate when any of these times are set since some
2132 of the fs types (eg ext3, fat) do not have fine enough
2133 time granularity to match protocol, and we do not have a
2134 a way (yet) to query the server fs's time granularity (and
2135 whether it rounds times down).
2136 */
2137 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2138 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002139out:
2140 kfree(args);
2141 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002142 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002143 return rc;
2144}
2145
Jeff Layton0510eeb2008-08-02 07:26:12 -04002146static int
2147cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002149 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002150 kuid_t uid = INVALID_UID;
2151 kgid_t gid = INVALID_GID;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002152 struct inode *inode = direntry->d_inode;
2153 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002154 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 char *full_path = NULL;
2156 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002157 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002158 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002159
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002160 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161
Joe Perchesf96637b2013-05-04 22:12:25 -05002162 cifs_dbg(FYI, "setattr on file %s attrs->iavalid 0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002163 direntry->d_name.name, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002164
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002165 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2166 attrs->ia_valid |= ATTR_FORCE;
2167
2168 rc = inode_change_ok(inode, attrs);
2169 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002170 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002171 return rc;
Steve French6473a552005-11-29 20:20:10 -08002172 }
Steve French50c2f752007-07-13 00:33:32 +00002173
Steve French7f573562005-08-30 11:32:14 -07002174 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302176 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002177 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302178 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180
Jeff Layton0f4d6342009-03-26 13:35:37 -04002181 /*
2182 * Attempt to flush data before changing attributes. We need to do
2183 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2184 * ownership or mode then we may also need to do this. Here, we take
2185 * the safe way out and just do the flush on all setattr requests. If
2186 * the flush returns error, store it to report later and continue.
2187 *
2188 * BB: This should be smarter. Why bother flushing pages that
2189 * will be truncated anyway? Also, should we error out here if
2190 * the flush returns error?
2191 */
2192 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002193 mapping_set_error(inode->i_mapping, rc);
2194 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002195
Steve French50531442008-03-14 19:21:31 +00002196 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002197 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2198 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002199 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002201
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002202 if (attrs->ia_valid & ATTR_UID)
2203 uid = attrs->ia_uid;
2204
2205 if (attrs->ia_valid & ATTR_GID)
2206 gid = attrs->ia_gid;
2207
2208#ifdef CONFIG_CIFS_ACL
2209 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002210 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002211 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2212 uid, gid);
2213 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002214 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2215 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002216 goto cifs_setattr_exit;
2217 }
2218 }
2219 } else
2220#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002221 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002222 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
Jeff Laytond32c4f22007-10-18 03:05:22 -07002224 /* skip mode change if it's just for clearing setuid/setgid */
2225 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2226 attrs->ia_valid &= ~ATTR_MODE;
2227
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002230 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002231#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002232 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002233 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002234 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002235 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002236 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2237 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002238 goto cifs_setattr_exit;
2239 }
2240 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002241#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002242 if (((mode & S_IWUGO) == 0) &&
2243 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002244
2245 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2246
Jeff Layton51328612008-05-22 09:33:34 -04002247 /* fix up mode if we're not using dynperm */
2248 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2249 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2250 } else if ((mode & S_IWUGO) &&
2251 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002252
2253 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2254 /* Attributes of 0 are ignored */
2255 if (dosattr == 0)
2256 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002257
2258 /* reset local inode permissions to normal */
2259 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2260 attrs->ia_mode &= ~(S_IALLUGO);
2261 if (S_ISDIR(inode->i_mode))
2262 attrs->ia_mode |=
2263 cifs_sb->mnt_dir_mode;
2264 else
2265 attrs->ia_mode |=
2266 cifs_sb->mnt_file_mode;
2267 }
2268 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2269 /* ignore mode change - ATTR_READONLY hasn't changed */
2270 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 }
2273
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002274 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2275 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2276 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2277 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Steve Frenche30dcf32005-09-20 20:49:16 -07002279 /* Even if error on time set, no sense failing the call if
2280 the server would set the time to a reasonable value anyway,
2281 and this check ensures that we are not being called from
2282 sys_utimes in which case we ought to fail the call back to
2283 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002284 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002285 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002286 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 }
2288
2289 /* do not need local check to inode_check_ok since the server does
2290 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002291 if (rc)
2292 goto cifs_setattr_exit;
2293
2294 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002295 attrs->ia_size != i_size_read(inode))
2296 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002297
2298 setattr_copy(inode, attrs);
2299 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002300
Steve Frenche30dcf32005-09-20 20:49:16 -07002301cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002303 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 return rc;
2305}
2306
Jeff Layton0510eeb2008-08-02 07:26:12 -04002307int
2308cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2309{
2310 struct inode *inode = direntry->d_inode;
2311 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002312 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002313
2314 if (pTcon->unix_ext)
2315 return cifs_setattr_unix(direntry, attrs);
2316
2317 return cifs_setattr_nounix(direntry, attrs);
2318
2319 /* BB: add cifs_setattr_legacy for really old servers */
2320}
2321
Steve French99ee4db2007-02-27 05:35:17 +00002322#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323void cifs_delete_inode(struct inode *inode)
2324{
Joe Perchesf96637b2013-05-04 22:12:25 -05002325 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 /* may have to add back in if and when safe distributed caching of
2327 directories added e.g. via FindNotify */
2328}
Steve French99ee4db2007-02-27 05:35:17 +00002329#endif