blob: fc3025199cb336f6c07c8172d19e501601a3f1f7 [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 */
104 if (cifs_i->clientCanCacheRead) {
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;
174 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000175}
176
Jeff Layton4065c802010-05-17 07:18:58 -0400177void
178cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
179{
180 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
181
182 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
183 return;
184
185 fattr->cf_uniqueid = iunique(sb, ROOT_I);
186}
187
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400188/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
189void
190cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
191 struct cifs_sb_info *cifs_sb)
192{
193 memset(fattr, 0, sizeof(*fattr));
194 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
195 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
196 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
197
198 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
199 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
200 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
201 fattr->cf_mode = le64_to_cpu(info->Permissions);
202
203 /*
204 * Since we set the inode type below we need to mask off
205 * to avoid strange results if bits set above.
206 */
207 fattr->cf_mode &= ~S_IFMT;
208 switch (le32_to_cpu(info->Type)) {
209 case UNIX_FILE:
210 fattr->cf_mode |= S_IFREG;
211 fattr->cf_dtype = DT_REG;
212 break;
213 case UNIX_SYMLINK:
214 fattr->cf_mode |= S_IFLNK;
215 fattr->cf_dtype = DT_LNK;
216 break;
217 case UNIX_DIR:
218 fattr->cf_mode |= S_IFDIR;
219 fattr->cf_dtype = DT_DIR;
220 break;
221 case UNIX_CHARDEV:
222 fattr->cf_mode |= S_IFCHR;
223 fattr->cf_dtype = DT_CHR;
224 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
225 le64_to_cpu(info->DevMinor) & MINORMASK);
226 break;
227 case UNIX_BLOCKDEV:
228 fattr->cf_mode |= S_IFBLK;
229 fattr->cf_dtype = DT_BLK;
230 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
231 le64_to_cpu(info->DevMinor) & MINORMASK);
232 break;
233 case UNIX_FIFO:
234 fattr->cf_mode |= S_IFIFO;
235 fattr->cf_dtype = DT_FIFO;
236 break;
237 case UNIX_SOCKET:
238 fattr->cf_mode |= S_IFSOCK;
239 fattr->cf_dtype = DT_SOCK;
240 break;
241 default:
242 /* safest to call it a file if we do not know */
243 fattr->cf_mode |= S_IFREG;
244 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500245 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400246 break;
247 }
248
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800249 fattr->cf_uid = cifs_sb->mnt_uid;
250 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
251 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800252 if (id < ((uid_t)-1)) {
253 kuid_t uid = make_kuid(&init_user_ns, id);
254 if (uid_valid(uid))
255 fattr->cf_uid = uid;
256 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800257 }
258
259 fattr->cf_gid = cifs_sb->mnt_gid;
260 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
261 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800262 if (id < ((gid_t)-1)) {
263 kgid_t gid = make_kgid(&init_user_ns, id);
264 if (gid_valid(gid))
265 fattr->cf_gid = gid;
266 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800267 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400268
269 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
270}
Steve Frenchb9a32602008-05-20 21:52:32 +0000271
272/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400273 * Fill a cifs_fattr struct with fake inode info.
274 *
275 * Needed to setup cifs_fattr data for the directory which is the
276 * junction to the new submount (ie to setup the fake directory
277 * which represents a DFS referral).
Steve Frenchb9a32602008-05-20 21:52:32 +0000278 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000279static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400280cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000281{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400282 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000283
Joe Perchesf96637b2013-05-04 22:12:25 -0500284 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000285
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400286 memset(fattr, 0, sizeof(*fattr));
287 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
288 fattr->cf_uid = cifs_sb->mnt_uid;
289 fattr->cf_gid = cifs_sb->mnt_gid;
290 fattr->cf_atime = CURRENT_TIME;
291 fattr->cf_ctime = CURRENT_TIME;
292 fattr->cf_mtime = CURRENT_TIME;
293 fattr->cf_nlink = 2;
294 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000295}
296
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700297static int
298cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500299{
300 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400301 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500302 FILE_UNIX_BASIC_INFO find_data;
303 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500304 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500305 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700306 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000307 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500308
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400309 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700310 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500311 if (!rc) {
312 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
313 } else if (rc == -EREMOTE) {
314 cifs_create_dfs_fattr(&fattr, inode->i_sb);
315 rc = 0;
316 }
317
318 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400319 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500320 return rc;
321}
322
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400324 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400325 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400327 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000328 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400329 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000330 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400331 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
Joe Perchesf96637b2013-05-04 22:12:25 -0500334 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000335
Jeff Layton7ffec372010-09-29 19:51:11 -0400336 tlink = cifs_sb_tlink(cifs_sb);
337 if (IS_ERR(tlink))
338 return PTR_ERR(tlink);
339 tcon = tlink_tcon(tlink);
340
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400342 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Steve French737b7582005-04-28 22:41:06 -0700343 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
344 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400345 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400346
347 if (!rc) {
348 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
349 } else if (rc == -EREMOTE) {
350 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700351 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400352 } else {
353 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000354 }
355
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200356 /* check for Minshall+French symlinks */
357 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
358 int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
359 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500360 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200361 }
362
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400363 if (*pinode == NULL) {
364 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400365 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400366 *pinode = cifs_iget(sb, &fattr);
367 if (!*pinode)
368 rc = -ENOMEM;
369 } else {
370 /* we already have inode, update it */
371 cifs_fattr_to_inode(*pinode, &fattr);
372 }
Steve French0e4bbde2008-05-20 19:50:46 +0000373
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 return rc;
375}
376
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400377static int
378cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400379 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800380{
381 int rc;
Steve French4b18f2a2008-04-29 00:06:05 +0000382 int oplock = 0;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800383 __u16 netfid;
Jeff Layton7ffec372010-09-29 19:51:11 -0400384 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000385 struct cifs_tcon *tcon;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000386 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800387 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800388 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000389 char *pbuf;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800390
391 pbuf = buf;
392
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400393 fattr->cf_mode &= ~S_IFMT;
394
395 if (fattr->cf_eof == 0) {
396 fattr->cf_mode |= S_IFIFO;
397 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800398 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400399 } else if (fattr->cf_eof < 8) {
400 fattr->cf_mode |= S_IFREG;
401 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800402 return -EINVAL; /* EOPNOTSUPP? */
403 }
Steve French50c2f752007-07-13 00:33:32 +0000404
Jeff Layton7ffec372010-09-29 19:51:11 -0400405 tlink = cifs_sb_tlink(cifs_sb);
406 if (IS_ERR(tlink))
407 return PTR_ERR(tlink);
408 tcon = tlink_tcon(tlink);
409
410 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800411 CREATE_NOT_DIR, &netfid, &oplock, NULL,
412 cifs_sb->local_nls,
413 cifs_sb->mnt_cifs_flags &
414 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000415 if (rc == 0) {
Steve Frenchec637e32005-12-12 20:53:18 -0800416 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800417 /* Read header */
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000418 io_parms.netfid = netfid;
419 io_parms.pid = current->tgid;
420 io_parms.tcon = tcon;
421 io_parms.offset = 0;
422 io_parms.length = 24;
423 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
424 &buf_type);
Steve French4523cc32007-04-30 20:13:06 +0000425 if ((rc == 0) && (bytes_read >= 8)) {
426 if (memcmp("IntxBLK", pbuf, 8) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500427 cifs_dbg(FYI, "Block device\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400428 fattr->cf_mode |= S_IFBLK;
429 fattr->cf_dtype = DT_BLK;
Steve French4523cc32007-04-30 20:13:06 +0000430 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800431 /* we have enough to decode dev num */
432 __u64 mjr; /* major */
433 __u64 mnr; /* minor */
434 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
435 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400436 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve French86c96b42005-11-18 20:25:31 -0800437 }
Steve French4523cc32007-04-30 20:13:06 +0000438 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500439 cifs_dbg(FYI, "Char device\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400440 fattr->cf_mode |= S_IFCHR;
441 fattr->cf_dtype = DT_CHR;
Steve French4523cc32007-04-30 20:13:06 +0000442 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800443 /* we have enough to decode dev num */
444 __u64 mjr; /* major */
445 __u64 mnr; /* minor */
446 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
447 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400448 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000449 }
Steve French4523cc32007-04-30 20:13:06 +0000450 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500451 cifs_dbg(FYI, "Symlink\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400452 fattr->cf_mode |= S_IFLNK;
453 fattr->cf_dtype = DT_LNK;
Steve French86c96b42005-11-18 20:25:31 -0800454 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400455 fattr->cf_mode |= S_IFREG; /* file? */
456 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000457 rc = -EOPNOTSUPP;
Steve French86c96b42005-11-18 20:25:31 -0800458 }
Steve French3020a1f2005-11-18 11:31:10 -0800459 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400460 fattr->cf_mode |= S_IFREG; /* then it is a file */
461 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000462 rc = -EOPNOTSUPP; /* or some unknown SFU type */
463 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400464 CIFSSMBClose(xid, tcon, netfid);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800465 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400466 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800467 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800468}
469
Steve French9e294f12005-11-17 16:59:21 -0800470#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
471
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400472/*
473 * Fetch mode bits as provided by SFU.
474 *
475 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
476 */
477static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400478 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800479{
Steve French3020a1f2005-11-18 11:31:10 -0800480#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800481 ssize_t rc;
482 char ea_value[4];
483 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400484 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000485 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800486
Jeff Layton7ffec372010-09-29 19:51:11 -0400487 tlink = cifs_sb_tlink(cifs_sb);
488 if (IS_ERR(tlink))
489 return PTR_ERR(tlink);
490 tcon = tlink_tcon(tlink);
491
492 rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400493 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
494 cifs_sb->mnt_cifs_flags &
495 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400496 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000497 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800498 return (int)rc;
499 else if (rc > 3) {
500 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400501 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500502 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
503 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400504 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500505 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800506 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400507
508 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800509#else
510 return -EOPNOTSUPP;
511#endif
Steve French9e294f12005-11-17 16:59:21 -0800512}
513
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400514/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000515static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400516cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
517 struct cifs_sb_info *cifs_sb, bool adjust_tz)
Steve Frenchb9a32602008-05-20 21:52:32 +0000518{
Steve French96daf2b2011-05-27 04:34:02 +0000519 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700520
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400521 memset(fattr, 0, sizeof(*fattr));
522 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
523 if (info->DeletePending)
524 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000525
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400526 if (info->LastAccessTime)
527 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
528 else
529 fattr->cf_atime = CURRENT_TIME;
530
531 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
532 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
533
534 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700535 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
536 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400537 }
538
539 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
540 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500541 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400542
543 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
544 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
545 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300546 /*
547 * Server can return wrong NumberOfLinks value for directories
548 * when Unix extensions are disabled - fake it.
549 */
550 fattr->cf_nlink = 2;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400551 } else {
552 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
553 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400554
Jeff Laytond0c280d2009-07-09 01:46:44 -0400555 /* clear write bits if ATTR_READONLY is set */
556 if (fattr->cf_cifsattrs & ATTR_READONLY)
557 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400558
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300559 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
560 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400561
562 fattr->cf_uid = cifs_sb->mnt_uid;
563 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000564}
565
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700566static int
567cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500568{
569 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400570 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500571 FILE_ALL_INFO find_data;
572 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500573 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500574 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700575 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000576 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700577 struct TCP_Server_Info *server = tcon->ses->server;
578
579 if (!server->ops->query_file_info)
580 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500581
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400582 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700583 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400584 switch (rc) {
585 case 0:
586 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
587 break;
588 case -EREMOTE:
589 cifs_create_dfs_fattr(&fattr, inode->i_sb);
590 rc = 0;
591 break;
592 case -EOPNOTSUPP:
593 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500594 /*
595 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000596 * for now, just skip revalidating and mark inode for
597 * immediate reval.
598 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500599 rc = 0;
600 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400601 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500602 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400603 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500604
605 /*
606 * don't bother with SFU junk here -- just mark inode as needing
607 * revalidation.
608 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500609 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
610 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
611 cifs_fattr_to_inode(inode, &fattr);
612cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400613 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500614 return rc;
615}
616
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400617int
618cifs_get_inode_info(struct inode **inode, const char *full_path,
619 FILE_ALL_INFO *data, struct super_block *sb, int xid,
620 const __u16 *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500622 bool validinum = false;
623 __u16 srchflgs;
624 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400625 struct cifs_tcon *tcon;
626 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400627 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400630 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400631 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500632 struct cifs_search_info *srchinf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
Jeff Layton7ffec372010-09-29 19:51:11 -0400634 tlink = cifs_sb_tlink(cifs_sb);
635 if (IS_ERR(tlink))
636 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400637 tcon = tlink_tcon(tlink);
638 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400639
Joe Perchesf96637b2013-05-04 22:12:25 -0500640 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400642 if ((data == NULL) && (*inode != NULL)) {
643 if (CIFS_I(*inode)->clientCanCacheRead) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500644 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400645 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 }
647 }
648
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400649 /* if inode info is not passed, get it from server */
650 if (data == NULL) {
651 if (!server->ops->query_path_info) {
652 rc = -ENOSYS;
653 goto cgii_exit;
654 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400656 if (buf == NULL) {
657 rc = -ENOMEM;
658 goto cgii_exit;
659 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400660 data = (FILE_ALL_INFO *)buf;
661 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
662 data, &adjust_tz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400664
665 if (!rc) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400666 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb,
667 adjust_tz);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400668 } else if (rc == -EREMOTE) {
669 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000670 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500671 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
672 srchinf = kzalloc(sizeof(struct cifs_search_info),
673 GFP_KERNEL);
674 if (srchinf == NULL) {
675 rc = -ENOMEM;
676 goto cgii_exit;
677 }
678
679 srchinf->endOfSearch = false;
680 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
681
682 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
683 CIFS_SEARCH_CLOSE_AT_END |
684 CIFS_SEARCH_BACKUP_SEARCH;
685
686 rc = CIFSFindFirst(xid, tcon, full_path,
687 cifs_sb, NULL, srchflgs, srchinf, false);
688 if (!rc) {
689 data =
690 (FILE_ALL_INFO *)srchinf->srch_entries_start;
691
692 cifs_dir_info_to_fattr(&fattr,
693 (FILE_DIRECTORY_INFO *)data, cifs_sb);
694 fattr.cf_uniqueid = le64_to_cpu(
695 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
696 validinum = true;
697
698 cifs_buf_release(srchinf->ntwrk_buf_start);
699 }
700 kfree(srchinf);
701 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000702 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400704 /*
705 * If an inode wasn't passed in, then get the inode number
706 *
707 * Is an i_ino of zero legal? Can we use that to check if the server
708 * supports returning inode numbers? Are there other sanity checks we
709 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400710 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400711 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000712 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500713 if (validinum == false) {
714 if (server->ops->get_srv_inum)
715 tmprc = server->ops->get_srv_inum(xid,
716 tcon, cifs_sb, full_path,
717 &fattr.cf_uniqueid, data);
718 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500719 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
720 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500721 fattr.cf_uniqueid = iunique(sb, ROOT_I);
722 cifs_autodisable_serverino(cifs_sb);
723 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500724 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500725 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400726 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500727 } else
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400728 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000729
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400730 /* query for SFU type info if supported and needed */
731 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
732 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
733 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
734 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500735 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000736 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000737
Jeff Layton79df1ba2010-12-06 12:52:08 -0500738#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000739 /* fill in 0777 bits from ACL */
740 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400741 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600742 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500743 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
744 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600745 goto cgii_exit;
746 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000747 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500748#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400749
750 /* fill in remaining high mode bits e.g. SUID, VTX */
751 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
752 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
753
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200754 /* check for Minshall+French symlinks */
755 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
756 tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
757 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500758 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200759 }
760
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400761 if (!*inode) {
762 *inode = cifs_iget(sb, &fattr);
763 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400764 rc = -ENOMEM;
765 } else {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400766 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000767 }
768
Igor Mammedov79626702008-03-09 03:44:18 +0000769cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400771 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 return rc;
773}
774
Steve French7f8ed422007-09-28 22:28:55 +0000775static const struct inode_operations cifs_ipc_inode_ops = {
776 .lookup = cifs_lookup,
777};
778
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400779static int
780cifs_find_inode(struct inode *inode, void *opaque)
781{
782 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
783
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400784 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400785 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
786 return 0;
787
Jeff Layton20054bd2011-01-07 11:30:27 -0500788 /* use createtime like an i_generation field */
789 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
790 return 0;
791
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400792 /* don't match inode of different type */
793 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
794 return 0;
795
Jeff Layton5acfec22010-08-02 17:43:54 -0400796 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400797 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400798 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400799
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400800 return 1;
801}
802
803static int
804cifs_init_inode(struct inode *inode, void *opaque)
805{
806 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
807
808 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500809 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400810 return 0;
811}
812
Jeff Layton5acfec22010-08-02 17:43:54 -0400813/*
814 * walk dentry list for an inode and report whether it has aliases that
815 * are hashed. We use this to determine if a directory inode can actually
816 * be used.
817 */
818static bool
819inode_has_hashed_dentries(struct inode *inode)
820{
821 struct dentry *dentry;
822
Nick Piggin873feea2011-01-07 17:50:06 +1100823 spin_lock(&inode->i_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800824 hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400825 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100826 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400827 return true;
828 }
829 }
Nick Piggin873feea2011-01-07 17:50:06 +1100830 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400831 return false;
832}
833
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400834/* Given fattrs, get a corresponding inode */
835struct inode *
836cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
837{
838 unsigned long hash;
839 struct inode *inode;
840
Jeff Layton3d694382010-05-11 14:59:55 -0400841retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -0500842 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400843
844 /* hash down to 32-bits on 32-bit arch */
845 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
846
847 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400848 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400849 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400850 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400851 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400852
853 if (inode_has_hashed_dentries(inode)) {
854 cifs_autodisable_serverino(CIFS_SB(sb));
855 iput(inode);
856 fattr->cf_uniqueid = iunique(sb, ROOT_I);
857 goto retry_iget5_locked;
858 }
Jeff Layton3d694382010-05-11 14:59:55 -0400859 }
860
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400861 cifs_fattr_to_inode(inode, fattr);
862 if (sb->s_flags & MS_NOATIME)
863 inode->i_flags |= S_NOATIME | S_NOCMTIME;
864 if (inode->i_state & I_NEW) {
865 inode->i_ino = hash;
Jeff Layton522440e2010-09-29 09:49:54 -0400866 if (S_ISREG(inode->i_mode))
867 inode->i_data.backing_dev_info = sb->s_bdi;
Steve French0ccd4802010-07-16 04:31:02 +0000868#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530869 /* initialize per-inode cache cookie pointer */
870 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000871#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400872 unlock_new_inode(inode);
873 }
874 }
875
876 return inode;
877}
878
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600880struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400882 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700883 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400884 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800885 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000886 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800887
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400888 xid = get_xid();
Jeff Layton0d424ad2010-09-20 16:01:35 -0700889 if (tcon->unix_ext)
Steve Frenchf87d39d2011-05-27 03:50:55 +0000890 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400891 else
Steve Frenchf87d39d2011-05-27 03:50:55 +0000892 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400893
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000894 if (!inode) {
895 inode = ERR_PTR(rc);
896 goto out;
897 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400898
Steve French0ccd4802010-07-16 04:31:02 +0000899#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530900 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700901 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000902#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530903
Jeff Layton0d424ad2010-09-20 16:01:35 -0700904 if (rc && tcon->ipc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500905 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -0500906 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +0000907 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200908 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +0000909 inode->i_op = &cifs_ipc_inode_ops;
910 inode->i_fop = &simple_dir_operations;
911 inode->i_uid = cifs_sb->mnt_uid;
912 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -0500913 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +0000914 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800915 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000916 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000917 }
918
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000919out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400920 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -0800921 * TODO: This is no longer true
922 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400923 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -0800924 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925}
926
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700927int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400928cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700929 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +0000930{
Steve French388e57b2008-09-16 23:50:58 +0000931 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +0000932 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700933 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +0000934 FILE_BASIC_INFO info_buf;
935
Steve French1adcb712009-02-25 14:19:56 +0000936 if (attrs == NULL)
937 return -EINVAL;
938
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700939 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
940 if (!server->ops->set_file_info)
941 return -ENOSYS;
942
Steve French388e57b2008-09-16 23:50:58 +0000943 if (attrs->ia_valid & ATTR_ATIME) {
944 set_time = true;
945 info_buf.LastAccessTime =
946 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
947 } else
948 info_buf.LastAccessTime = 0;
949
950 if (attrs->ia_valid & ATTR_MTIME) {
951 set_time = true;
952 info_buf.LastWriteTime =
953 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
954 } else
955 info_buf.LastWriteTime = 0;
956
957 /*
958 * Samba throws this field away, but windows may actually use it.
959 * Do not set ctime unless other time stamps are changed explicitly
960 * (i.e. by utimes()) since we would then have a mix of client and
961 * server times.
962 */
963 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500964 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +0000965 info_buf.ChangeTime =
966 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
967 } else
968 info_buf.ChangeTime = 0;
969
970 info_buf.CreationTime = 0; /* don't change */
971 info_buf.Attributes = cpu_to_le32(dosattr);
972
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700973 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +0000974}
975
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400976/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700977 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400978 * and rename it to a random name that hopefully won't conflict with
979 * anything else.
980 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700981int
982cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
983 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400984{
985 int oplock = 0;
986 int rc;
987 __u16 netfid;
Steve French32709582008-10-20 00:44:19 +0000988 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400989 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
990 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400991 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000992 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +0000993 __u32 dosattr, origattr;
994 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400995
Jeff Layton7ffec372010-09-29 19:51:11 -0400996 tlink = cifs_sb_tlink(cifs_sb);
997 if (IS_ERR(tlink))
998 return PTR_ERR(tlink);
999 tcon = tlink_tcon(tlink);
1000
Sachin Prabhuc483a982013-03-05 19:25:56 +00001001 /*
1002 * We cannot rename the file if the server doesn't support
1003 * CAP_INFOLEVEL_PASSTHRU
1004 */
1005 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1006 rc = -EBUSY;
1007 goto out;
1008 }
1009
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001010 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001011 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001012 &netfid, &oplock, NULL, cifs_sb->local_nls,
1013 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1014 if (rc != 0)
1015 goto out;
1016
Steve French32709582008-10-20 00:44:19 +00001017 origattr = cifsInode->cifsAttrs;
1018 if (origattr == 0)
1019 origattr |= ATTR_NORMAL;
1020
1021 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001022 if (dosattr == 0)
1023 dosattr |= ATTR_NORMAL;
1024 dosattr |= ATTR_HIDDEN;
1025
Steve French32709582008-10-20 00:44:19 +00001026 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1027 if (dosattr != origattr) {
1028 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1029 if (info_buf == NULL) {
1030 rc = -ENOMEM;
1031 goto out_close;
1032 }
1033 info_buf->Attributes = cpu_to_le32(dosattr);
1034 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1035 current->tgid);
1036 /* although we would like to mark the file hidden
1037 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001038 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001039 cifsInode->cifsAttrs = dosattr;
1040 else
1041 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001042 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001043
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001044 /* rename the file */
1045 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001046 cifs_sb->mnt_cifs_flags &
1047 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French32709582008-10-20 00:44:19 +00001048 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001049 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001050 goto undo_setattr;
1051 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001052
Steve French32709582008-10-20 00:44:19 +00001053 /* try to set DELETE_ON_CLOSE */
1054 if (!cifsInode->delete_pending) {
1055 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
1056 current->tgid);
1057 /*
1058 * some samba versions return -ENOENT when we try to set the
1059 * file disposition here. Likely a samba bug, but work around
1060 * it for now. This means that some cifsXXX files may hang
1061 * around after they shouldn't.
1062 *
1063 * BB: remove this hack after more servers have the fix
1064 */
1065 if (rc == -ENOENT)
1066 rc = 0;
1067 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001068 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001069 goto undo_rename;
1070 }
1071 cifsInode->delete_pending = true;
1072 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001073
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001074out_close:
1075 CIFSSMBClose(xid, tcon, netfid);
1076out:
Steve French32709582008-10-20 00:44:19 +00001077 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001078 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001079 return rc;
Steve French32709582008-10-20 00:44:19 +00001080
1081 /*
1082 * reset everything back to the original state. Don't bother
1083 * dealing with errors here since we can't do anything about
1084 * them anyway.
1085 */
1086undo_rename:
1087 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
1088 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1089 CIFS_MOUNT_MAP_SPECIAL_CHR);
1090undo_setattr:
1091 if (dosattr != origattr) {
1092 info_buf->Attributes = cpu_to_le32(origattr);
1093 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1094 current->tgid))
1095 cifsInode->cifsAttrs = origattr;
1096 }
1097
1098 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001099}
1100
Steve Frenchb7ca6922012-08-03 08:43:01 -05001101/* copied from fs/nfs/dir.c with small changes */
1102static void
1103cifs_drop_nlink(struct inode *inode)
1104{
1105 spin_lock(&inode->i_lock);
1106 if (inode->i_nlink > 0)
1107 drop_nlink(inode);
1108 spin_unlock(&inode->i_lock);
1109}
Steve Frenchff694522009-04-20 19:45:13 +00001110
1111/*
1112 * If dentry->d_inode is null (usually meaning the cached dentry
1113 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001114 * if that fails we can not attempt the fall back mechanisms on EACCESS
1115 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001116 * unlink on negative dentries currently.
1117 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001118int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
1120 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001121 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001123 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001124 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001125 struct super_block *sb = dir->i_sb;
1126 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001127 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001128 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001129 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001130 struct iattr *attrs = NULL;
1131 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
Joe Perchesf96637b2013-05-04 22:12:25 -05001133 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134
Jeff Layton7ffec372010-09-29 19:51:11 -04001135 tlink = cifs_sb_tlink(cifs_sb);
1136 if (IS_ERR(tlink))
1137 return PTR_ERR(tlink);
1138 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001139 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001140
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001141 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Jeff Layton5f0319a2008-09-16 14:05:16 -04001143 /* Unlink can be called from rename so we can not take the
1144 * sb->s_vfs_rename_mutex here */
1145 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301147 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001148 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 }
Steve French2d785a52007-07-15 01:48:57 +00001150
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001151 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1152 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001153 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001154 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1155 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesf96637b2013-05-04 22:12:25 -05001156 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001157 if ((rc == 0) || (rc == -ENOENT))
1158 goto psx_del_no_retry;
1159 }
1160
Steve French60502472008-10-07 18:42:52 +00001161retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001162 if (!server->ops->unlink) {
1163 rc = -ENOSYS;
1164 goto psx_del_no_retry;
1165 }
1166
1167 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001168
Steve French2d785a52007-07-15 01:48:57 +00001169psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001171 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001172 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001174 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001175 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001176 if (server->ops->rename_pending_delete) {
1177 rc = server->ops->rename_pending_delete(full_path,
1178 dentry, xid);
1179 if (rc == 0)
1180 cifs_drop_nlink(inode);
1181 }
Steve Frenchff694522009-04-20 19:45:13 +00001182 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001183 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1184 if (attrs == NULL) {
1185 rc = -ENOMEM;
1186 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 }
Steve French388e57b2008-09-16 23:50:58 +00001188
1189 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001190 cifs_inode = CIFS_I(inode);
1191 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001192 if (origattr == 0)
1193 origattr |= ATTR_NORMAL;
1194 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001195 if (dosattr == 0)
1196 dosattr |= ATTR_NORMAL;
1197 dosattr |= ATTR_HIDDEN;
1198
1199 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001200 if (rc != 0)
1201 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001202
1203 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 }
Steve French60502472008-10-07 18:42:52 +00001205
1206 /* undo the setattr if we errored out and it's needed */
1207 if (rc != 0 && dosattr != 0)
1208 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1209
Steve French388e57b2008-09-16 23:50:58 +00001210out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001211 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001212 cifs_inode = CIFS_I(inode);
1213 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001214 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001215 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001216 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001217 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001218 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001219 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001220unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001222 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001223 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001224 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 return rc;
1226}
1227
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001228static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001229cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001230 const char *full_path, struct cifs_sb_info *cifs_sb,
1231 struct cifs_tcon *tcon, const unsigned int xid)
1232{
1233 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001234 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001235
1236 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001237 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001238 xid);
1239 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001240 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1241 xid, NULL);
1242
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001243 if (rc)
1244 return rc;
1245
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001246 /*
1247 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001248 * from the server or was set bogus. Also, since this is a brand new
1249 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001250 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001251 if (inode->i_nlink < 2)
1252 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001253 mode &= ~current_umask();
1254 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001255 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001256 mode |= S_ISGID;
1257
1258 if (tcon->unix_ext) {
1259 struct cifs_unix_set_info_args args = {
1260 .mode = mode,
1261 .ctime = NO_CHANGE_64,
1262 .atime = NO_CHANGE_64,
1263 .mtime = NO_CHANGE_64,
1264 .device = 0,
1265 };
1266 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001267 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001268 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001269 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001270 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001271 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001272 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001273 args.uid = INVALID_UID; /* no change */
1274 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001275 }
1276 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1277 cifs_sb->local_nls,
1278 cifs_sb->mnt_cifs_flags &
1279 CIFS_MOUNT_MAP_SPECIAL_CHR);
1280 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001281 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001282 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001283 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001284 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001285 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001286 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1287 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001288
Jeff Layton101b92d2012-09-19 06:22:45 -07001289 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1290 inode->i_uid = current_fsuid();
1291 if (inode->i_mode & S_ISGID)
1292 inode->i_gid = parent->i_gid;
1293 else
1294 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001295 }
1296 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001297 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001298 return rc;
1299}
1300
1301static int
1302cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1303 const char *full_path, struct cifs_sb_info *cifs_sb,
1304 struct cifs_tcon *tcon, const unsigned int xid)
1305{
1306 int rc = 0;
1307 u32 oplock = 0;
1308 FILE_UNIX_BASIC_INFO *info = NULL;
1309 struct inode *newinode = NULL;
1310 struct cifs_fattr fattr;
1311
1312 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1313 if (info == NULL) {
1314 rc = -ENOMEM;
1315 goto posix_mkdir_out;
1316 }
1317
1318 mode &= ~current_umask();
1319 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1320 NULL /* netfid */, info, &oplock, full_path,
1321 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1322 CIFS_MOUNT_MAP_SPECIAL_CHR);
1323 if (rc == -EOPNOTSUPP)
1324 goto posix_mkdir_out;
1325 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001326 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001327 d_drop(dentry);
1328 goto posix_mkdir_out;
1329 }
1330
1331 if (info->Type == cpu_to_le32(-1))
1332 /* no return info, go query for it */
1333 goto posix_mkdir_get_info;
1334 /*
1335 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1336 * need to set uid/gid.
1337 */
1338
1339 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1340 cifs_fill_uniqueid(inode->i_sb, &fattr);
1341 newinode = cifs_iget(inode->i_sb, &fattr);
1342 if (!newinode)
1343 goto posix_mkdir_get_info;
1344
1345 d_instantiate(dentry, newinode);
1346
1347#ifdef CONFIG_CIFS_DEBUG2
Joe Perchesf96637b2013-05-04 22:12:25 -05001348 cifs_dbg(FYI, "instantiated dentry %p %s to inode %p\n",
1349 dentry, dentry->d_name.name, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001350
1351 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001352 cifs_dbg(FYI, "unexpected number of links %d\n",
1353 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001354#endif
1355
1356posix_mkdir_out:
1357 kfree(info);
1358 return rc;
1359posix_mkdir_get_info:
1360 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1361 xid);
1362 goto posix_mkdir_out;
1363}
1364
Al Viro18bb1db2011-07-26 01:41:39 -04001365int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001367 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001368 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001370 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001371 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001372 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001373 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
Joe Perchesf96637b2013-05-04 22:12:25 -05001375 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1376 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001379 tlink = cifs_sb_tlink(cifs_sb);
1380 if (IS_ERR(tlink))
1381 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001382 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001383
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001384 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
Steve French7f573562005-08-30 11:32:14 -07001386 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301388 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001389 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 }
Steve French50c2f752007-07-13 00:33:32 +00001391
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001392 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1393 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001394 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1395 tcon, xid);
1396 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001397 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001398 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001399
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001400 server = tcon->ses->server;
1401
1402 if (!server->ops->mkdir) {
1403 rc = -ENOSYS;
1404 goto mkdir_out;
1405 }
1406
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001408 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001410 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001412 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001414
1415 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1416 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001417mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001418 /*
1419 * Force revalidate to get parent dir info when needed since cached
1420 * attributes are invalid now.
1421 */
1422 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001424 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001425 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 return rc;
1427}
1428
1429int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1430{
1431 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001432 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001434 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001435 struct cifs_tcon *tcon;
1436 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 char *full_path = NULL;
1438 struct cifsInodeInfo *cifsInode;
1439
Joe Perchesf96637b2013-05-04 22:12:25 -05001440 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001442 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Steve French7f573562005-08-30 11:32:14 -07001444 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301446 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001447 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 }
1449
Jeff Layton7ffec372010-09-29 19:51:11 -04001450 cifs_sb = CIFS_SB(inode->i_sb);
1451 tlink = cifs_sb_tlink(cifs_sb);
1452 if (IS_ERR(tlink)) {
1453 rc = PTR_ERR(tlink);
1454 goto rmdir_exit;
1455 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001456 tcon = tlink_tcon(tlink);
1457 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001458
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001459 if (!server->ops->rmdir) {
1460 rc = -ENOSYS;
1461 cifs_put_tlink(tlink);
1462 goto rmdir_exit;
1463 }
1464
1465 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001466 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
1468 if (!rc) {
Steve French3677db12007-02-26 16:46:11 +00001469 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001470 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001471 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001472 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 }
1474
1475 cifsInode = CIFS_I(direntry->d_inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001476 /* force revalidate to go get info when needed */
1477 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001478
1479 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001480 /*
1481 * Force revalidate to get parent dir info when needed since cached
1482 * attributes are invalid now.
1483 */
1484 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001485
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1487 current_fs_time(inode->i_sb);
1488
Jeff Layton7ffec372010-09-29 19:51:11 -04001489rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001491 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 return rc;
1493}
1494
Steve Frenchee2fd962008-09-23 18:23:33 +00001495static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001496cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1497 const char *from_path, struct dentry *to_dentry,
1498 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001499{
1500 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001501 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001502 struct cifs_tcon *tcon;
1503 struct TCP_Server_Info *server;
Steve Frenchee2fd962008-09-23 18:23:33 +00001504 __u16 srcfid;
1505 int oplock, rc;
1506
Jeff Layton7ffec372010-09-29 19:51:11 -04001507 tlink = cifs_sb_tlink(cifs_sb);
1508 if (IS_ERR(tlink))
1509 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001510 tcon = tlink_tcon(tlink);
1511 server = tcon->ses->server;
1512
1513 if (!server->ops->rename)
1514 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001515
Steve Frenchee2fd962008-09-23 18:23:33 +00001516 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001517 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001518
1519 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001520 * Don't bother with rename by filehandle unless file is busy and
1521 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001522 * rename by filehandle to various Windows servers.
1523 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001524 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001525 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001526
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001527 /* open-file renames don't work across directories */
1528 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001529 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001530
Steve Frenchee2fd962008-09-23 18:23:33 +00001531 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001532 rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE,
Steve Frenchee2fd962008-09-23 18:23:33 +00001533 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1534 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1535 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchee2fd962008-09-23 18:23:33 +00001536 if (rc == 0) {
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001537 rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001538 (const char *) to_dentry->d_name.name,
1539 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1540 CIFS_MOUNT_MAP_SPECIAL_CHR);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001541 CIFSSMBClose(xid, tcon, srcfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001542 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001543do_rename_exit:
1544 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001545 return rc;
1546}
1547
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001548int
1549cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1550 struct inode *target_dir, struct dentry *target_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001552 char *from_name = NULL;
1553 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001554 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001555 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001556 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001557 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1558 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001559 unsigned int xid;
1560 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
Jeff Layton639e7a92010-09-03 11:50:09 -04001562 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001563 tlink = cifs_sb_tlink(cifs_sb);
1564 if (IS_ERR(tlink))
1565 return PTR_ERR(tlink);
1566 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001568 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001569
1570 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001571 * we already have the rename sem so we do not need to
1572 * grab it again here to protect the path integrity
1573 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001574 from_name = build_path_from_dentry(source_dentry);
1575 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 rc = -ENOMEM;
1577 goto cifs_rename_exit;
1578 }
1579
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001580 to_name = build_path_from_dentry(target_dentry);
1581 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001582 rc = -ENOMEM;
1583 goto cifs_rename_exit;
1584 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001586 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1587 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001588
Jeff Layton14121bd2008-10-20 14:45:22 -04001589 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001590 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001591 * Are src and dst hardlinks of same inode? We can only tell
1592 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001593 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001594 info_buf_source =
1595 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1596 GFP_KERNEL);
1597 if (info_buf_source == NULL) {
1598 rc = -ENOMEM;
1599 goto cifs_rename_exit;
1600 }
1601
1602 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001603 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1604 info_buf_source,
1605 cifs_sb->local_nls,
1606 cifs_sb->mnt_cifs_flags &
1607 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton8d281ef2008-10-22 13:57:01 -04001608 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001609 goto unlink_target;
1610
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001611 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1612 info_buf_target,
1613 cifs_sb->local_nls,
1614 cifs_sb->mnt_cifs_flags &
1615 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton14121bd2008-10-20 14:45:22 -04001616
Jeff Layton8d281ef2008-10-22 13:57:01 -04001617 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001618 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001619 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001620 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001621 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001622 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001623 }
1624 /*
1625 * else ... BB we could add the same check for Windows by
1626 * checking the UniqueId via FILE_INTERNAL_INFO
1627 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001628
Jeff Layton14121bd2008-10-20 14:45:22 -04001629unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001630 /* Try unlinking the target dentry if it's not negative */
1631 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Jeff Layton8d281ef2008-10-22 13:57:01 -04001632 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001633 if (tmprc)
1634 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001635 rc = cifs_do_rename(xid, source_dentry, from_name,
1636 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 }
1638
1639cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001640 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001641 kfree(from_name);
1642 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001643 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001644 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 return rc;
1646}
1647
Jeff Laytondf2cf172010-02-12 07:44:16 -05001648static bool
1649cifs_inode_needs_reval(struct inode *inode)
1650{
1651 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301652 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001653
1654 if (cifs_i->clientCanCacheRead)
1655 return false;
1656
1657 if (!lookupCacheEnabled)
1658 return true;
1659
1660 if (cifs_i->time == 0)
1661 return true;
1662
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301663 if (!time_in_range(jiffies, cifs_i->time,
1664 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001665 return true;
1666
Jeff Laytondb192722010-05-17 14:51:49 -04001667 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301668 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001669 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1670 return true;
1671
Jeff Laytondf2cf172010-02-12 07:44:16 -05001672 return false;
1673}
1674
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301675/*
1676 * Zap the cache. Called when invalid_mapping flag is set.
1677 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001678int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001679cifs_invalidate_mapping(struct inode *inode)
1680{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001681 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001682 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1683
1684 cifs_i->invalid_mapping = false;
1685
Jeff Laytondf2cf172010-02-12 07:44:16 -05001686 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001687 rc = invalidate_inode_pages2(inode->i_mapping);
1688 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001689 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1690 __func__, inode);
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001691 cifs_i->invalid_mapping = true;
1692 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001693 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001694
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301695 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001696 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001697}
1698
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001699int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001700{
1701 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001702 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001703 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001704
1705 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001706 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001707
Jeff Layton13cfb732010-09-29 19:51:11 -04001708 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001709 rc = cifs_get_file_info_unix(filp);
1710 else
1711 rc = cifs_get_file_info(filp);
1712
Jeff Laytonabab0952010-02-12 07:44:18 -05001713 return rc;
1714}
1715
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001716int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001718 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001719 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001720 struct inode *inode = dentry->d_inode;
1721 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001722 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Jeff Laytondf2cf172010-02-12 07:44:16 -05001724 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 return -ENOENT;
1726
Jeff Laytondf2cf172010-02-12 07:44:16 -05001727 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001728 return rc;
1729
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001730 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
1732 /* can not safely grab the rename sem here if rename calls revalidate
1733 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001734 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301736 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001737 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001739
Joe Perchesf96637b2013-05-04 22:12:25 -05001740 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1741 full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001742 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743
Jeff Layton0d424ad2010-09-20 16:01:35 -07001744 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001745 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1746 else
1747 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1748 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001750out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001752 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 return rc;
1754}
1755
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001756int cifs_revalidate_file(struct file *filp)
1757{
1758 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001759 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001760
1761 rc = cifs_revalidate_file_attr(filp);
1762 if (rc)
1763 return rc;
1764
1765 if (CIFS_I(inode)->invalid_mapping)
1766 rc = cifs_invalidate_mapping(inode);
1767 return rc;
1768}
1769
1770/* revalidate a dentry's inode attributes */
1771int cifs_revalidate_dentry(struct dentry *dentry)
1772{
1773 int rc;
1774 struct inode *inode = dentry->d_inode;
1775
1776 rc = cifs_revalidate_dentry_attr(dentry);
1777 if (rc)
1778 return rc;
1779
1780 if (CIFS_I(inode)->invalid_mapping)
1781 rc = cifs_invalidate_mapping(inode);
1782 return rc;
1783}
1784
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001786 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001788 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001789 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001790 struct inode *inode = dentry->d_inode;
1791 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001792
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001793 /*
1794 * We need to be sure that all dirty pages are written and the server
1795 * has actual ctime, mtime and file length.
1796 */
1797 if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
1798 inode->i_mapping->nrpages != 0) {
1799 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001800 if (rc) {
1801 mapping_set_error(inode->i_mapping, rc);
1802 return rc;
1803 }
Steve French5fe14c82006-11-07 19:26:33 +00001804 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001805
1806 rc = cifs_revalidate_dentry_attr(dentry);
1807 if (rc)
1808 return rc;
1809
1810 generic_fillattr(inode, stat);
1811 stat->blksize = CIFS_MAX_MSGSIZE;
1812 stat->ino = CIFS_I(inode)->uniqueid;
1813
1814 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001815 * If on a multiuser mount without unix extensions or cifsacl being
1816 * enabled, and the admin hasn't overridden them, set the ownership
1817 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001818 */
1819 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001820 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001821 !tcon->unix_ext) {
1822 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1823 stat->uid = current_fsuid();
1824 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1825 stat->gid = current_fsgid();
1826 }
1827 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828}
1829
1830static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1831{
1832 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1833 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1834 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 int rc = 0;
1836
1837 page = grab_cache_page(mapping, index);
1838 if (!page)
1839 return -ENOMEM;
1840
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001841 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 unlock_page(page);
1843 page_cache_release(page);
1844 return rc;
1845}
1846
Christoph Hellwig1b947462010-07-18 17:51:21 -04001847static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001848{
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001849 loff_t oldsize;
Steve French3677db12007-02-26 16:46:11 +00001850
Steve Frenchba6a46a2007-02-26 20:06:29 +00001851 spin_lock(&inode->i_lock);
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001852 oldsize = inode->i_size;
Steve French3677db12007-02-26 16:46:11 +00001853 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001854 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001855
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001856 truncate_pagecache(inode, oldsize, offset);
Steve French3677db12007-02-26 16:46:11 +00001857}
1858
Jeff Layton8efdbde2008-07-23 21:28:12 +00001859static int
1860cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001861 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00001862{
1863 int rc;
1864 struct cifsFileInfo *open_file;
1865 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1866 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001867 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001868 struct cifs_tcon *tcon = NULL;
1869 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001870 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001871
1872 /*
1873 * To avoid spurious oplock breaks from server, in the case of
1874 * inodes that we already have open, avoid doing path based
1875 * setting of file size if we can do it by handle.
1876 * This keeps our caching token (oplock) and avoids timeouts
1877 * when the local oplock break takes longer to flush
1878 * writebehind data than the SMB timeout for the SetPathInfo
1879 * request would allow
1880 */
Jeff Layton6508d902010-09-29 19:51:11 -04001881 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001882 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001883 tcon = tlink_tcon(open_file->tlink);
1884 server = tcon->ses->server;
1885 if (server->ops->set_file_size)
1886 rc = server->ops->set_file_size(xid, tcon, open_file,
1887 attrs->ia_size, false);
1888 else
1889 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001890 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05001891 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001892 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1893 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001894
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001895 io_parms.netfid = open_file->fid.netfid;
1896 io_parms.pid = open_file->pid;
1897 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001898 io_parms.offset = 0;
1899 io_parms.length = attrs->ia_size;
1900 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1901 NULL, NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001902 cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001903 }
1904 } else
1905 rc = -EINVAL;
1906
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001907 if (!rc)
1908 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07001909
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001910 if (tcon == NULL) {
1911 tlink = cifs_sb_tlink(cifs_sb);
1912 if (IS_ERR(tlink))
1913 return PTR_ERR(tlink);
1914 tcon = tlink_tcon(tlink);
1915 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001916 }
1917
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001918 /*
1919 * Set file size by pathname rather than by handle either because no
1920 * valid, writeable file handle for it was found or because there was
1921 * an error setting it by handle.
1922 */
1923 if (server->ops->set_path_size)
1924 rc = server->ops->set_path_size(xid, tcon, full_path,
1925 attrs->ia_size, cifs_sb, false);
1926 else
1927 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05001928 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001929 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1930 __u16 netfid;
1931 int oplock = 0;
1932
1933 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
1934 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
1935 &oplock, NULL, cifs_sb->local_nls,
1936 cifs_sb->mnt_cifs_flags &
1937 CIFS_MOUNT_MAP_SPECIAL_CHR);
1938 if (rc == 0) {
1939 unsigned int bytes_written;
1940
1941 io_parms.netfid = netfid;
1942 io_parms.pid = current->tgid;
1943 io_parms.tcon = tcon;
1944 io_parms.offset = 0;
1945 io_parms.length = attrs->ia_size;
1946 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
1947 NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001948 cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001949 CIFSSMBClose(xid, tcon, netfid);
1950 }
1951 }
1952 if (tlink)
1953 cifs_put_tlink(tlink);
1954
1955set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00001956 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001957 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04001958 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001959 cifs_truncate_page(inode->i_mapping, inode->i_size);
1960 }
1961
1962 return rc;
1963}
1964
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001965static int
1966cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1967{
1968 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001969 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001970 char *full_path = NULL;
1971 struct inode *inode = direntry->d_inode;
1972 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1973 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001974 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001975 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001976 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04001977 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001978
Joe Perchesf96637b2013-05-04 22:12:25 -05001979 cifs_dbg(FYI, "setattr_unix on file %s attrs->ia_valid=0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00001980 direntry->d_name.name, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001981
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001982 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001983
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001984 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
1985 attrs->ia_valid |= ATTR_FORCE;
1986
1987 rc = inode_change_ok(inode, attrs);
1988 if (rc < 0)
1989 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001990
1991 full_path = build_path_from_dentry(direntry);
1992 if (full_path == NULL) {
1993 rc = -ENOMEM;
1994 goto out;
1995 }
1996
Jeff Layton0f4d6342009-03-26 13:35:37 -04001997 /*
1998 * Attempt to flush data before changing attributes. We need to do
1999 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2000 * ownership or mode then we may also need to do this. Here, we take
2001 * the safe way out and just do the flush on all setattr requests. If
2002 * the flush returns error, store it to report later and continue.
2003 *
2004 * BB: This should be smarter. Why bother flushing pages that
2005 * will be truncated anyway? Also, should we error out here if
2006 * the flush returns error?
2007 */
2008 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002009 mapping_set_error(inode->i_mapping, rc);
2010 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002011
2012 if (attrs->ia_valid & ATTR_SIZE) {
2013 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2014 if (rc != 0)
2015 goto out;
2016 }
2017
2018 /* skip mode change if it's just for clearing setuid/setgid */
2019 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2020 attrs->ia_valid &= ~ATTR_MODE;
2021
2022 args = kmalloc(sizeof(*args), GFP_KERNEL);
2023 if (args == NULL) {
2024 rc = -ENOMEM;
2025 goto out;
2026 }
2027
2028 /* set up the struct */
2029 if (attrs->ia_valid & ATTR_MODE)
2030 args->mode = attrs->ia_mode;
2031 else
2032 args->mode = NO_CHANGE_64;
2033
2034 if (attrs->ia_valid & ATTR_UID)
2035 args->uid = attrs->ia_uid;
2036 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002037 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002038
2039 if (attrs->ia_valid & ATTR_GID)
2040 args->gid = attrs->ia_gid;
2041 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002042 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002043
2044 if (attrs->ia_valid & ATTR_ATIME)
2045 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2046 else
2047 args->atime = NO_CHANGE_64;
2048
2049 if (attrs->ia_valid & ATTR_MTIME)
2050 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2051 else
2052 args->mtime = NO_CHANGE_64;
2053
2054 if (attrs->ia_valid & ATTR_CTIME)
2055 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2056 else
2057 args->ctime = NO_CHANGE_64;
2058
2059 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002060 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002061 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002062 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002063 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002064 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002065 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002066 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002067 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002068 tlink = cifs_sb_tlink(cifs_sb);
2069 if (IS_ERR(tlink)) {
2070 rc = PTR_ERR(tlink);
2071 goto out;
2072 }
2073 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002074 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002075 cifs_sb->local_nls,
2076 cifs_sb->mnt_cifs_flags &
2077 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002078 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002079 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002080
Christoph Hellwig10257742010-06-04 11:30:02 +02002081 if (rc)
2082 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002083
Christoph Hellwig10257742010-06-04 11:30:02 +02002084 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002085 attrs->ia_size != i_size_read(inode))
2086 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002087
2088 setattr_copy(inode, attrs);
2089 mark_inode_dirty(inode);
2090
2091 /* force revalidate when any of these times are set since some
2092 of the fs types (eg ext3, fat) do not have fine enough
2093 time granularity to match protocol, and we do not have a
2094 a way (yet) to query the server fs's time granularity (and
2095 whether it rounds times down).
2096 */
2097 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2098 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002099out:
2100 kfree(args);
2101 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002102 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002103 return rc;
2104}
2105
Jeff Layton0510eeb2008-08-02 07:26:12 -04002106static int
2107cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002109 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002110 kuid_t uid = INVALID_UID;
2111 kgid_t gid = INVALID_GID;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002112 struct inode *inode = direntry->d_inode;
2113 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002114 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 char *full_path = NULL;
2116 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002117 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002118 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002119
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002120 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121
Joe Perchesf96637b2013-05-04 22:12:25 -05002122 cifs_dbg(FYI, "setattr on file %s attrs->iavalid 0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002123 direntry->d_name.name, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002124
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002125 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2126 attrs->ia_valid |= ATTR_FORCE;
2127
2128 rc = inode_change_ok(inode, attrs);
2129 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002130 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002131 return rc;
Steve French6473a552005-11-29 20:20:10 -08002132 }
Steve French50c2f752007-07-13 00:33:32 +00002133
Steve French7f573562005-08-30 11:32:14 -07002134 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302136 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002137 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302138 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140
Jeff Layton0f4d6342009-03-26 13:35:37 -04002141 /*
2142 * Attempt to flush data before changing attributes. We need to do
2143 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2144 * ownership or mode then we may also need to do this. Here, we take
2145 * the safe way out and just do the flush on all setattr requests. If
2146 * the flush returns error, store it to report later and continue.
2147 *
2148 * BB: This should be smarter. Why bother flushing pages that
2149 * will be truncated anyway? Also, should we error out here if
2150 * the flush returns error?
2151 */
2152 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002153 mapping_set_error(inode->i_mapping, rc);
2154 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002155
Steve French50531442008-03-14 19:21:31 +00002156 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002157 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2158 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002159 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002161
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002162 if (attrs->ia_valid & ATTR_UID)
2163 uid = attrs->ia_uid;
2164
2165 if (attrs->ia_valid & ATTR_GID)
2166 gid = attrs->ia_gid;
2167
2168#ifdef CONFIG_CIFS_ACL
2169 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002170 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002171 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2172 uid, gid);
2173 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002174 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2175 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002176 goto cifs_setattr_exit;
2177 }
2178 }
2179 } else
2180#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002181 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002182 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183
Jeff Laytond32c4f22007-10-18 03:05:22 -07002184 /* skip mode change if it's just for clearing setuid/setgid */
2185 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2186 attrs->ia_valid &= ~ATTR_MODE;
2187
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002190 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002191#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002192 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002193 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002194 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002195 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002196 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2197 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002198 goto cifs_setattr_exit;
2199 }
2200 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002201#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002202 if (((mode & S_IWUGO) == 0) &&
2203 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002204
2205 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2206
Jeff Layton51328612008-05-22 09:33:34 -04002207 /* fix up mode if we're not using dynperm */
2208 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2209 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2210 } else if ((mode & S_IWUGO) &&
2211 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002212
2213 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2214 /* Attributes of 0 are ignored */
2215 if (dosattr == 0)
2216 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002217
2218 /* reset local inode permissions to normal */
2219 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2220 attrs->ia_mode &= ~(S_IALLUGO);
2221 if (S_ISDIR(inode->i_mode))
2222 attrs->ia_mode |=
2223 cifs_sb->mnt_dir_mode;
2224 else
2225 attrs->ia_mode |=
2226 cifs_sb->mnt_file_mode;
2227 }
2228 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2229 /* ignore mode change - ATTR_READONLY hasn't changed */
2230 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 }
2233
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002234 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2235 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2236 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2237 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238
Steve Frenche30dcf32005-09-20 20:49:16 -07002239 /* Even if error on time set, no sense failing the call if
2240 the server would set the time to a reasonable value anyway,
2241 and this check ensures that we are not being called from
2242 sys_utimes in which case we ought to fail the call back to
2243 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002244 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002245 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002246 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 }
2248
2249 /* do not need local check to inode_check_ok since the server does
2250 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002251 if (rc)
2252 goto cifs_setattr_exit;
2253
2254 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002255 attrs->ia_size != i_size_read(inode))
2256 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002257
2258 setattr_copy(inode, attrs);
2259 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002260
Steve Frenche30dcf32005-09-20 20:49:16 -07002261cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002263 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 return rc;
2265}
2266
Jeff Layton0510eeb2008-08-02 07:26:12 -04002267int
2268cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2269{
2270 struct inode *inode = direntry->d_inode;
2271 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002272 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002273
2274 if (pTcon->unix_ext)
2275 return cifs_setattr_unix(direntry, attrs);
2276
2277 return cifs_setattr_nounix(direntry, attrs);
2278
2279 /* BB: add cifs_setattr_legacy for really old servers */
2280}
2281
Steve French99ee4db2007-02-27 05:35:17 +00002282#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283void cifs_delete_inode(struct inode *inode)
2284{
Joe Perchesf96637b2013-05-04 22:12:25 -05002285 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 /* may have to add back in if and when safe distributed caching of
2287 directories added e.g. via FindNotify */
2288}
Steve French99ee4db2007-02-27 05:35:17 +00002289#endif