blob: be58b8fcdb3c321ffbab033a4a91abc76c774df3 [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) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000386 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
387 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200388 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000389 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200390 }
391
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400392 if (*pinode == NULL) {
393 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400394 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400395 *pinode = cifs_iget(sb, &fattr);
396 if (!*pinode)
397 rc = -ENOMEM;
398 } else {
399 /* we already have inode, update it */
400 cifs_fattr_to_inode(*pinode, &fattr);
401 }
Steve French0e4bbde2008-05-20 19:50:46 +0000402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 return rc;
404}
405
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400406static int
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400407cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400408 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800409{
410 int rc;
Steve French4b18f2a2008-04-29 00:06:05 +0000411 int oplock = 0;
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 Shilovskyd81b8a42014-01-16 15:53:36 +0400414 struct cifs_fid fid;
415 struct cifs_open_parms oparms;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000416 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800417 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800418 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000419 char *pbuf;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400420 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800421
422 pbuf = buf;
423
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400424 fattr->cf_mode &= ~S_IFMT;
425
426 if (fattr->cf_eof == 0) {
427 fattr->cf_mode |= S_IFIFO;
428 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800429 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400430 } else if (fattr->cf_eof < 8) {
431 fattr->cf_mode |= S_IFREG;
432 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800433 return -EINVAL; /* EOPNOTSUPP? */
434 }
Steve French50c2f752007-07-13 00:33:32 +0000435
Jeff Layton7ffec372010-09-29 19:51:11 -0400436 tlink = cifs_sb_tlink(cifs_sb);
437 if (IS_ERR(tlink))
438 return PTR_ERR(tlink);
439 tcon = tlink_tcon(tlink);
440
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400441 oparms.tcon = tcon;
442 oparms.cifs_sb = cifs_sb;
443 oparms.desired_access = GENERIC_READ;
444 oparms.create_options = CREATE_NOT_DIR;
445 oparms.disposition = FILE_OPEN;
446 oparms.path = path;
447 oparms.fid = &fid;
448 oparms.reconnect = false;
449
450 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400451 if (rc) {
452 cifs_put_tlink(tlink);
453 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800454 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400455
456 /* Read header */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400457 io_parms.netfid = fid.netfid;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400458 io_parms.pid = current->tgid;
459 io_parms.tcon = tcon;
460 io_parms.offset = 0;
461 io_parms.length = 24;
462
463 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
464 if ((rc == 0) && (bytes_read >= 8)) {
465 if (memcmp("IntxBLK", pbuf, 8) == 0) {
466 cifs_dbg(FYI, "Block device\n");
467 fattr->cf_mode |= S_IFBLK;
468 fattr->cf_dtype = DT_BLK;
469 if (bytes_read == 24) {
470 /* we have enough to decode dev num */
471 __u64 mjr; /* major */
472 __u64 mnr; /* minor */
473 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
474 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
475 fattr->cf_rdev = MKDEV(mjr, mnr);
476 }
477 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
478 cifs_dbg(FYI, "Char device\n");
479 fattr->cf_mode |= S_IFCHR;
480 fattr->cf_dtype = DT_CHR;
481 if (bytes_read == 24) {
482 /* we have enough to decode dev num */
483 __u64 mjr; /* major */
484 __u64 mnr; /* minor */
485 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
486 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
487 fattr->cf_rdev = MKDEV(mjr, mnr);
488 }
489 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
490 cifs_dbg(FYI, "Symlink\n");
491 fattr->cf_mode |= S_IFLNK;
492 fattr->cf_dtype = DT_LNK;
493 } else {
494 fattr->cf_mode |= S_IFREG; /* file? */
495 fattr->cf_dtype = DT_REG;
496 rc = -EOPNOTSUPP;
497 }
498 } else {
499 fattr->cf_mode |= S_IFREG; /* then it is a file */
500 fattr->cf_dtype = DT_REG;
501 rc = -EOPNOTSUPP; /* or some unknown SFU type */
502 }
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +0400503 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400504 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800505 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800506}
507
Steve French9e294f12005-11-17 16:59:21 -0800508#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
509
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400510/*
511 * Fetch mode bits as provided by SFU.
512 *
513 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
514 */
515static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400516 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800517{
Steve French3020a1f2005-11-18 11:31:10 -0800518#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800519 ssize_t rc;
520 char ea_value[4];
521 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400522 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000523 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800524
Jeff Layton7ffec372010-09-29 19:51:11 -0400525 tlink = cifs_sb_tlink(cifs_sb);
526 if (IS_ERR(tlink))
527 return PTR_ERR(tlink);
528 tcon = tlink_tcon(tlink);
529
Steve Frenchd979f3b2014-02-01 23:27:18 -0600530 if (tcon->ses->server->ops->query_all_EAs == NULL) {
531 cifs_put_tlink(tlink);
532 return -EOPNOTSUPP;
533 }
534
535 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
536 "SETFILEBITS", ea_value, 4 /* size of buf */,
537 cifs_sb->local_nls,
538 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400539 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000540 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800541 return (int)rc;
542 else if (rc > 3) {
543 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400544 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500545 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
546 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400547 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500548 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800549 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400550
551 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800552#else
553 return -EOPNOTSUPP;
554#endif
Steve French9e294f12005-11-17 16:59:21 -0800555}
556
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400557/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000558static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400559cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400560 struct cifs_sb_info *cifs_sb, bool adjust_tz,
561 bool symlink)
Steve Frenchb9a32602008-05-20 21:52:32 +0000562{
Steve French96daf2b2011-05-27 04:34:02 +0000563 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700564
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400565 memset(fattr, 0, sizeof(*fattr));
566 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
567 if (info->DeletePending)
568 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000569
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400570 if (info->LastAccessTime)
571 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
572 else
573 fattr->cf_atime = CURRENT_TIME;
574
575 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
576 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
577
578 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700579 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
580 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400581 }
582
583 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
584 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500585 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400586
Jim McDonough74d290d2013-09-21 10:36:10 -0500587 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400588
589 if (symlink) {
590 fattr->cf_mode = S_IFLNK;
591 fattr->cf_dtype = DT_LNK;
592 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400593 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
594 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300595 /*
596 * Server can return wrong NumberOfLinks value for directories
597 * when Unix extensions are disabled - fake it.
598 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500599 if (!tcon->unix_ext)
600 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400601 } else {
602 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
603 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400604
Jeff Laytond0c280d2009-07-09 01:46:44 -0400605 /* clear write bits if ATTR_READONLY is set */
606 if (fattr->cf_cifsattrs & ATTR_READONLY)
607 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400608
Jim McDonough74d290d2013-09-21 10:36:10 -0500609 /*
610 * Don't accept zero nlink from non-unix servers unless
611 * delete is pending. Instead mark it as unknown.
612 */
613 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
614 !info->DeletePending) {
615 cifs_dbg(1, "bogus file nlink value %u\n",
Steve French6658b9f2013-07-04 14:38:48 -0500616 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500617 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500618 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300619 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400620
621 fattr->cf_uid = cifs_sb->mnt_uid;
622 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000623}
624
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700625static int
626cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500627{
628 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400629 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500630 FILE_ALL_INFO find_data;
631 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500632 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500633 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700634 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000635 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700636 struct TCP_Server_Info *server = tcon->ses->server;
637
638 if (!server->ops->query_file_info)
639 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500640
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400641 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700642 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400643 switch (rc) {
644 case 0:
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400645 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false,
646 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400647 break;
648 case -EREMOTE:
649 cifs_create_dfs_fattr(&fattr, inode->i_sb);
650 rc = 0;
651 break;
652 case -EOPNOTSUPP:
653 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500654 /*
655 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000656 * for now, just skip revalidating and mark inode for
657 * immediate reval.
658 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500659 rc = 0;
660 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400661 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500662 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400663 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500664
665 /*
666 * don't bother with SFU junk here -- just mark inode as needing
667 * revalidation.
668 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500669 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
670 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
671 cifs_fattr_to_inode(inode, &fattr);
672cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400673 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500674 return rc;
675}
676
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400677int
678cifs_get_inode_info(struct inode **inode, const char *full_path,
679 FILE_ALL_INFO *data, struct super_block *sb, int xid,
680 const __u16 *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500682 bool validinum = false;
683 __u16 srchflgs;
684 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400685 struct cifs_tcon *tcon;
686 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400687 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400690 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400691 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500692 struct cifs_search_info *srchinf = NULL;
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400693 bool symlink = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694
Jeff Layton7ffec372010-09-29 19:51:11 -0400695 tlink = cifs_sb_tlink(cifs_sb);
696 if (IS_ERR(tlink))
697 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400698 tcon = tlink_tcon(tlink);
699 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400700
Joe Perchesf96637b2013-05-04 22:12:25 -0500701 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400703 if ((data == NULL) && (*inode != NULL)) {
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400704 if (CIFS_CACHE_READ(CIFS_I(*inode))) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500705 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400706 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 }
708 }
709
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400710 /* if inode info is not passed, get it from server */
711 if (data == NULL) {
712 if (!server->ops->query_path_info) {
713 rc = -ENOSYS;
714 goto cgii_exit;
715 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400717 if (buf == NULL) {
718 rc = -ENOMEM;
719 goto cgii_exit;
720 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400721 data = (FILE_ALL_INFO *)buf;
722 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400723 data, &adjust_tz, &symlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400725
726 if (!rc) {
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400727 cifs_all_info_to_fattr(&fattr, data, cifs_sb, adjust_tz,
728 symlink);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400729 } else if (rc == -EREMOTE) {
730 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000731 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500732 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
733 srchinf = kzalloc(sizeof(struct cifs_search_info),
734 GFP_KERNEL);
735 if (srchinf == NULL) {
736 rc = -ENOMEM;
737 goto cgii_exit;
738 }
739
740 srchinf->endOfSearch = false;
741 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
742
743 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
744 CIFS_SEARCH_CLOSE_AT_END |
745 CIFS_SEARCH_BACKUP_SEARCH;
746
747 rc = CIFSFindFirst(xid, tcon, full_path,
748 cifs_sb, NULL, srchflgs, srchinf, false);
749 if (!rc) {
750 data =
751 (FILE_ALL_INFO *)srchinf->srch_entries_start;
752
753 cifs_dir_info_to_fattr(&fattr,
754 (FILE_DIRECTORY_INFO *)data, cifs_sb);
755 fattr.cf_uniqueid = le64_to_cpu(
756 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
757 validinum = true;
758
759 cifs_buf_release(srchinf->ntwrk_buf_start);
760 }
761 kfree(srchinf);
762 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000763 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400765 /*
766 * If an inode wasn't passed in, then get the inode number
767 *
768 * Is an i_ino of zero legal? Can we use that to check if the server
769 * supports returning inode numbers? Are there other sanity checks we
770 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400771 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400772 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000773 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500774 if (validinum == false) {
775 if (server->ops->get_srv_inum)
776 tmprc = server->ops->get_srv_inum(xid,
777 tcon, cifs_sb, full_path,
778 &fattr.cf_uniqueid, data);
779 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500780 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
781 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500782 fattr.cf_uniqueid = iunique(sb, ROOT_I);
783 cifs_autodisable_serverino(cifs_sb);
784 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500785 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500786 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400787 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500788 } else
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400789 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000790
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400791 /* query for SFU type info if supported and needed */
792 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
793 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
794 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
795 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500796 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000797 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000798
Jeff Layton79df1ba2010-12-06 12:52:08 -0500799#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000800 /* fill in 0777 bits from ACL */
801 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400802 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600803 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500804 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
805 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600806 goto cgii_exit;
807 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000808 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500809#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400810
811 /* fill in remaining high mode bits e.g. SUID, VTX */
812 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
813 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
814
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200815 /* check for Minshall+French symlinks */
816 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000817 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
818 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200819 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000820 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200821 }
822
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400823 if (!*inode) {
824 *inode = cifs_iget(sb, &fattr);
825 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400826 rc = -ENOMEM;
827 } else {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400828 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000829 }
830
Igor Mammedov79626702008-03-09 03:44:18 +0000831cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400833 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 return rc;
835}
836
Steve French7f8ed422007-09-28 22:28:55 +0000837static const struct inode_operations cifs_ipc_inode_ops = {
838 .lookup = cifs_lookup,
839};
840
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400841static int
842cifs_find_inode(struct inode *inode, void *opaque)
843{
844 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
845
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400846 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400847 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
848 return 0;
849
Jeff Layton20054bd2011-01-07 11:30:27 -0500850 /* use createtime like an i_generation field */
851 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
852 return 0;
853
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400854 /* don't match inode of different type */
855 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
856 return 0;
857
Jeff Layton5acfec22010-08-02 17:43:54 -0400858 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400859 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400860 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400861
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400862 return 1;
863}
864
865static int
866cifs_init_inode(struct inode *inode, void *opaque)
867{
868 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
869
870 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500871 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400872 return 0;
873}
874
Jeff Layton5acfec22010-08-02 17:43:54 -0400875/*
876 * walk dentry list for an inode and report whether it has aliases that
877 * are hashed. We use this to determine if a directory inode can actually
878 * be used.
879 */
880static bool
881inode_has_hashed_dentries(struct inode *inode)
882{
883 struct dentry *dentry;
884
Nick Piggin873feea2011-01-07 17:50:06 +1100885 spin_lock(&inode->i_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800886 hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400887 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100888 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400889 return true;
890 }
891 }
Nick Piggin873feea2011-01-07 17:50:06 +1100892 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400893 return false;
894}
895
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400896/* Given fattrs, get a corresponding inode */
897struct inode *
898cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
899{
900 unsigned long hash;
901 struct inode *inode;
902
Jeff Layton3d694382010-05-11 14:59:55 -0400903retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -0500904 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400905
906 /* hash down to 32-bits on 32-bit arch */
907 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
908
909 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400910 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400911 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400912 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400913 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400914
915 if (inode_has_hashed_dentries(inode)) {
916 cifs_autodisable_serverino(CIFS_SB(sb));
917 iput(inode);
918 fattr->cf_uniqueid = iunique(sb, ROOT_I);
919 goto retry_iget5_locked;
920 }
Jeff Layton3d694382010-05-11 14:59:55 -0400921 }
922
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400923 cifs_fattr_to_inode(inode, fattr);
924 if (sb->s_flags & MS_NOATIME)
925 inode->i_flags |= S_NOATIME | S_NOCMTIME;
926 if (inode->i_state & I_NEW) {
927 inode->i_ino = hash;
Jeff Layton522440e2010-09-29 09:49:54 -0400928 if (S_ISREG(inode->i_mode))
929 inode->i_data.backing_dev_info = sb->s_bdi;
Steve French0ccd4802010-07-16 04:31:02 +0000930#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530931 /* initialize per-inode cache cookie pointer */
932 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000933#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400934 unlock_new_inode(inode);
935 }
936 }
937
938 return inode;
939}
940
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600942struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400944 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700945 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400946 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800947 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000948 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800949
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400950 xid = get_xid();
Jeff Layton0d424ad2010-09-20 16:01:35 -0700951 if (tcon->unix_ext)
Steve Frenchf87d39d2011-05-27 03:50:55 +0000952 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400953 else
Steve Frenchf87d39d2011-05-27 03:50:55 +0000954 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400955
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000956 if (!inode) {
957 inode = ERR_PTR(rc);
958 goto out;
959 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400960
Steve French0ccd4802010-07-16 04:31:02 +0000961#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530962 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700963 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000964#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530965
Jeff Layton0d424ad2010-09-20 16:01:35 -0700966 if (rc && tcon->ipc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500967 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -0500968 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +0000969 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200970 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +0000971 inode->i_op = &cifs_ipc_inode_ops;
972 inode->i_fop = &simple_dir_operations;
973 inode->i_uid = cifs_sb->mnt_uid;
974 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -0500975 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +0000976 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800977 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000978 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000979 }
980
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000981out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400982 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -0800983 * TODO: This is no longer true
984 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400985 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -0800986 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987}
988
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700989int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400990cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700991 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +0000992{
Steve French388e57b2008-09-16 23:50:58 +0000993 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +0000994 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700995 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +0000996 FILE_BASIC_INFO info_buf;
997
Steve French1adcb712009-02-25 14:19:56 +0000998 if (attrs == NULL)
999 return -EINVAL;
1000
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001001 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
1002 if (!server->ops->set_file_info)
1003 return -ENOSYS;
1004
Steve French388e57b2008-09-16 23:50:58 +00001005 if (attrs->ia_valid & ATTR_ATIME) {
1006 set_time = true;
1007 info_buf.LastAccessTime =
1008 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1009 } else
1010 info_buf.LastAccessTime = 0;
1011
1012 if (attrs->ia_valid & ATTR_MTIME) {
1013 set_time = true;
1014 info_buf.LastWriteTime =
1015 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1016 } else
1017 info_buf.LastWriteTime = 0;
1018
1019 /*
1020 * Samba throws this field away, but windows may actually use it.
1021 * Do not set ctime unless other time stamps are changed explicitly
1022 * (i.e. by utimes()) since we would then have a mix of client and
1023 * server times.
1024 */
1025 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001026 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001027 info_buf.ChangeTime =
1028 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1029 } else
1030 info_buf.ChangeTime = 0;
1031
1032 info_buf.CreationTime = 0; /* don't change */
1033 info_buf.Attributes = cpu_to_le32(dosattr);
1034
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001035 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001036}
1037
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001038/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001039 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001040 * and rename it to a random name that hopefully won't conflict with
1041 * anything else.
1042 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001043int
1044cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1045 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001046{
1047 int oplock = 0;
1048 int rc;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001049 struct cifs_fid fid;
1050 struct cifs_open_parms oparms;
Steve French32709582008-10-20 00:44:19 +00001051 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001052 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1053 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001054 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001055 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001056 __u32 dosattr, origattr;
1057 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001058
Jeff Layton7ffec372010-09-29 19:51:11 -04001059 tlink = cifs_sb_tlink(cifs_sb);
1060 if (IS_ERR(tlink))
1061 return PTR_ERR(tlink);
1062 tcon = tlink_tcon(tlink);
1063
Sachin Prabhuc483a982013-03-05 19:25:56 +00001064 /*
1065 * We cannot rename the file if the server doesn't support
1066 * CAP_INFOLEVEL_PASSTHRU
1067 */
1068 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1069 rc = -EBUSY;
1070 goto out;
1071 }
1072
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001073 oparms.tcon = tcon;
1074 oparms.cifs_sb = cifs_sb;
1075 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1076 oparms.create_options = CREATE_NOT_DIR;
1077 oparms.disposition = FILE_OPEN;
1078 oparms.path = full_path;
1079 oparms.fid = &fid;
1080 oparms.reconnect = false;
1081
1082 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001083 if (rc != 0)
1084 goto out;
1085
Steve French32709582008-10-20 00:44:19 +00001086 origattr = cifsInode->cifsAttrs;
1087 if (origattr == 0)
1088 origattr |= ATTR_NORMAL;
1089
1090 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001091 if (dosattr == 0)
1092 dosattr |= ATTR_NORMAL;
1093 dosattr |= ATTR_HIDDEN;
1094
Steve French32709582008-10-20 00:44:19 +00001095 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1096 if (dosattr != origattr) {
1097 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1098 if (info_buf == NULL) {
1099 rc = -ENOMEM;
1100 goto out_close;
1101 }
1102 info_buf->Attributes = cpu_to_le32(dosattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001103 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001104 current->tgid);
1105 /* although we would like to mark the file hidden
1106 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001107 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001108 cifsInode->cifsAttrs = dosattr;
1109 else
1110 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001111 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001112
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001113 /* rename the file */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001114 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1115 cifs_sb->local_nls,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001116 cifs_sb->mnt_cifs_flags &
1117 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French32709582008-10-20 00:44:19 +00001118 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001119 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001120 goto undo_setattr;
1121 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001122
Steve French32709582008-10-20 00:44:19 +00001123 /* try to set DELETE_ON_CLOSE */
1124 if (!cifsInode->delete_pending) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001125 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001126 current->tgid);
1127 /*
1128 * some samba versions return -ENOENT when we try to set the
1129 * file disposition here. Likely a samba bug, but work around
1130 * it for now. This means that some cifsXXX files may hang
1131 * around after they shouldn't.
1132 *
1133 * BB: remove this hack after more servers have the fix
1134 */
1135 if (rc == -ENOENT)
1136 rc = 0;
1137 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001138 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001139 goto undo_rename;
1140 }
1141 cifsInode->delete_pending = true;
1142 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001143
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001144out_close:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001145 CIFSSMBClose(xid, tcon, fid.netfid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001146out:
Steve French32709582008-10-20 00:44:19 +00001147 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001148 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001149 return rc;
Steve French32709582008-10-20 00:44:19 +00001150
1151 /*
1152 * reset everything back to the original state. Don't bother
1153 * dealing with errors here since we can't do anything about
1154 * them anyway.
1155 */
1156undo_rename:
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001157 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
Steve French32709582008-10-20 00:44:19 +00001158 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1159 CIFS_MOUNT_MAP_SPECIAL_CHR);
1160undo_setattr:
1161 if (dosattr != origattr) {
1162 info_buf->Attributes = cpu_to_le32(origattr);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001163 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
Steve French32709582008-10-20 00:44:19 +00001164 current->tgid))
1165 cifsInode->cifsAttrs = origattr;
1166 }
1167
1168 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001169}
1170
Steve Frenchb7ca6922012-08-03 08:43:01 -05001171/* copied from fs/nfs/dir.c with small changes */
1172static void
1173cifs_drop_nlink(struct inode *inode)
1174{
1175 spin_lock(&inode->i_lock);
1176 if (inode->i_nlink > 0)
1177 drop_nlink(inode);
1178 spin_unlock(&inode->i_lock);
1179}
Steve Frenchff694522009-04-20 19:45:13 +00001180
1181/*
1182 * If dentry->d_inode is null (usually meaning the cached dentry
1183 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001184 * if that fails we can not attempt the fall back mechanisms on EACCESS
1185 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001186 * unlink on negative dentries currently.
1187 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001188int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189{
1190 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001191 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001193 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001194 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001195 struct super_block *sb = dir->i_sb;
1196 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001197 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001198 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001199 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001200 struct iattr *attrs = NULL;
1201 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202
Joe Perchesf96637b2013-05-04 22:12:25 -05001203 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
Jeff Layton7ffec372010-09-29 19:51:11 -04001205 tlink = cifs_sb_tlink(cifs_sb);
1206 if (IS_ERR(tlink))
1207 return PTR_ERR(tlink);
1208 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001209 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001210
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001211 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
Jeff Layton5f0319a2008-09-16 14:05:16 -04001213 /* Unlink can be called from rename so we can not take the
1214 * sb->s_vfs_rename_mutex here */
1215 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301217 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001218 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 }
Steve French2d785a52007-07-15 01:48:57 +00001220
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001221 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1222 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001223 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001224 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1225 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesf96637b2013-05-04 22:12:25 -05001226 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001227 if ((rc == 0) || (rc == -ENOENT))
1228 goto psx_del_no_retry;
1229 }
1230
Steve French60502472008-10-07 18:42:52 +00001231retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001232 if (!server->ops->unlink) {
1233 rc = -ENOSYS;
1234 goto psx_del_no_retry;
1235 }
1236
1237 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001238
Steve French2d785a52007-07-15 01:48:57 +00001239psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001241 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001242 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001244 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001245 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001246 if (server->ops->rename_pending_delete) {
1247 rc = server->ops->rename_pending_delete(full_path,
1248 dentry, xid);
1249 if (rc == 0)
1250 cifs_drop_nlink(inode);
1251 }
Steve Frenchff694522009-04-20 19:45:13 +00001252 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001253 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1254 if (attrs == NULL) {
1255 rc = -ENOMEM;
1256 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 }
Steve French388e57b2008-09-16 23:50:58 +00001258
1259 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001260 cifs_inode = CIFS_I(inode);
1261 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001262 if (origattr == 0)
1263 origattr |= ATTR_NORMAL;
1264 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001265 if (dosattr == 0)
1266 dosattr |= ATTR_NORMAL;
1267 dosattr |= ATTR_HIDDEN;
1268
1269 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001270 if (rc != 0)
1271 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001272
1273 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 }
Steve French60502472008-10-07 18:42:52 +00001275
1276 /* undo the setattr if we errored out and it's needed */
1277 if (rc != 0 && dosattr != 0)
1278 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1279
Steve French388e57b2008-09-16 23:50:58 +00001280out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001281 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001282 cifs_inode = CIFS_I(inode);
1283 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001284 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001285 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001286 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001287 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001288 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001289 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001290unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001292 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001293 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001294 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 return rc;
1296}
1297
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001298static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001299cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001300 const char *full_path, struct cifs_sb_info *cifs_sb,
1301 struct cifs_tcon *tcon, const unsigned int xid)
1302{
1303 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001304 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001305
1306 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001307 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001308 xid);
1309 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001310 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1311 xid, NULL);
1312
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001313 if (rc)
1314 return rc;
1315
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001316 /*
1317 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001318 * from the server or was set bogus. Also, since this is a brand new
1319 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001320 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001321 if (inode->i_nlink < 2)
1322 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001323 mode &= ~current_umask();
1324 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001325 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001326 mode |= S_ISGID;
1327
1328 if (tcon->unix_ext) {
1329 struct cifs_unix_set_info_args args = {
1330 .mode = mode,
1331 .ctime = NO_CHANGE_64,
1332 .atime = NO_CHANGE_64,
1333 .mtime = NO_CHANGE_64,
1334 .device = 0,
1335 };
1336 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001337 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001338 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001339 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001340 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001341 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001342 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001343 args.uid = INVALID_UID; /* no change */
1344 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001345 }
1346 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1347 cifs_sb->local_nls,
1348 cifs_sb->mnt_cifs_flags &
1349 CIFS_MOUNT_MAP_SPECIAL_CHR);
1350 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001351 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001352 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001353 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001354 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001355 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001356 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1357 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001358
Jeff Layton101b92d2012-09-19 06:22:45 -07001359 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1360 inode->i_uid = current_fsuid();
1361 if (inode->i_mode & S_ISGID)
1362 inode->i_gid = parent->i_gid;
1363 else
1364 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001365 }
1366 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001367 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001368 return rc;
1369}
1370
1371static int
1372cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1373 const char *full_path, struct cifs_sb_info *cifs_sb,
1374 struct cifs_tcon *tcon, const unsigned int xid)
1375{
1376 int rc = 0;
1377 u32 oplock = 0;
1378 FILE_UNIX_BASIC_INFO *info = NULL;
1379 struct inode *newinode = NULL;
1380 struct cifs_fattr fattr;
1381
1382 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1383 if (info == NULL) {
1384 rc = -ENOMEM;
1385 goto posix_mkdir_out;
1386 }
1387
1388 mode &= ~current_umask();
1389 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1390 NULL /* netfid */, info, &oplock, full_path,
1391 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1392 CIFS_MOUNT_MAP_SPECIAL_CHR);
1393 if (rc == -EOPNOTSUPP)
1394 goto posix_mkdir_out;
1395 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001396 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001397 d_drop(dentry);
1398 goto posix_mkdir_out;
1399 }
1400
1401 if (info->Type == cpu_to_le32(-1))
1402 /* no return info, go query for it */
1403 goto posix_mkdir_get_info;
1404 /*
1405 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1406 * need to set uid/gid.
1407 */
1408
1409 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1410 cifs_fill_uniqueid(inode->i_sb, &fattr);
1411 newinode = cifs_iget(inode->i_sb, &fattr);
1412 if (!newinode)
1413 goto posix_mkdir_get_info;
1414
1415 d_instantiate(dentry, newinode);
1416
1417#ifdef CONFIG_CIFS_DEBUG2
Joe Perchesf96637b2013-05-04 22:12:25 -05001418 cifs_dbg(FYI, "instantiated dentry %p %s to inode %p\n",
1419 dentry, dentry->d_name.name, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001420
1421 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001422 cifs_dbg(FYI, "unexpected number of links %d\n",
1423 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001424#endif
1425
1426posix_mkdir_out:
1427 kfree(info);
1428 return rc;
1429posix_mkdir_get_info:
1430 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1431 xid);
1432 goto posix_mkdir_out;
1433}
1434
Al Viro18bb1db2011-07-26 01:41:39 -04001435int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001437 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001438 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001440 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001441 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001442 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001443 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Joe Perchesf96637b2013-05-04 22:12:25 -05001445 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1446 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001449 tlink = cifs_sb_tlink(cifs_sb);
1450 if (IS_ERR(tlink))
1451 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001452 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001453
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001454 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
Steve French7f573562005-08-30 11:32:14 -07001456 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301458 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001459 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 }
Steve French50c2f752007-07-13 00:33:32 +00001461
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001462 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1463 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001464 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1465 tcon, xid);
1466 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001467 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001468 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001469
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001470 server = tcon->ses->server;
1471
1472 if (!server->ops->mkdir) {
1473 rc = -ENOSYS;
1474 goto mkdir_out;
1475 }
1476
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001478 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001480 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001482 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001484
1485 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1486 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001487mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001488 /*
1489 * Force revalidate to get parent dir info when needed since cached
1490 * attributes are invalid now.
1491 */
1492 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001494 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001495 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 return rc;
1497}
1498
1499int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1500{
1501 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001502 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001504 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001505 struct cifs_tcon *tcon;
1506 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 char *full_path = NULL;
1508 struct cifsInodeInfo *cifsInode;
1509
Joe Perchesf96637b2013-05-04 22:12:25 -05001510 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001512 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513
Steve French7f573562005-08-30 11:32:14 -07001514 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301516 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001517 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 }
1519
Jeff Layton7ffec372010-09-29 19:51:11 -04001520 cifs_sb = CIFS_SB(inode->i_sb);
1521 tlink = cifs_sb_tlink(cifs_sb);
1522 if (IS_ERR(tlink)) {
1523 rc = PTR_ERR(tlink);
1524 goto rmdir_exit;
1525 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001526 tcon = tlink_tcon(tlink);
1527 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001528
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001529 if (!server->ops->rmdir) {
1530 rc = -ENOSYS;
1531 cifs_put_tlink(tlink);
1532 goto rmdir_exit;
1533 }
1534
1535 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001536 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
1538 if (!rc) {
Steve French3677db12007-02-26 16:46:11 +00001539 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001540 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001541 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001542 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 }
1544
1545 cifsInode = CIFS_I(direntry->d_inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001546 /* force revalidate to go get info when needed */
1547 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001548
1549 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001550 /*
1551 * Force revalidate to get parent dir info when needed since cached
1552 * attributes are invalid now.
1553 */
1554 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001555
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1557 current_fs_time(inode->i_sb);
1558
Jeff Layton7ffec372010-09-29 19:51:11 -04001559rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001561 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 return rc;
1563}
1564
Steve Frenchee2fd962008-09-23 18:23:33 +00001565static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001566cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1567 const char *from_path, struct dentry *to_dentry,
1568 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001569{
1570 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001571 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001572 struct cifs_tcon *tcon;
1573 struct TCP_Server_Info *server;
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001574 struct cifs_fid fid;
1575 struct cifs_open_parms oparms;
Steve Frenchee2fd962008-09-23 18:23:33 +00001576 int oplock, rc;
1577
Jeff Layton7ffec372010-09-29 19:51:11 -04001578 tlink = cifs_sb_tlink(cifs_sb);
1579 if (IS_ERR(tlink))
1580 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001581 tcon = tlink_tcon(tlink);
1582 server = tcon->ses->server;
1583
1584 if (!server->ops->rename)
1585 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001586
Steve Frenchee2fd962008-09-23 18:23:33 +00001587 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001588 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001589
1590 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001591 * Don't bother with rename by filehandle unless file is busy and
1592 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001593 * rename by filehandle to various Windows servers.
1594 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001595 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001596 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001597
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001598 /* open-file renames don't work across directories */
1599 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001600 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001601
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001602 oparms.tcon = tcon;
1603 oparms.cifs_sb = cifs_sb;
Steve Frenchee2fd962008-09-23 18:23:33 +00001604 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001605 oparms.desired_access = DELETE;
1606 oparms.create_options = CREATE_NOT_DIR;
1607 oparms.disposition = FILE_OPEN;
1608 oparms.path = from_path;
1609 oparms.fid = &fid;
1610 oparms.reconnect = false;
1611
1612 rc = CIFS_open(xid, &oparms, &oplock, NULL);
Steve Frenchee2fd962008-09-23 18:23:33 +00001613 if (rc == 0) {
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001614 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001615 (const char *) to_dentry->d_name.name,
1616 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1617 CIFS_MOUNT_MAP_SPECIAL_CHR);
Pavel Shilovskyd81b8a42014-01-16 15:53:36 +04001618 CIFSSMBClose(xid, tcon, fid.netfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001619 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001620do_rename_exit:
1621 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001622 return rc;
1623}
1624
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001625int
1626cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1627 struct inode *target_dir, struct dentry *target_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001629 char *from_name = NULL;
1630 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001631 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001632 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001633 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001634 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1635 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001636 unsigned int xid;
1637 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638
Jeff Layton639e7a92010-09-03 11:50:09 -04001639 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001640 tlink = cifs_sb_tlink(cifs_sb);
1641 if (IS_ERR(tlink))
1642 return PTR_ERR(tlink);
1643 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001645 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001646
1647 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001648 * we already have the rename sem so we do not need to
1649 * grab it again here to protect the path integrity
1650 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001651 from_name = build_path_from_dentry(source_dentry);
1652 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 rc = -ENOMEM;
1654 goto cifs_rename_exit;
1655 }
1656
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001657 to_name = build_path_from_dentry(target_dentry);
1658 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001659 rc = -ENOMEM;
1660 goto cifs_rename_exit;
1661 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001663 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1664 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001665
Jeff Layton14121bd2008-10-20 14:45:22 -04001666 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001667 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001668 * Are src and dst hardlinks of same inode? We can only tell
1669 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001670 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001671 info_buf_source =
1672 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1673 GFP_KERNEL);
1674 if (info_buf_source == NULL) {
1675 rc = -ENOMEM;
1676 goto cifs_rename_exit;
1677 }
1678
1679 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001680 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1681 info_buf_source,
1682 cifs_sb->local_nls,
1683 cifs_sb->mnt_cifs_flags &
1684 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton8d281ef2008-10-22 13:57:01 -04001685 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001686 goto unlink_target;
1687
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001688 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1689 info_buf_target,
1690 cifs_sb->local_nls,
1691 cifs_sb->mnt_cifs_flags &
1692 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton14121bd2008-10-20 14:45:22 -04001693
Jeff Layton8d281ef2008-10-22 13:57:01 -04001694 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001695 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001696 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001697 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001698 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001699 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001700 }
1701 /*
1702 * else ... BB we could add the same check for Windows by
1703 * checking the UniqueId via FILE_INTERNAL_INFO
1704 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001705
Jeff Layton14121bd2008-10-20 14:45:22 -04001706unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001707 /* Try unlinking the target dentry if it's not negative */
1708 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Jeff Layton8d281ef2008-10-22 13:57:01 -04001709 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001710 if (tmprc)
1711 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001712 rc = cifs_do_rename(xid, source_dentry, from_name,
1713 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 }
1715
1716cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001717 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001718 kfree(from_name);
1719 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001720 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001721 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 return rc;
1723}
1724
Jeff Laytondf2cf172010-02-12 07:44:16 -05001725static bool
1726cifs_inode_needs_reval(struct inode *inode)
1727{
1728 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301729 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001730
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001731 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001732 return false;
1733
1734 if (!lookupCacheEnabled)
1735 return true;
1736
1737 if (cifs_i->time == 0)
1738 return true;
1739
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301740 if (!time_in_range(jiffies, cifs_i->time,
1741 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001742 return true;
1743
Jeff Laytondb192722010-05-17 14:51:49 -04001744 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301745 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001746 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1747 return true;
1748
Jeff Laytondf2cf172010-02-12 07:44:16 -05001749 return false;
1750}
1751
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301752/*
1753 * Zap the cache. Called when invalid_mapping flag is set.
1754 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001755int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001756cifs_invalidate_mapping(struct inode *inode)
1757{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001758 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001759 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1760
1761 cifs_i->invalid_mapping = false;
1762
Jeff Laytondf2cf172010-02-12 07:44:16 -05001763 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001764 rc = invalidate_inode_pages2(inode->i_mapping);
1765 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001766 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1767 __func__, inode);
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001768 cifs_i->invalid_mapping = true;
1769 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001770 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001771
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301772 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001773 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001774}
1775
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001776int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001777{
1778 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001779 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001780 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001781
1782 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001783 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001784
Jeff Layton13cfb732010-09-29 19:51:11 -04001785 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001786 rc = cifs_get_file_info_unix(filp);
1787 else
1788 rc = cifs_get_file_info(filp);
1789
Jeff Laytonabab0952010-02-12 07:44:18 -05001790 return rc;
1791}
1792
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001793int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001795 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001796 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001797 struct inode *inode = dentry->d_inode;
1798 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001799 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
Jeff Laytondf2cf172010-02-12 07:44:16 -05001801 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 return -ENOENT;
1803
Jeff Laytondf2cf172010-02-12 07:44:16 -05001804 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001805 return rc;
1806
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001807 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808
1809 /* can not safely grab the rename sem here if rename calls revalidate
1810 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001811 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301813 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001814 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001816
Joe Perchesf96637b2013-05-04 22:12:25 -05001817 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1818 full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001819 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
Jeff Layton0d424ad2010-09-20 16:01:35 -07001821 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001822 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1823 else
1824 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1825 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001827out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001829 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 return rc;
1831}
1832
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001833int cifs_revalidate_file(struct file *filp)
1834{
1835 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001836 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001837
1838 rc = cifs_revalidate_file_attr(filp);
1839 if (rc)
1840 return rc;
1841
1842 if (CIFS_I(inode)->invalid_mapping)
1843 rc = cifs_invalidate_mapping(inode);
1844 return rc;
1845}
1846
1847/* revalidate a dentry's inode attributes */
1848int cifs_revalidate_dentry(struct dentry *dentry)
1849{
1850 int rc;
1851 struct inode *inode = dentry->d_inode;
1852
1853 rc = cifs_revalidate_dentry_attr(dentry);
1854 if (rc)
1855 return rc;
1856
1857 if (CIFS_I(inode)->invalid_mapping)
1858 rc = cifs_invalidate_mapping(inode);
1859 return rc;
1860}
1861
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001863 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001865 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001866 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001867 struct inode *inode = dentry->d_inode;
1868 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001869
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001870 /*
1871 * We need to be sure that all dirty pages are written and the server
1872 * has actual ctime, mtime and file length.
1873 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001874 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001875 inode->i_mapping->nrpages != 0) {
1876 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001877 if (rc) {
1878 mapping_set_error(inode->i_mapping, rc);
1879 return rc;
1880 }
Steve French5fe14c82006-11-07 19:26:33 +00001881 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001882
1883 rc = cifs_revalidate_dentry_attr(dentry);
1884 if (rc)
1885 return rc;
1886
1887 generic_fillattr(inode, stat);
1888 stat->blksize = CIFS_MAX_MSGSIZE;
1889 stat->ino = CIFS_I(inode)->uniqueid;
1890
1891 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001892 * If on a multiuser mount without unix extensions or cifsacl being
1893 * enabled, and the admin hasn't overridden them, set the ownership
1894 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001895 */
1896 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001897 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001898 !tcon->unix_ext) {
1899 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1900 stat->uid = current_fsuid();
1901 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1902 stat->gid = current_fsgid();
1903 }
1904 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905}
1906
1907static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1908{
1909 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1910 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1911 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 int rc = 0;
1913
1914 page = grab_cache_page(mapping, index);
1915 if (!page)
1916 return -ENOMEM;
1917
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001918 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 unlock_page(page);
1920 page_cache_release(page);
1921 return rc;
1922}
1923
Christoph Hellwig1b947462010-07-18 17:51:21 -04001924static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001925{
Steve Frenchba6a46a2007-02-26 20:06:29 +00001926 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00001927 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001928 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001929
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001930 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00001931}
1932
Jeff Layton8efdbde2008-07-23 21:28:12 +00001933static int
1934cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001935 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00001936{
1937 int rc;
1938 struct cifsFileInfo *open_file;
1939 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1940 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001941 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001942 struct cifs_tcon *tcon = NULL;
1943 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001944 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001945
1946 /*
1947 * To avoid spurious oplock breaks from server, in the case of
1948 * inodes that we already have open, avoid doing path based
1949 * setting of file size if we can do it by handle.
1950 * This keeps our caching token (oplock) and avoids timeouts
1951 * when the local oplock break takes longer to flush
1952 * writebehind data than the SMB timeout for the SetPathInfo
1953 * request would allow
1954 */
Jeff Layton6508d902010-09-29 19:51:11 -04001955 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001956 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001957 tcon = tlink_tcon(open_file->tlink);
1958 server = tcon->ses->server;
1959 if (server->ops->set_file_size)
1960 rc = server->ops->set_file_size(xid, tcon, open_file,
1961 attrs->ia_size, false);
1962 else
1963 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001964 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05001965 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001966 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1967 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001968
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001969 io_parms.netfid = open_file->fid.netfid;
1970 io_parms.pid = open_file->pid;
1971 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001972 io_parms.offset = 0;
1973 io_parms.length = attrs->ia_size;
1974 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1975 NULL, NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001976 cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001977 }
1978 } else
1979 rc = -EINVAL;
1980
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001981 if (!rc)
1982 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07001983
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001984 if (tcon == NULL) {
1985 tlink = cifs_sb_tlink(cifs_sb);
1986 if (IS_ERR(tlink))
1987 return PTR_ERR(tlink);
1988 tcon = tlink_tcon(tlink);
1989 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001990 }
1991
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001992 /*
1993 * Set file size by pathname rather than by handle either because no
1994 * valid, writeable file handle for it was found or because there was
1995 * an error setting it by handle.
1996 */
1997 if (server->ops->set_path_size)
1998 rc = server->ops->set_path_size(xid, tcon, full_path,
1999 attrs->ia_size, cifs_sb, false);
2000 else
2001 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002002 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002003 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
2004 __u16 netfid;
2005 int oplock = 0;
2006
2007 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
2008 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
2009 &oplock, NULL, cifs_sb->local_nls,
2010 cifs_sb->mnt_cifs_flags &
2011 CIFS_MOUNT_MAP_SPECIAL_CHR);
2012 if (rc == 0) {
2013 unsigned int bytes_written;
2014
2015 io_parms.netfid = netfid;
2016 io_parms.pid = current->tgid;
2017 io_parms.tcon = tcon;
2018 io_parms.offset = 0;
2019 io_parms.length = attrs->ia_size;
2020 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
2021 NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05002022 cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07002023 CIFSSMBClose(xid, tcon, netfid);
2024 }
2025 }
2026 if (tlink)
2027 cifs_put_tlink(tlink);
2028
2029set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002030 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002031 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002032 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002033 cifs_truncate_page(inode->i_mapping, inode->i_size);
2034 }
2035
2036 return rc;
2037}
2038
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002039static int
2040cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2041{
2042 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002043 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002044 char *full_path = NULL;
2045 struct inode *inode = direntry->d_inode;
2046 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2047 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002048 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002049 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002050 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002051 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002052
Joe Perchesf96637b2013-05-04 22:12:25 -05002053 cifs_dbg(FYI, "setattr_unix on file %s attrs->ia_valid=0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002054 direntry->d_name.name, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002055
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002056 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002057
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002058 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2059 attrs->ia_valid |= ATTR_FORCE;
2060
2061 rc = inode_change_ok(inode, attrs);
2062 if (rc < 0)
2063 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002064
2065 full_path = build_path_from_dentry(direntry);
2066 if (full_path == NULL) {
2067 rc = -ENOMEM;
2068 goto out;
2069 }
2070
Jeff Layton0f4d6342009-03-26 13:35:37 -04002071 /*
2072 * Attempt to flush data before changing attributes. We need to do
2073 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2074 * ownership or mode then we may also need to do this. Here, we take
2075 * the safe way out and just do the flush on all setattr requests. If
2076 * the flush returns error, store it to report later and continue.
2077 *
2078 * BB: This should be smarter. Why bother flushing pages that
2079 * will be truncated anyway? Also, should we error out here if
2080 * the flush returns error?
2081 */
2082 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002083 mapping_set_error(inode->i_mapping, rc);
2084 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002085
2086 if (attrs->ia_valid & ATTR_SIZE) {
2087 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2088 if (rc != 0)
2089 goto out;
2090 }
2091
2092 /* skip mode change if it's just for clearing setuid/setgid */
2093 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2094 attrs->ia_valid &= ~ATTR_MODE;
2095
2096 args = kmalloc(sizeof(*args), GFP_KERNEL);
2097 if (args == NULL) {
2098 rc = -ENOMEM;
2099 goto out;
2100 }
2101
2102 /* set up the struct */
2103 if (attrs->ia_valid & ATTR_MODE)
2104 args->mode = attrs->ia_mode;
2105 else
2106 args->mode = NO_CHANGE_64;
2107
2108 if (attrs->ia_valid & ATTR_UID)
2109 args->uid = attrs->ia_uid;
2110 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002111 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002112
2113 if (attrs->ia_valid & ATTR_GID)
2114 args->gid = attrs->ia_gid;
2115 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002116 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002117
2118 if (attrs->ia_valid & ATTR_ATIME)
2119 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2120 else
2121 args->atime = NO_CHANGE_64;
2122
2123 if (attrs->ia_valid & ATTR_MTIME)
2124 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2125 else
2126 args->mtime = NO_CHANGE_64;
2127
2128 if (attrs->ia_valid & ATTR_CTIME)
2129 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2130 else
2131 args->ctime = NO_CHANGE_64;
2132
2133 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002134 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002135 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002136 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002137 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002138 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002139 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002140 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002141 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002142 tlink = cifs_sb_tlink(cifs_sb);
2143 if (IS_ERR(tlink)) {
2144 rc = PTR_ERR(tlink);
2145 goto out;
2146 }
2147 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002148 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002149 cifs_sb->local_nls,
2150 cifs_sb->mnt_cifs_flags &
2151 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002152 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002153 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002154
Christoph Hellwig10257742010-06-04 11:30:02 +02002155 if (rc)
2156 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002157
Christoph Hellwig10257742010-06-04 11:30:02 +02002158 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002159 attrs->ia_size != i_size_read(inode))
2160 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002161
2162 setattr_copy(inode, attrs);
2163 mark_inode_dirty(inode);
2164
2165 /* force revalidate when any of these times are set since some
2166 of the fs types (eg ext3, fat) do not have fine enough
2167 time granularity to match protocol, and we do not have a
2168 a way (yet) to query the server fs's time granularity (and
2169 whether it rounds times down).
2170 */
2171 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2172 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002173out:
2174 kfree(args);
2175 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002176 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002177 return rc;
2178}
2179
Jeff Layton0510eeb2008-08-02 07:26:12 -04002180static int
2181cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002183 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002184 kuid_t uid = INVALID_UID;
2185 kgid_t gid = INVALID_GID;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002186 struct inode *inode = direntry->d_inode;
2187 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002188 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 char *full_path = NULL;
2190 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002191 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002192 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002193
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002194 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
Joe Perchesf96637b2013-05-04 22:12:25 -05002196 cifs_dbg(FYI, "setattr on file %s attrs->iavalid 0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002197 direntry->d_name.name, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002198
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002199 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2200 attrs->ia_valid |= ATTR_FORCE;
2201
2202 rc = inode_change_ok(inode, attrs);
2203 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002204 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002205 return rc;
Steve French6473a552005-11-29 20:20:10 -08002206 }
Steve French50c2f752007-07-13 00:33:32 +00002207
Steve French7f573562005-08-30 11:32:14 -07002208 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302210 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002211 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302212 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
Jeff Layton0f4d6342009-03-26 13:35:37 -04002215 /*
2216 * Attempt to flush data before changing attributes. We need to do
2217 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2218 * ownership or mode then we may also need to do this. Here, we take
2219 * the safe way out and just do the flush on all setattr requests. If
2220 * the flush returns error, store it to report later and continue.
2221 *
2222 * BB: This should be smarter. Why bother flushing pages that
2223 * will be truncated anyway? Also, should we error out here if
2224 * the flush returns error?
2225 */
2226 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002227 mapping_set_error(inode->i_mapping, rc);
2228 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002229
Steve French50531442008-03-14 19:21:31 +00002230 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002231 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2232 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002233 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002235
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002236 if (attrs->ia_valid & ATTR_UID)
2237 uid = attrs->ia_uid;
2238
2239 if (attrs->ia_valid & ATTR_GID)
2240 gid = attrs->ia_gid;
2241
2242#ifdef CONFIG_CIFS_ACL
2243 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002244 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002245 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2246 uid, gid);
2247 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002248 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2249 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002250 goto cifs_setattr_exit;
2251 }
2252 }
2253 } else
2254#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002255 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002256 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
Jeff Laytond32c4f22007-10-18 03:05:22 -07002258 /* skip mode change if it's just for clearing setuid/setgid */
2259 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2260 attrs->ia_valid &= ~ATTR_MODE;
2261
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002264 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002265#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002266 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002267 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002268 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002269 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002270 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2271 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002272 goto cifs_setattr_exit;
2273 }
2274 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002275#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002276 if (((mode & S_IWUGO) == 0) &&
2277 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002278
2279 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2280
Jeff Layton51328612008-05-22 09:33:34 -04002281 /* fix up mode if we're not using dynperm */
2282 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2283 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2284 } else if ((mode & S_IWUGO) &&
2285 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002286
2287 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2288 /* Attributes of 0 are ignored */
2289 if (dosattr == 0)
2290 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002291
2292 /* reset local inode permissions to normal */
2293 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2294 attrs->ia_mode &= ~(S_IALLUGO);
2295 if (S_ISDIR(inode->i_mode))
2296 attrs->ia_mode |=
2297 cifs_sb->mnt_dir_mode;
2298 else
2299 attrs->ia_mode |=
2300 cifs_sb->mnt_file_mode;
2301 }
2302 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2303 /* ignore mode change - ATTR_READONLY hasn't changed */
2304 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 }
2307
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002308 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2309 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2310 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2311 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312
Steve Frenche30dcf32005-09-20 20:49:16 -07002313 /* Even if error on time set, no sense failing the call if
2314 the server would set the time to a reasonable value anyway,
2315 and this check ensures that we are not being called from
2316 sys_utimes in which case we ought to fail the call back to
2317 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002318 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002319 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002320 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 }
2322
2323 /* do not need local check to inode_check_ok since the server does
2324 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002325 if (rc)
2326 goto cifs_setattr_exit;
2327
2328 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002329 attrs->ia_size != i_size_read(inode))
2330 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002331
2332 setattr_copy(inode, attrs);
2333 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002334
Steve Frenche30dcf32005-09-20 20:49:16 -07002335cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002337 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 return rc;
2339}
2340
Jeff Layton0510eeb2008-08-02 07:26:12 -04002341int
2342cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2343{
2344 struct inode *inode = direntry->d_inode;
2345 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002346 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002347
2348 if (pTcon->unix_ext)
2349 return cifs_setattr_unix(direntry, attrs);
2350
2351 return cifs_setattr_nounix(direntry, attrs);
2352
2353 /* BB: add cifs_setattr_legacy for really old servers */
2354}
2355
Steve French99ee4db2007-02-27 05:35:17 +00002356#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357void cifs_delete_inode(struct inode *inode)
2358{
Joe Perchesf96637b2013-05-04 22:12:25 -05002359 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 /* may have to add back in if and when safe distributed caching of
2361 directories added e.g. via FindNotify */
2362}
Steve French99ee4db2007-02-27 05:35:17 +00002363#endif