blob: f9ff9c173f78ad6a8abcc6afb56849109dbfd515 [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
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400123/* populate an inode with info from a cifs_fattr struct */
124void
125cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
Christoph Hellwig75f12982008-02-25 20:25:21 +0000126{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400127 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400128 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000129
Jeff Laytondf2cf172010-02-12 07:44:16 -0500130 cifs_revalidate_cache(inode, fattr);
131
Steve Frenchb7ca6922012-08-03 08:43:01 -0500132 spin_lock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400133 inode->i_atime = fattr->cf_atime;
134 inode->i_mtime = fattr->cf_mtime;
135 inode->i_ctime = fattr->cf_ctime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400136 inode->i_rdev = fattr->cf_rdev;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200137 set_nlink(inode, fattr->cf_nlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400138 inode->i_uid = fattr->cf_uid;
139 inode->i_gid = fattr->cf_gid;
140
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400141 /* if dynperm is set, don't clobber existing mode */
142 if (inode->i_state & I_NEW ||
143 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
144 inode->i_mode = fattr->cf_mode;
145
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400146 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400147
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400148 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
149 cifs_i->time = 0;
150 else
151 cifs_i->time = jiffies;
152
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400153 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000154
Jeff Layton835a36c2010-02-10 16:21:33 -0500155 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000156 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400157 * Can't safely change the file size here if the client is writing to
158 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000159 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400160 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
161 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000162
163 /*
164 * i_blocks is not related to (i_size / i_blksize),
165 * but instead 512 byte (2**9) size is required for
166 * calculating num blocks.
167 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400168 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000169 }
170 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400171
David Howells01c64fe2011-01-14 18:45:47 +0000172 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
173 inode->i_flags |= S_AUTOMOUNT;
Jeff Laytonc2b93e02013-05-07 11:28:31 -0400174 if (inode->i_state & I_NEW)
175 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000176}
177
Jeff Layton4065c802010-05-17 07:18:58 -0400178void
179cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
180{
181 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
182
183 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
184 return;
185
186 fattr->cf_uniqueid = iunique(sb, ROOT_I);
187}
188
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400189/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
190void
191cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
192 struct cifs_sb_info *cifs_sb)
193{
194 memset(fattr, 0, sizeof(*fattr));
195 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
196 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
197 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
198
199 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
200 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
201 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
202 fattr->cf_mode = le64_to_cpu(info->Permissions);
203
204 /*
205 * Since we set the inode type below we need to mask off
206 * to avoid strange results if bits set above.
207 */
208 fattr->cf_mode &= ~S_IFMT;
209 switch (le32_to_cpu(info->Type)) {
210 case UNIX_FILE:
211 fattr->cf_mode |= S_IFREG;
212 fattr->cf_dtype = DT_REG;
213 break;
214 case UNIX_SYMLINK:
215 fattr->cf_mode |= S_IFLNK;
216 fattr->cf_dtype = DT_LNK;
217 break;
218 case UNIX_DIR:
219 fattr->cf_mode |= S_IFDIR;
220 fattr->cf_dtype = DT_DIR;
221 break;
222 case UNIX_CHARDEV:
223 fattr->cf_mode |= S_IFCHR;
224 fattr->cf_dtype = DT_CHR;
225 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
226 le64_to_cpu(info->DevMinor) & MINORMASK);
227 break;
228 case UNIX_BLOCKDEV:
229 fattr->cf_mode |= S_IFBLK;
230 fattr->cf_dtype = DT_BLK;
231 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
232 le64_to_cpu(info->DevMinor) & MINORMASK);
233 break;
234 case UNIX_FIFO:
235 fattr->cf_mode |= S_IFIFO;
236 fattr->cf_dtype = DT_FIFO;
237 break;
238 case UNIX_SOCKET:
239 fattr->cf_mode |= S_IFSOCK;
240 fattr->cf_dtype = DT_SOCK;
241 break;
242 default:
243 /* safest to call it a file if we do not know */
244 fattr->cf_mode |= S_IFREG;
245 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500246 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400247 break;
248 }
249
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800250 fattr->cf_uid = cifs_sb->mnt_uid;
251 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
252 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800253 if (id < ((uid_t)-1)) {
254 kuid_t uid = make_kuid(&init_user_ns, id);
255 if (uid_valid(uid))
256 fattr->cf_uid = uid;
257 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800258 }
259
260 fattr->cf_gid = cifs_sb->mnt_gid;
261 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
262 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800263 if (id < ((gid_t)-1)) {
264 kgid_t gid = make_kgid(&init_user_ns, id);
265 if (gid_valid(gid))
266 fattr->cf_gid = gid;
267 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800268 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400269
270 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
271}
Steve Frenchb9a32602008-05-20 21:52:32 +0000272
273/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400274 * Fill a cifs_fattr struct with fake inode info.
275 *
276 * Needed to setup cifs_fattr data for the directory which is the
277 * junction to the new submount (ie to setup the fake directory
278 * which represents a DFS referral).
Steve Frenchb9a32602008-05-20 21:52:32 +0000279 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000280static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400281cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000282{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400283 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000284
Joe Perchesf96637b2013-05-04 22:12:25 -0500285 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000286
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400287 memset(fattr, 0, sizeof(*fattr));
288 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
289 fattr->cf_uid = cifs_sb->mnt_uid;
290 fattr->cf_gid = cifs_sb->mnt_gid;
291 fattr->cf_atime = CURRENT_TIME;
292 fattr->cf_ctime = CURRENT_TIME;
293 fattr->cf_mtime = CURRENT_TIME;
294 fattr->cf_nlink = 2;
295 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000296}
297
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700298static int
299cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500300{
301 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400302 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500303 FILE_UNIX_BASIC_INFO find_data;
304 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500305 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500306 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700307 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000308 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500309
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400310 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700311 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500312 if (!rc) {
313 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
314 } else if (rc == -EREMOTE) {
315 cifs_create_dfs_fattr(&fattr, inode->i_sb);
316 rc = 0;
317 }
318
319 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400320 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500321 return rc;
322}
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400325 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400326 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400328 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000329 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400330 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000331 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400332 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
Joe Perchesf96637b2013-05-04 22:12:25 -0500335 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000336
Jeff Layton7ffec372010-09-29 19:51:11 -0400337 tlink = cifs_sb_tlink(cifs_sb);
338 if (IS_ERR(tlink))
339 return PTR_ERR(tlink);
340 tcon = tlink_tcon(tlink);
341
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400343 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Steve French737b7582005-04-28 22:41:06 -0700344 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
345 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400346 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400347
348 if (!rc) {
349 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
350 } else if (rc == -EREMOTE) {
351 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700352 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400353 } else {
354 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000355 }
356
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200357 /* check for Minshall+French symlinks */
358 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
359 int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
360 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500361 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200362 }
363
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400364 if (*pinode == NULL) {
365 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400366 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400367 *pinode = cifs_iget(sb, &fattr);
368 if (!*pinode)
369 rc = -ENOMEM;
370 } else {
371 /* we already have inode, update it */
372 cifs_fattr_to_inode(*pinode, &fattr);
373 }
Steve French0e4bbde2008-05-20 19:50:46 +0000374
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 return rc;
376}
377
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400378static int
379cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400380 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800381{
382 int rc;
Steve French4b18f2a2008-04-29 00:06:05 +0000383 int oplock = 0;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800384 __u16 netfid;
Jeff Layton7ffec372010-09-29 19:51:11 -0400385 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000386 struct cifs_tcon *tcon;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000387 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800388 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800389 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000390 char *pbuf;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800391
392 pbuf = buf;
393
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400394 fattr->cf_mode &= ~S_IFMT;
395
396 if (fattr->cf_eof == 0) {
397 fattr->cf_mode |= S_IFIFO;
398 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800399 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400400 } else if (fattr->cf_eof < 8) {
401 fattr->cf_mode |= S_IFREG;
402 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800403 return -EINVAL; /* EOPNOTSUPP? */
404 }
Steve French50c2f752007-07-13 00:33:32 +0000405
Jeff Layton7ffec372010-09-29 19:51:11 -0400406 tlink = cifs_sb_tlink(cifs_sb);
407 if (IS_ERR(tlink))
408 return PTR_ERR(tlink);
409 tcon = tlink_tcon(tlink);
410
411 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800412 CREATE_NOT_DIR, &netfid, &oplock, NULL,
413 cifs_sb->local_nls,
414 cifs_sb->mnt_cifs_flags &
415 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000416 if (rc == 0) {
Steve Frenchec637e32005-12-12 20:53:18 -0800417 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800418 /* Read header */
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000419 io_parms.netfid = netfid;
420 io_parms.pid = current->tgid;
421 io_parms.tcon = tcon;
422 io_parms.offset = 0;
423 io_parms.length = 24;
424 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
425 &buf_type);
Steve French4523cc32007-04-30 20:13:06 +0000426 if ((rc == 0) && (bytes_read >= 8)) {
427 if (memcmp("IntxBLK", pbuf, 8) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500428 cifs_dbg(FYI, "Block device\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400429 fattr->cf_mode |= S_IFBLK;
430 fattr->cf_dtype = DT_BLK;
Steve French4523cc32007-04-30 20:13:06 +0000431 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800432 /* we have enough to decode dev num */
433 __u64 mjr; /* major */
434 __u64 mnr; /* minor */
435 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
436 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400437 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve French86c96b42005-11-18 20:25:31 -0800438 }
Steve French4523cc32007-04-30 20:13:06 +0000439 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500440 cifs_dbg(FYI, "Char device\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400441 fattr->cf_mode |= S_IFCHR;
442 fattr->cf_dtype = DT_CHR;
Steve French4523cc32007-04-30 20:13:06 +0000443 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800444 /* we have enough to decode dev num */
445 __u64 mjr; /* major */
446 __u64 mnr; /* minor */
447 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
448 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400449 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000450 }
Steve French4523cc32007-04-30 20:13:06 +0000451 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500452 cifs_dbg(FYI, "Symlink\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400453 fattr->cf_mode |= S_IFLNK;
454 fattr->cf_dtype = DT_LNK;
Steve French86c96b42005-11-18 20:25:31 -0800455 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400456 fattr->cf_mode |= S_IFREG; /* file? */
457 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000458 rc = -EOPNOTSUPP;
Steve French86c96b42005-11-18 20:25:31 -0800459 }
Steve French3020a1f2005-11-18 11:31:10 -0800460 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400461 fattr->cf_mode |= S_IFREG; /* then it is a file */
462 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000463 rc = -EOPNOTSUPP; /* or some unknown SFU type */
464 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400465 CIFSSMBClose(xid, tcon, netfid);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800466 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400467 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800468 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800469}
470
Steve French9e294f12005-11-17 16:59:21 -0800471#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
472
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400473/*
474 * Fetch mode bits as provided by SFU.
475 *
476 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
477 */
478static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400479 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800480{
Steve French3020a1f2005-11-18 11:31:10 -0800481#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800482 ssize_t rc;
483 char ea_value[4];
484 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400485 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000486 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800487
Jeff Layton7ffec372010-09-29 19:51:11 -0400488 tlink = cifs_sb_tlink(cifs_sb);
489 if (IS_ERR(tlink))
490 return PTR_ERR(tlink);
491 tcon = tlink_tcon(tlink);
492
493 rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400494 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
495 cifs_sb->mnt_cifs_flags &
496 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400497 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000498 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800499 return (int)rc;
500 else if (rc > 3) {
501 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400502 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500503 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
504 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400505 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500506 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800507 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400508
509 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800510#else
511 return -EOPNOTSUPP;
512#endif
Steve French9e294f12005-11-17 16:59:21 -0800513}
514
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400515/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000516static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400517cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
518 struct cifs_sb_info *cifs_sb, bool adjust_tz)
Steve Frenchb9a32602008-05-20 21:52:32 +0000519{
Steve French96daf2b2011-05-27 04:34:02 +0000520 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700521
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400522 memset(fattr, 0, sizeof(*fattr));
523 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
524 if (info->DeletePending)
525 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000526
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400527 if (info->LastAccessTime)
528 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
529 else
530 fattr->cf_atime = CURRENT_TIME;
531
532 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
533 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
534
535 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700536 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
537 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400538 }
539
540 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
541 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500542 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400543
544 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
545 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
546 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300547 /*
548 * Server can return wrong NumberOfLinks value for directories
549 * when Unix extensions are disabled - fake it.
550 */
551 fattr->cf_nlink = 2;
Pavel Shilovskyb42bf882013-08-14 19:25:21 +0400552 } else if (fattr->cf_cifsattrs & ATTR_REPARSE) {
553 fattr->cf_mode = S_IFLNK;
554 fattr->cf_dtype = DT_LNK;
555 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400556 } else {
557 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
558 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400559
Jeff Laytond0c280d2009-07-09 01:46:44 -0400560 /* clear write bits if ATTR_READONLY is set */
561 if (fattr->cf_cifsattrs & ATTR_READONLY)
562 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400563
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300564 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Steve French6658b9f2013-07-04 14:38:48 -0500565 if (fattr->cf_nlink < 1) {
566 cifs_dbg(1, "replacing bogus file nlink value %u\n",
567 fattr->cf_nlink);
568 fattr->cf_nlink = 1;
569 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300570 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400571
572 fattr->cf_uid = cifs_sb->mnt_uid;
573 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000574}
575
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700576static int
577cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500578{
579 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400580 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500581 FILE_ALL_INFO find_data;
582 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500583 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500584 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700585 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000586 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700587 struct TCP_Server_Info *server = tcon->ses->server;
588
589 if (!server->ops->query_file_info)
590 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500591
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400592 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700593 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400594 switch (rc) {
595 case 0:
596 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
597 break;
598 case -EREMOTE:
599 cifs_create_dfs_fattr(&fattr, inode->i_sb);
600 rc = 0;
601 break;
602 case -EOPNOTSUPP:
603 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500604 /*
605 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000606 * for now, just skip revalidating and mark inode for
607 * immediate reval.
608 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500609 rc = 0;
610 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400611 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500612 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400613 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500614
615 /*
616 * don't bother with SFU junk here -- just mark inode as needing
617 * revalidation.
618 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500619 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
620 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
621 cifs_fattr_to_inode(inode, &fattr);
622cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400623 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500624 return rc;
625}
626
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400627int
628cifs_get_inode_info(struct inode **inode, const char *full_path,
629 FILE_ALL_INFO *data, struct super_block *sb, int xid,
630 const __u16 *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500632 bool validinum = false;
633 __u16 srchflgs;
634 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400635 struct cifs_tcon *tcon;
636 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400637 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400640 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400641 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500642 struct cifs_search_info *srchinf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Jeff Layton7ffec372010-09-29 19:51:11 -0400644 tlink = cifs_sb_tlink(cifs_sb);
645 if (IS_ERR(tlink))
646 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400647 tcon = tlink_tcon(tlink);
648 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400649
Joe Perchesf96637b2013-05-04 22:12:25 -0500650 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400652 if ((data == NULL) && (*inode != NULL)) {
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400653 if (CIFS_CACHE_READ(CIFS_I(*inode))) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500654 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400655 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 }
657 }
658
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400659 /* if inode info is not passed, get it from server */
660 if (data == NULL) {
661 if (!server->ops->query_path_info) {
662 rc = -ENOSYS;
663 goto cgii_exit;
664 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400666 if (buf == NULL) {
667 rc = -ENOMEM;
668 goto cgii_exit;
669 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400670 data = (FILE_ALL_INFO *)buf;
671 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
672 data, &adjust_tz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400674
675 if (!rc) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400676 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb,
677 adjust_tz);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400678 } else if (rc == -EREMOTE) {
679 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000680 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500681 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
682 srchinf = kzalloc(sizeof(struct cifs_search_info),
683 GFP_KERNEL);
684 if (srchinf == NULL) {
685 rc = -ENOMEM;
686 goto cgii_exit;
687 }
688
689 srchinf->endOfSearch = false;
690 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
691
692 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
693 CIFS_SEARCH_CLOSE_AT_END |
694 CIFS_SEARCH_BACKUP_SEARCH;
695
696 rc = CIFSFindFirst(xid, tcon, full_path,
697 cifs_sb, NULL, srchflgs, srchinf, false);
698 if (!rc) {
699 data =
700 (FILE_ALL_INFO *)srchinf->srch_entries_start;
701
702 cifs_dir_info_to_fattr(&fattr,
703 (FILE_DIRECTORY_INFO *)data, cifs_sb);
704 fattr.cf_uniqueid = le64_to_cpu(
705 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
706 validinum = true;
707
708 cifs_buf_release(srchinf->ntwrk_buf_start);
709 }
710 kfree(srchinf);
711 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000712 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400714 /*
715 * If an inode wasn't passed in, then get the inode number
716 *
717 * Is an i_ino of zero legal? Can we use that to check if the server
718 * supports returning inode numbers? Are there other sanity checks we
719 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400720 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400721 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000722 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500723 if (validinum == false) {
724 if (server->ops->get_srv_inum)
725 tmprc = server->ops->get_srv_inum(xid,
726 tcon, cifs_sb, full_path,
727 &fattr.cf_uniqueid, data);
728 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500729 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
730 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500731 fattr.cf_uniqueid = iunique(sb, ROOT_I);
732 cifs_autodisable_serverino(cifs_sb);
733 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500734 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500735 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400736 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500737 } else
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400738 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000739
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400740 /* query for SFU type info if supported and needed */
741 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
742 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
743 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
744 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500745 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000746 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000747
Jeff Layton79df1ba2010-12-06 12:52:08 -0500748#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000749 /* fill in 0777 bits from ACL */
750 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400751 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600752 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500753 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
754 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600755 goto cgii_exit;
756 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000757 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500758#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400759
760 /* fill in remaining high mode bits e.g. SUID, VTX */
761 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
762 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
763
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200764 /* check for Minshall+French symlinks */
765 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
766 tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
767 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500768 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200769 }
770
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400771 if (!*inode) {
772 *inode = cifs_iget(sb, &fattr);
773 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400774 rc = -ENOMEM;
775 } else {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400776 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000777 }
778
Igor Mammedov79626702008-03-09 03:44:18 +0000779cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400781 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 return rc;
783}
784
Steve French7f8ed422007-09-28 22:28:55 +0000785static const struct inode_operations cifs_ipc_inode_ops = {
786 .lookup = cifs_lookup,
787};
788
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400789static int
790cifs_find_inode(struct inode *inode, void *opaque)
791{
792 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
793
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400794 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400795 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
796 return 0;
797
Jeff Layton20054bd2011-01-07 11:30:27 -0500798 /* use createtime like an i_generation field */
799 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
800 return 0;
801
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400802 /* don't match inode of different type */
803 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
804 return 0;
805
Jeff Layton5acfec22010-08-02 17:43:54 -0400806 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400807 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400808 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400809
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400810 return 1;
811}
812
813static int
814cifs_init_inode(struct inode *inode, void *opaque)
815{
816 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
817
818 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500819 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400820 return 0;
821}
822
Jeff Layton5acfec22010-08-02 17:43:54 -0400823/*
824 * walk dentry list for an inode and report whether it has aliases that
825 * are hashed. We use this to determine if a directory inode can actually
826 * be used.
827 */
828static bool
829inode_has_hashed_dentries(struct inode *inode)
830{
831 struct dentry *dentry;
832
Nick Piggin873feea2011-01-07 17:50:06 +1100833 spin_lock(&inode->i_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800834 hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400835 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100836 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400837 return true;
838 }
839 }
Nick Piggin873feea2011-01-07 17:50:06 +1100840 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400841 return false;
842}
843
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400844/* Given fattrs, get a corresponding inode */
845struct inode *
846cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
847{
848 unsigned long hash;
849 struct inode *inode;
850
Jeff Layton3d694382010-05-11 14:59:55 -0400851retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -0500852 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400853
854 /* hash down to 32-bits on 32-bit arch */
855 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
856
857 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400858 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400859 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400860 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400861 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400862
863 if (inode_has_hashed_dentries(inode)) {
864 cifs_autodisable_serverino(CIFS_SB(sb));
865 iput(inode);
866 fattr->cf_uniqueid = iunique(sb, ROOT_I);
867 goto retry_iget5_locked;
868 }
Jeff Layton3d694382010-05-11 14:59:55 -0400869 }
870
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400871 cifs_fattr_to_inode(inode, fattr);
872 if (sb->s_flags & MS_NOATIME)
873 inode->i_flags |= S_NOATIME | S_NOCMTIME;
874 if (inode->i_state & I_NEW) {
875 inode->i_ino = hash;
Jeff Layton522440e2010-09-29 09:49:54 -0400876 if (S_ISREG(inode->i_mode))
877 inode->i_data.backing_dev_info = sb->s_bdi;
Steve French0ccd4802010-07-16 04:31:02 +0000878#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530879 /* initialize per-inode cache cookie pointer */
880 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000881#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400882 unlock_new_inode(inode);
883 }
884 }
885
886 return inode;
887}
888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600890struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400892 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700893 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400894 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800895 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000896 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800897
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400898 xid = get_xid();
Jeff Layton0d424ad2010-09-20 16:01:35 -0700899 if (tcon->unix_ext)
Steve Frenchf87d39d2011-05-27 03:50:55 +0000900 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400901 else
Steve Frenchf87d39d2011-05-27 03:50:55 +0000902 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400903
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000904 if (!inode) {
905 inode = ERR_PTR(rc);
906 goto out;
907 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400908
Steve French0ccd4802010-07-16 04:31:02 +0000909#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530910 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700911 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000912#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530913
Jeff Layton0d424ad2010-09-20 16:01:35 -0700914 if (rc && tcon->ipc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500915 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -0500916 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +0000917 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200918 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +0000919 inode->i_op = &cifs_ipc_inode_ops;
920 inode->i_fop = &simple_dir_operations;
921 inode->i_uid = cifs_sb->mnt_uid;
922 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -0500923 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +0000924 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800925 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000926 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000927 }
928
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000929out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400930 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -0800931 * TODO: This is no longer true
932 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400933 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -0800934 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935}
936
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700937int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400938cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700939 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +0000940{
Steve French388e57b2008-09-16 23:50:58 +0000941 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +0000942 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700943 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +0000944 FILE_BASIC_INFO info_buf;
945
Steve French1adcb712009-02-25 14:19:56 +0000946 if (attrs == NULL)
947 return -EINVAL;
948
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700949 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
950 if (!server->ops->set_file_info)
951 return -ENOSYS;
952
Steve French388e57b2008-09-16 23:50:58 +0000953 if (attrs->ia_valid & ATTR_ATIME) {
954 set_time = true;
955 info_buf.LastAccessTime =
956 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
957 } else
958 info_buf.LastAccessTime = 0;
959
960 if (attrs->ia_valid & ATTR_MTIME) {
961 set_time = true;
962 info_buf.LastWriteTime =
963 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
964 } else
965 info_buf.LastWriteTime = 0;
966
967 /*
968 * Samba throws this field away, but windows may actually use it.
969 * Do not set ctime unless other time stamps are changed explicitly
970 * (i.e. by utimes()) since we would then have a mix of client and
971 * server times.
972 */
973 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500974 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +0000975 info_buf.ChangeTime =
976 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
977 } else
978 info_buf.ChangeTime = 0;
979
980 info_buf.CreationTime = 0; /* don't change */
981 info_buf.Attributes = cpu_to_le32(dosattr);
982
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700983 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +0000984}
985
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400986/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700987 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400988 * and rename it to a random name that hopefully won't conflict with
989 * anything else.
990 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700991int
992cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
993 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400994{
995 int oplock = 0;
996 int rc;
997 __u16 netfid;
Steve French32709582008-10-20 00:44:19 +0000998 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400999 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1000 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001001 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001002 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001003 __u32 dosattr, origattr;
1004 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001005
Jeff Layton7ffec372010-09-29 19:51:11 -04001006 tlink = cifs_sb_tlink(cifs_sb);
1007 if (IS_ERR(tlink))
1008 return PTR_ERR(tlink);
1009 tcon = tlink_tcon(tlink);
1010
Sachin Prabhuc483a982013-03-05 19:25:56 +00001011 /*
1012 * We cannot rename the file if the server doesn't support
1013 * CAP_INFOLEVEL_PASSTHRU
1014 */
1015 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1016 rc = -EBUSY;
1017 goto out;
1018 }
1019
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001020 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001021 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001022 &netfid, &oplock, NULL, cifs_sb->local_nls,
1023 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1024 if (rc != 0)
1025 goto out;
1026
Steve French32709582008-10-20 00:44:19 +00001027 origattr = cifsInode->cifsAttrs;
1028 if (origattr == 0)
1029 origattr |= ATTR_NORMAL;
1030
1031 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001032 if (dosattr == 0)
1033 dosattr |= ATTR_NORMAL;
1034 dosattr |= ATTR_HIDDEN;
1035
Steve French32709582008-10-20 00:44:19 +00001036 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1037 if (dosattr != origattr) {
1038 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1039 if (info_buf == NULL) {
1040 rc = -ENOMEM;
1041 goto out_close;
1042 }
1043 info_buf->Attributes = cpu_to_le32(dosattr);
1044 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1045 current->tgid);
1046 /* although we would like to mark the file hidden
1047 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001048 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001049 cifsInode->cifsAttrs = dosattr;
1050 else
1051 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001052 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001053
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001054 /* rename the file */
1055 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001056 cifs_sb->mnt_cifs_flags &
1057 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French32709582008-10-20 00:44:19 +00001058 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001059 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001060 goto undo_setattr;
1061 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001062
Steve French32709582008-10-20 00:44:19 +00001063 /* try to set DELETE_ON_CLOSE */
1064 if (!cifsInode->delete_pending) {
1065 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
1066 current->tgid);
1067 /*
1068 * some samba versions return -ENOENT when we try to set the
1069 * file disposition here. Likely a samba bug, but work around
1070 * it for now. This means that some cifsXXX files may hang
1071 * around after they shouldn't.
1072 *
1073 * BB: remove this hack after more servers have the fix
1074 */
1075 if (rc == -ENOENT)
1076 rc = 0;
1077 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001078 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001079 goto undo_rename;
1080 }
1081 cifsInode->delete_pending = true;
1082 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001083
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001084out_close:
1085 CIFSSMBClose(xid, tcon, netfid);
1086out:
Steve French32709582008-10-20 00:44:19 +00001087 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001088 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001089 return rc;
Steve French32709582008-10-20 00:44:19 +00001090
1091 /*
1092 * reset everything back to the original state. Don't bother
1093 * dealing with errors here since we can't do anything about
1094 * them anyway.
1095 */
1096undo_rename:
1097 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
1098 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1099 CIFS_MOUNT_MAP_SPECIAL_CHR);
1100undo_setattr:
1101 if (dosattr != origattr) {
1102 info_buf->Attributes = cpu_to_le32(origattr);
1103 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1104 current->tgid))
1105 cifsInode->cifsAttrs = origattr;
1106 }
1107
1108 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001109}
1110
Steve Frenchb7ca6922012-08-03 08:43:01 -05001111/* copied from fs/nfs/dir.c with small changes */
1112static void
1113cifs_drop_nlink(struct inode *inode)
1114{
1115 spin_lock(&inode->i_lock);
1116 if (inode->i_nlink > 0)
1117 drop_nlink(inode);
1118 spin_unlock(&inode->i_lock);
1119}
Steve Frenchff694522009-04-20 19:45:13 +00001120
1121/*
1122 * If dentry->d_inode is null (usually meaning the cached dentry
1123 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001124 * if that fails we can not attempt the fall back mechanisms on EACCESS
1125 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001126 * unlink on negative dentries currently.
1127 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001128int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129{
1130 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001131 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001133 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001134 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001135 struct super_block *sb = dir->i_sb;
1136 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001137 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001138 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001139 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001140 struct iattr *attrs = NULL;
1141 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Joe Perchesf96637b2013-05-04 22:12:25 -05001143 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Jeff Layton7ffec372010-09-29 19:51:11 -04001145 tlink = cifs_sb_tlink(cifs_sb);
1146 if (IS_ERR(tlink))
1147 return PTR_ERR(tlink);
1148 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001149 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001150
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001151 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
Jeff Layton5f0319a2008-09-16 14:05:16 -04001153 /* Unlink can be called from rename so we can not take the
1154 * sb->s_vfs_rename_mutex here */
1155 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301157 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001158 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 }
Steve French2d785a52007-07-15 01:48:57 +00001160
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001161 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1162 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001163 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001164 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1165 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesf96637b2013-05-04 22:12:25 -05001166 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001167 if ((rc == 0) || (rc == -ENOENT))
1168 goto psx_del_no_retry;
1169 }
1170
Steve French60502472008-10-07 18:42:52 +00001171retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001172 if (!server->ops->unlink) {
1173 rc = -ENOSYS;
1174 goto psx_del_no_retry;
1175 }
1176
1177 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001178
Steve French2d785a52007-07-15 01:48:57 +00001179psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001181 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001182 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001184 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001185 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001186 if (server->ops->rename_pending_delete) {
1187 rc = server->ops->rename_pending_delete(full_path,
1188 dentry, xid);
1189 if (rc == 0)
1190 cifs_drop_nlink(inode);
1191 }
Steve Frenchff694522009-04-20 19:45:13 +00001192 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001193 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1194 if (attrs == NULL) {
1195 rc = -ENOMEM;
1196 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 }
Steve French388e57b2008-09-16 23:50:58 +00001198
1199 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001200 cifs_inode = CIFS_I(inode);
1201 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001202 if (origattr == 0)
1203 origattr |= ATTR_NORMAL;
1204 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001205 if (dosattr == 0)
1206 dosattr |= ATTR_NORMAL;
1207 dosattr |= ATTR_HIDDEN;
1208
1209 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001210 if (rc != 0)
1211 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001212
1213 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 }
Steve French60502472008-10-07 18:42:52 +00001215
1216 /* undo the setattr if we errored out and it's needed */
1217 if (rc != 0 && dosattr != 0)
1218 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1219
Steve French388e57b2008-09-16 23:50:58 +00001220out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001221 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001222 cifs_inode = CIFS_I(inode);
1223 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001224 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001225 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001226 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001227 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001228 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001229 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001230unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001232 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001233 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001234 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 return rc;
1236}
1237
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001238static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001239cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001240 const char *full_path, struct cifs_sb_info *cifs_sb,
1241 struct cifs_tcon *tcon, const unsigned int xid)
1242{
1243 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001244 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001245
1246 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001247 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001248 xid);
1249 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001250 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1251 xid, NULL);
1252
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001253 if (rc)
1254 return rc;
1255
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001256 /*
1257 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001258 * from the server or was set bogus. Also, since this is a brand new
1259 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001260 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001261 if (inode->i_nlink < 2)
1262 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001263 mode &= ~current_umask();
1264 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001265 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001266 mode |= S_ISGID;
1267
1268 if (tcon->unix_ext) {
1269 struct cifs_unix_set_info_args args = {
1270 .mode = mode,
1271 .ctime = NO_CHANGE_64,
1272 .atime = NO_CHANGE_64,
1273 .mtime = NO_CHANGE_64,
1274 .device = 0,
1275 };
1276 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001277 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001278 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001279 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001280 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001281 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001282 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001283 args.uid = INVALID_UID; /* no change */
1284 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001285 }
1286 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1287 cifs_sb->local_nls,
1288 cifs_sb->mnt_cifs_flags &
1289 CIFS_MOUNT_MAP_SPECIAL_CHR);
1290 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001291 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001292 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001293 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001294 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001295 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001296 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1297 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001298
Jeff Layton101b92d2012-09-19 06:22:45 -07001299 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1300 inode->i_uid = current_fsuid();
1301 if (inode->i_mode & S_ISGID)
1302 inode->i_gid = parent->i_gid;
1303 else
1304 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001305 }
1306 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001307 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001308 return rc;
1309}
1310
1311static int
1312cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1313 const char *full_path, struct cifs_sb_info *cifs_sb,
1314 struct cifs_tcon *tcon, const unsigned int xid)
1315{
1316 int rc = 0;
1317 u32 oplock = 0;
1318 FILE_UNIX_BASIC_INFO *info = NULL;
1319 struct inode *newinode = NULL;
1320 struct cifs_fattr fattr;
1321
1322 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1323 if (info == NULL) {
1324 rc = -ENOMEM;
1325 goto posix_mkdir_out;
1326 }
1327
1328 mode &= ~current_umask();
1329 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1330 NULL /* netfid */, info, &oplock, full_path,
1331 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1332 CIFS_MOUNT_MAP_SPECIAL_CHR);
1333 if (rc == -EOPNOTSUPP)
1334 goto posix_mkdir_out;
1335 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001336 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001337 d_drop(dentry);
1338 goto posix_mkdir_out;
1339 }
1340
1341 if (info->Type == cpu_to_le32(-1))
1342 /* no return info, go query for it */
1343 goto posix_mkdir_get_info;
1344 /*
1345 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1346 * need to set uid/gid.
1347 */
1348
1349 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1350 cifs_fill_uniqueid(inode->i_sb, &fattr);
1351 newinode = cifs_iget(inode->i_sb, &fattr);
1352 if (!newinode)
1353 goto posix_mkdir_get_info;
1354
1355 d_instantiate(dentry, newinode);
1356
1357#ifdef CONFIG_CIFS_DEBUG2
Joe Perchesf96637b2013-05-04 22:12:25 -05001358 cifs_dbg(FYI, "instantiated dentry %p %s to inode %p\n",
1359 dentry, dentry->d_name.name, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001360
1361 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001362 cifs_dbg(FYI, "unexpected number of links %d\n",
1363 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001364#endif
1365
1366posix_mkdir_out:
1367 kfree(info);
1368 return rc;
1369posix_mkdir_get_info:
1370 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1371 xid);
1372 goto posix_mkdir_out;
1373}
1374
Al Viro18bb1db2011-07-26 01:41:39 -04001375int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001377 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001378 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001380 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001381 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001382 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001383 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
Joe Perchesf96637b2013-05-04 22:12:25 -05001385 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1386 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001389 tlink = cifs_sb_tlink(cifs_sb);
1390 if (IS_ERR(tlink))
1391 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001392 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001393
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001394 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
Steve French7f573562005-08-30 11:32:14 -07001396 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301398 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001399 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 }
Steve French50c2f752007-07-13 00:33:32 +00001401
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001402 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1403 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001404 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1405 tcon, xid);
1406 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001407 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001408 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001409
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001410 server = tcon->ses->server;
1411
1412 if (!server->ops->mkdir) {
1413 rc = -ENOSYS;
1414 goto mkdir_out;
1415 }
1416
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001418 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001420 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001422 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001424
1425 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1426 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001427mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001428 /*
1429 * Force revalidate to get parent dir info when needed since cached
1430 * attributes are invalid now.
1431 */
1432 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001434 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001435 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 return rc;
1437}
1438
1439int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1440{
1441 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001442 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001444 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001445 struct cifs_tcon *tcon;
1446 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 char *full_path = NULL;
1448 struct cifsInodeInfo *cifsInode;
1449
Joe Perchesf96637b2013-05-04 22:12:25 -05001450 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001452 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
Steve French7f573562005-08-30 11:32:14 -07001454 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301456 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001457 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 }
1459
Jeff Layton7ffec372010-09-29 19:51:11 -04001460 cifs_sb = CIFS_SB(inode->i_sb);
1461 tlink = cifs_sb_tlink(cifs_sb);
1462 if (IS_ERR(tlink)) {
1463 rc = PTR_ERR(tlink);
1464 goto rmdir_exit;
1465 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001466 tcon = tlink_tcon(tlink);
1467 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001468
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001469 if (!server->ops->rmdir) {
1470 rc = -ENOSYS;
1471 cifs_put_tlink(tlink);
1472 goto rmdir_exit;
1473 }
1474
1475 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001476 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
1478 if (!rc) {
Steve French3677db12007-02-26 16:46:11 +00001479 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001480 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001481 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001482 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 }
1484
1485 cifsInode = CIFS_I(direntry->d_inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001486 /* force revalidate to go get info when needed */
1487 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001488
1489 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001490 /*
1491 * Force revalidate to get parent dir info when needed since cached
1492 * attributes are invalid now.
1493 */
1494 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001495
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1497 current_fs_time(inode->i_sb);
1498
Jeff Layton7ffec372010-09-29 19:51:11 -04001499rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001501 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 return rc;
1503}
1504
Steve Frenchee2fd962008-09-23 18:23:33 +00001505static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001506cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1507 const char *from_path, struct dentry *to_dentry,
1508 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001509{
1510 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001511 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001512 struct cifs_tcon *tcon;
1513 struct TCP_Server_Info *server;
Steve Frenchee2fd962008-09-23 18:23:33 +00001514 __u16 srcfid;
1515 int oplock, rc;
1516
Jeff Layton7ffec372010-09-29 19:51:11 -04001517 tlink = cifs_sb_tlink(cifs_sb);
1518 if (IS_ERR(tlink))
1519 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001520 tcon = tlink_tcon(tlink);
1521 server = tcon->ses->server;
1522
1523 if (!server->ops->rename)
1524 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001525
Steve Frenchee2fd962008-09-23 18:23:33 +00001526 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001527 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001528
1529 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001530 * Don't bother with rename by filehandle unless file is busy and
1531 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001532 * rename by filehandle to various Windows servers.
1533 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001534 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001535 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001536
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001537 /* open-file renames don't work across directories */
1538 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001539 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001540
Steve Frenchee2fd962008-09-23 18:23:33 +00001541 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001542 rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE,
Steve Frenchee2fd962008-09-23 18:23:33 +00001543 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1544 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1545 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchee2fd962008-09-23 18:23:33 +00001546 if (rc == 0) {
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001547 rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001548 (const char *) to_dentry->d_name.name,
1549 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1550 CIFS_MOUNT_MAP_SPECIAL_CHR);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001551 CIFSSMBClose(xid, tcon, srcfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001552 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001553do_rename_exit:
1554 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001555 return rc;
1556}
1557
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001558int
1559cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1560 struct inode *target_dir, struct dentry *target_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001562 char *from_name = NULL;
1563 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001564 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001565 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001566 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001567 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1568 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001569 unsigned int xid;
1570 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
Jeff Layton639e7a92010-09-03 11:50:09 -04001572 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001573 tlink = cifs_sb_tlink(cifs_sb);
1574 if (IS_ERR(tlink))
1575 return PTR_ERR(tlink);
1576 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001578 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001579
1580 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001581 * we already have the rename sem so we do not need to
1582 * grab it again here to protect the path integrity
1583 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001584 from_name = build_path_from_dentry(source_dentry);
1585 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 rc = -ENOMEM;
1587 goto cifs_rename_exit;
1588 }
1589
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001590 to_name = build_path_from_dentry(target_dentry);
1591 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001592 rc = -ENOMEM;
1593 goto cifs_rename_exit;
1594 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001596 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1597 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001598
Jeff Layton14121bd2008-10-20 14:45:22 -04001599 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001600 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001601 * Are src and dst hardlinks of same inode? We can only tell
1602 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001603 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001604 info_buf_source =
1605 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1606 GFP_KERNEL);
1607 if (info_buf_source == NULL) {
1608 rc = -ENOMEM;
1609 goto cifs_rename_exit;
1610 }
1611
1612 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001613 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1614 info_buf_source,
1615 cifs_sb->local_nls,
1616 cifs_sb->mnt_cifs_flags &
1617 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton8d281ef2008-10-22 13:57:01 -04001618 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001619 goto unlink_target;
1620
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001621 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1622 info_buf_target,
1623 cifs_sb->local_nls,
1624 cifs_sb->mnt_cifs_flags &
1625 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton14121bd2008-10-20 14:45:22 -04001626
Jeff Layton8d281ef2008-10-22 13:57:01 -04001627 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001628 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001629 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001630 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001631 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001632 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001633 }
1634 /*
1635 * else ... BB we could add the same check for Windows by
1636 * checking the UniqueId via FILE_INTERNAL_INFO
1637 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001638
Jeff Layton14121bd2008-10-20 14:45:22 -04001639unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001640 /* Try unlinking the target dentry if it's not negative */
1641 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Jeff Layton8d281ef2008-10-22 13:57:01 -04001642 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001643 if (tmprc)
1644 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001645 rc = cifs_do_rename(xid, source_dentry, from_name,
1646 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 }
1648
1649cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001650 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001651 kfree(from_name);
1652 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001653 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001654 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 return rc;
1656}
1657
Jeff Laytondf2cf172010-02-12 07:44:16 -05001658static bool
1659cifs_inode_needs_reval(struct inode *inode)
1660{
1661 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301662 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001663
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001664 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001665 return false;
1666
1667 if (!lookupCacheEnabled)
1668 return true;
1669
1670 if (cifs_i->time == 0)
1671 return true;
1672
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301673 if (!time_in_range(jiffies, cifs_i->time,
1674 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001675 return true;
1676
Jeff Laytondb192722010-05-17 14:51:49 -04001677 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301678 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001679 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1680 return true;
1681
Jeff Laytondf2cf172010-02-12 07:44:16 -05001682 return false;
1683}
1684
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301685/*
1686 * Zap the cache. Called when invalid_mapping flag is set.
1687 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001688int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001689cifs_invalidate_mapping(struct inode *inode)
1690{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001691 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001692 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1693
1694 cifs_i->invalid_mapping = false;
1695
Jeff Laytondf2cf172010-02-12 07:44:16 -05001696 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001697 rc = invalidate_inode_pages2(inode->i_mapping);
1698 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001699 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1700 __func__, inode);
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001701 cifs_i->invalid_mapping = true;
1702 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001703 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001704
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301705 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001706 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001707}
1708
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001709int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001710{
1711 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001712 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001713 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001714
1715 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001716 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001717
Jeff Layton13cfb732010-09-29 19:51:11 -04001718 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001719 rc = cifs_get_file_info_unix(filp);
1720 else
1721 rc = cifs_get_file_info(filp);
1722
Jeff Laytonabab0952010-02-12 07:44:18 -05001723 return rc;
1724}
1725
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001726int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001728 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001729 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001730 struct inode *inode = dentry->d_inode;
1731 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001732 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
Jeff Laytondf2cf172010-02-12 07:44:16 -05001734 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 return -ENOENT;
1736
Jeff Laytondf2cf172010-02-12 07:44:16 -05001737 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001738 return rc;
1739
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001740 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741
1742 /* can not safely grab the rename sem here if rename calls revalidate
1743 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001744 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301746 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001747 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001749
Joe Perchesf96637b2013-05-04 22:12:25 -05001750 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1751 full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001752 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
Jeff Layton0d424ad2010-09-20 16:01:35 -07001754 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001755 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1756 else
1757 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1758 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001760out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001762 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 return rc;
1764}
1765
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001766int cifs_revalidate_file(struct file *filp)
1767{
1768 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001769 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001770
1771 rc = cifs_revalidate_file_attr(filp);
1772 if (rc)
1773 return rc;
1774
1775 if (CIFS_I(inode)->invalid_mapping)
1776 rc = cifs_invalidate_mapping(inode);
1777 return rc;
1778}
1779
1780/* revalidate a dentry's inode attributes */
1781int cifs_revalidate_dentry(struct dentry *dentry)
1782{
1783 int rc;
1784 struct inode *inode = dentry->d_inode;
1785
1786 rc = cifs_revalidate_dentry_attr(dentry);
1787 if (rc)
1788 return rc;
1789
1790 if (CIFS_I(inode)->invalid_mapping)
1791 rc = cifs_invalidate_mapping(inode);
1792 return rc;
1793}
1794
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001796 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001798 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001799 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001800 struct inode *inode = dentry->d_inode;
1801 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001802
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001803 /*
1804 * We need to be sure that all dirty pages are written and the server
1805 * has actual ctime, mtime and file length.
1806 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001807 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001808 inode->i_mapping->nrpages != 0) {
1809 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001810 if (rc) {
1811 mapping_set_error(inode->i_mapping, rc);
1812 return rc;
1813 }
Steve French5fe14c82006-11-07 19:26:33 +00001814 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001815
1816 rc = cifs_revalidate_dentry_attr(dentry);
1817 if (rc)
1818 return rc;
1819
1820 generic_fillattr(inode, stat);
1821 stat->blksize = CIFS_MAX_MSGSIZE;
1822 stat->ino = CIFS_I(inode)->uniqueid;
1823
1824 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001825 * If on a multiuser mount without unix extensions or cifsacl being
1826 * enabled, and the admin hasn't overridden them, set the ownership
1827 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001828 */
1829 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001830 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001831 !tcon->unix_ext) {
1832 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1833 stat->uid = current_fsuid();
1834 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1835 stat->gid = current_fsgid();
1836 }
1837 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838}
1839
1840static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1841{
1842 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1843 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1844 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 int rc = 0;
1846
1847 page = grab_cache_page(mapping, index);
1848 if (!page)
1849 return -ENOMEM;
1850
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001851 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 unlock_page(page);
1853 page_cache_release(page);
1854 return rc;
1855}
1856
Christoph Hellwig1b947462010-07-18 17:51:21 -04001857static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001858{
Steve Frenchba6a46a2007-02-26 20:06:29 +00001859 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00001860 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001861 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001862
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001863 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00001864}
1865
Jeff Layton8efdbde2008-07-23 21:28:12 +00001866static int
1867cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001868 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00001869{
1870 int rc;
1871 struct cifsFileInfo *open_file;
1872 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1873 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001874 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001875 struct cifs_tcon *tcon = NULL;
1876 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001877 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001878
1879 /*
1880 * To avoid spurious oplock breaks from server, in the case of
1881 * inodes that we already have open, avoid doing path based
1882 * setting of file size if we can do it by handle.
1883 * This keeps our caching token (oplock) and avoids timeouts
1884 * when the local oplock break takes longer to flush
1885 * writebehind data than the SMB timeout for the SetPathInfo
1886 * request would allow
1887 */
Jeff Layton6508d902010-09-29 19:51:11 -04001888 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001889 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001890 tcon = tlink_tcon(open_file->tlink);
1891 server = tcon->ses->server;
1892 if (server->ops->set_file_size)
1893 rc = server->ops->set_file_size(xid, tcon, open_file,
1894 attrs->ia_size, false);
1895 else
1896 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001897 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05001898 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001899 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1900 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001901
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001902 io_parms.netfid = open_file->fid.netfid;
1903 io_parms.pid = open_file->pid;
1904 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001905 io_parms.offset = 0;
1906 io_parms.length = attrs->ia_size;
1907 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1908 NULL, NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001909 cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001910 }
1911 } else
1912 rc = -EINVAL;
1913
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001914 if (!rc)
1915 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07001916
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001917 if (tcon == NULL) {
1918 tlink = cifs_sb_tlink(cifs_sb);
1919 if (IS_ERR(tlink))
1920 return PTR_ERR(tlink);
1921 tcon = tlink_tcon(tlink);
1922 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001923 }
1924
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001925 /*
1926 * Set file size by pathname rather than by handle either because no
1927 * valid, writeable file handle for it was found or because there was
1928 * an error setting it by handle.
1929 */
1930 if (server->ops->set_path_size)
1931 rc = server->ops->set_path_size(xid, tcon, full_path,
1932 attrs->ia_size, cifs_sb, false);
1933 else
1934 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05001935 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001936 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1937 __u16 netfid;
1938 int oplock = 0;
1939
1940 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
1941 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
1942 &oplock, NULL, cifs_sb->local_nls,
1943 cifs_sb->mnt_cifs_flags &
1944 CIFS_MOUNT_MAP_SPECIAL_CHR);
1945 if (rc == 0) {
1946 unsigned int bytes_written;
1947
1948 io_parms.netfid = netfid;
1949 io_parms.pid = current->tgid;
1950 io_parms.tcon = tcon;
1951 io_parms.offset = 0;
1952 io_parms.length = attrs->ia_size;
1953 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
1954 NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001955 cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001956 CIFSSMBClose(xid, tcon, netfid);
1957 }
1958 }
1959 if (tlink)
1960 cifs_put_tlink(tlink);
1961
1962set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00001963 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001964 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04001965 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001966 cifs_truncate_page(inode->i_mapping, inode->i_size);
1967 }
1968
1969 return rc;
1970}
1971
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001972static int
1973cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1974{
1975 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001976 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001977 char *full_path = NULL;
1978 struct inode *inode = direntry->d_inode;
1979 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1980 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001981 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001982 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001983 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04001984 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001985
Joe Perchesf96637b2013-05-04 22:12:25 -05001986 cifs_dbg(FYI, "setattr_unix on file %s attrs->ia_valid=0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00001987 direntry->d_name.name, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001988
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001989 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001990
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001991 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
1992 attrs->ia_valid |= ATTR_FORCE;
1993
1994 rc = inode_change_ok(inode, attrs);
1995 if (rc < 0)
1996 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001997
1998 full_path = build_path_from_dentry(direntry);
1999 if (full_path == NULL) {
2000 rc = -ENOMEM;
2001 goto out;
2002 }
2003
Jeff Layton0f4d6342009-03-26 13:35:37 -04002004 /*
2005 * Attempt to flush data before changing attributes. We need to do
2006 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2007 * ownership or mode then we may also need to do this. Here, we take
2008 * the safe way out and just do the flush on all setattr requests. If
2009 * the flush returns error, store it to report later and continue.
2010 *
2011 * BB: This should be smarter. Why bother flushing pages that
2012 * will be truncated anyway? Also, should we error out here if
2013 * the flush returns error?
2014 */
2015 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002016 mapping_set_error(inode->i_mapping, rc);
2017 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002018
2019 if (attrs->ia_valid & ATTR_SIZE) {
2020 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2021 if (rc != 0)
2022 goto out;
2023 }
2024
2025 /* skip mode change if it's just for clearing setuid/setgid */
2026 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2027 attrs->ia_valid &= ~ATTR_MODE;
2028
2029 args = kmalloc(sizeof(*args), GFP_KERNEL);
2030 if (args == NULL) {
2031 rc = -ENOMEM;
2032 goto out;
2033 }
2034
2035 /* set up the struct */
2036 if (attrs->ia_valid & ATTR_MODE)
2037 args->mode = attrs->ia_mode;
2038 else
2039 args->mode = NO_CHANGE_64;
2040
2041 if (attrs->ia_valid & ATTR_UID)
2042 args->uid = attrs->ia_uid;
2043 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002044 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002045
2046 if (attrs->ia_valid & ATTR_GID)
2047 args->gid = attrs->ia_gid;
2048 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002049 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002050
2051 if (attrs->ia_valid & ATTR_ATIME)
2052 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2053 else
2054 args->atime = NO_CHANGE_64;
2055
2056 if (attrs->ia_valid & ATTR_MTIME)
2057 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2058 else
2059 args->mtime = NO_CHANGE_64;
2060
2061 if (attrs->ia_valid & ATTR_CTIME)
2062 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2063 else
2064 args->ctime = NO_CHANGE_64;
2065
2066 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002067 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002068 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002069 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002070 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002071 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002072 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002073 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002074 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002075 tlink = cifs_sb_tlink(cifs_sb);
2076 if (IS_ERR(tlink)) {
2077 rc = PTR_ERR(tlink);
2078 goto out;
2079 }
2080 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002081 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002082 cifs_sb->local_nls,
2083 cifs_sb->mnt_cifs_flags &
2084 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002085 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002086 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002087
Christoph Hellwig10257742010-06-04 11:30:02 +02002088 if (rc)
2089 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002090
Christoph Hellwig10257742010-06-04 11:30:02 +02002091 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002092 attrs->ia_size != i_size_read(inode))
2093 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002094
2095 setattr_copy(inode, attrs);
2096 mark_inode_dirty(inode);
2097
2098 /* force revalidate when any of these times are set since some
2099 of the fs types (eg ext3, fat) do not have fine enough
2100 time granularity to match protocol, and we do not have a
2101 a way (yet) to query the server fs's time granularity (and
2102 whether it rounds times down).
2103 */
2104 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2105 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002106out:
2107 kfree(args);
2108 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002109 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002110 return rc;
2111}
2112
Jeff Layton0510eeb2008-08-02 07:26:12 -04002113static int
2114cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002116 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002117 kuid_t uid = INVALID_UID;
2118 kgid_t gid = INVALID_GID;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002119 struct inode *inode = direntry->d_inode;
2120 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002121 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 char *full_path = NULL;
2123 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002124 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002125 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002126
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002127 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128
Joe Perchesf96637b2013-05-04 22:12:25 -05002129 cifs_dbg(FYI, "setattr on file %s attrs->iavalid 0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002130 direntry->d_name.name, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002131
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002132 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2133 attrs->ia_valid |= ATTR_FORCE;
2134
2135 rc = inode_change_ok(inode, attrs);
2136 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002137 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002138 return rc;
Steve French6473a552005-11-29 20:20:10 -08002139 }
Steve French50c2f752007-07-13 00:33:32 +00002140
Steve French7f573562005-08-30 11:32:14 -07002141 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302143 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002144 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302145 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147
Jeff Layton0f4d6342009-03-26 13:35:37 -04002148 /*
2149 * Attempt to flush data before changing attributes. We need to do
2150 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2151 * ownership or mode then we may also need to do this. Here, we take
2152 * the safe way out and just do the flush on all setattr requests. If
2153 * the flush returns error, store it to report later and continue.
2154 *
2155 * BB: This should be smarter. Why bother flushing pages that
2156 * will be truncated anyway? Also, should we error out here if
2157 * the flush returns error?
2158 */
2159 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002160 mapping_set_error(inode->i_mapping, rc);
2161 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002162
Steve French50531442008-03-14 19:21:31 +00002163 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002164 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2165 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002166 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002168
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002169 if (attrs->ia_valid & ATTR_UID)
2170 uid = attrs->ia_uid;
2171
2172 if (attrs->ia_valid & ATTR_GID)
2173 gid = attrs->ia_gid;
2174
2175#ifdef CONFIG_CIFS_ACL
2176 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002177 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002178 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2179 uid, gid);
2180 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002181 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2182 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002183 goto cifs_setattr_exit;
2184 }
2185 }
2186 } else
2187#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002188 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002189 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
Jeff Laytond32c4f22007-10-18 03:05:22 -07002191 /* skip mode change if it's just for clearing setuid/setgid */
2192 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2193 attrs->ia_valid &= ~ATTR_MODE;
2194
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002197 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002198#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002199 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002200 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002201 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002202 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002203 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2204 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002205 goto cifs_setattr_exit;
2206 }
2207 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002208#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002209 if (((mode & S_IWUGO) == 0) &&
2210 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002211
2212 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2213
Jeff Layton51328612008-05-22 09:33:34 -04002214 /* fix up mode if we're not using dynperm */
2215 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2216 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2217 } else if ((mode & S_IWUGO) &&
2218 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002219
2220 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2221 /* Attributes of 0 are ignored */
2222 if (dosattr == 0)
2223 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002224
2225 /* reset local inode permissions to normal */
2226 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2227 attrs->ia_mode &= ~(S_IALLUGO);
2228 if (S_ISDIR(inode->i_mode))
2229 attrs->ia_mode |=
2230 cifs_sb->mnt_dir_mode;
2231 else
2232 attrs->ia_mode |=
2233 cifs_sb->mnt_file_mode;
2234 }
2235 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2236 /* ignore mode change - ATTR_READONLY hasn't changed */
2237 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 }
2240
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002241 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2242 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2243 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2244 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
Steve Frenche30dcf32005-09-20 20:49:16 -07002246 /* Even if error on time set, no sense failing the call if
2247 the server would set the time to a reasonable value anyway,
2248 and this check ensures that we are not being called from
2249 sys_utimes in which case we ought to fail the call back to
2250 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002251 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002252 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002253 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 }
2255
2256 /* do not need local check to inode_check_ok since the server does
2257 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002258 if (rc)
2259 goto cifs_setattr_exit;
2260
2261 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002262 attrs->ia_size != i_size_read(inode))
2263 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002264
2265 setattr_copy(inode, attrs);
2266 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002267
Steve Frenche30dcf32005-09-20 20:49:16 -07002268cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002270 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 return rc;
2272}
2273
Jeff Layton0510eeb2008-08-02 07:26:12 -04002274int
2275cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2276{
2277 struct inode *inode = direntry->d_inode;
2278 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002279 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002280
2281 if (pTcon->unix_ext)
2282 return cifs_setattr_unix(direntry, attrs);
2283
2284 return cifs_setattr_nounix(direntry, attrs);
2285
2286 /* BB: add cifs_setattr_legacy for really old servers */
2287}
2288
Steve French99ee4db2007-02-27 05:35:17 +00002289#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290void cifs_delete_inode(struct inode *inode)
2291{
Joe Perchesf96637b2013-05-04 22:12:25 -05002292 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 /* may have to add back in if and when safe distributed caching of
2294 directories added e.g. via FindNotify */
2295}
Steve French99ee4db2007-02-27 05:35:17 +00002296#endif