blob: 9d463501348f794283585d03f65beab1b4dfb357 [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;
Jeff Laytonc2b93e02013-05-07 11:28:31 -0400174 if (inode->i_state & I_NEW)
175 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000176}
177
Jeff Layton4065c802010-05-17 07:18:58 -0400178void
179cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
180{
181 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
182
183 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
184 return;
185
186 fattr->cf_uniqueid = iunique(sb, ROOT_I);
187}
188
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400189/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
190void
191cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
192 struct cifs_sb_info *cifs_sb)
193{
194 memset(fattr, 0, sizeof(*fattr));
195 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
196 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
197 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
198
199 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
200 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
201 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
202 fattr->cf_mode = le64_to_cpu(info->Permissions);
203
204 /*
205 * Since we set the inode type below we need to mask off
206 * to avoid strange results if bits set above.
207 */
208 fattr->cf_mode &= ~S_IFMT;
209 switch (le32_to_cpu(info->Type)) {
210 case UNIX_FILE:
211 fattr->cf_mode |= S_IFREG;
212 fattr->cf_dtype = DT_REG;
213 break;
214 case UNIX_SYMLINK:
215 fattr->cf_mode |= S_IFLNK;
216 fattr->cf_dtype = DT_LNK;
217 break;
218 case UNIX_DIR:
219 fattr->cf_mode |= S_IFDIR;
220 fattr->cf_dtype = DT_DIR;
221 break;
222 case UNIX_CHARDEV:
223 fattr->cf_mode |= S_IFCHR;
224 fattr->cf_dtype = DT_CHR;
225 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
226 le64_to_cpu(info->DevMinor) & MINORMASK);
227 break;
228 case UNIX_BLOCKDEV:
229 fattr->cf_mode |= S_IFBLK;
230 fattr->cf_dtype = DT_BLK;
231 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
232 le64_to_cpu(info->DevMinor) & MINORMASK);
233 break;
234 case UNIX_FIFO:
235 fattr->cf_mode |= S_IFIFO;
236 fattr->cf_dtype = DT_FIFO;
237 break;
238 case UNIX_SOCKET:
239 fattr->cf_mode |= S_IFSOCK;
240 fattr->cf_dtype = DT_SOCK;
241 break;
242 default:
243 /* safest to call it a file if we do not know */
244 fattr->cf_mode |= S_IFREG;
245 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500246 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400247 break;
248 }
249
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800250 fattr->cf_uid = cifs_sb->mnt_uid;
251 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
252 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800253 if (id < ((uid_t)-1)) {
254 kuid_t uid = make_kuid(&init_user_ns, id);
255 if (uid_valid(uid))
256 fattr->cf_uid = uid;
257 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800258 }
259
260 fattr->cf_gid = cifs_sb->mnt_gid;
261 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
262 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800263 if (id < ((gid_t)-1)) {
264 kgid_t gid = make_kgid(&init_user_ns, id);
265 if (gid_valid(gid))
266 fattr->cf_gid = gid;
267 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800268 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400269
270 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
271}
Steve Frenchb9a32602008-05-20 21:52:32 +0000272
273/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400274 * Fill a cifs_fattr struct with fake inode info.
275 *
276 * Needed to setup cifs_fattr data for the directory which is the
277 * junction to the new submount (ie to setup the fake directory
278 * which represents a DFS referral).
Steve Frenchb9a32602008-05-20 21:52:32 +0000279 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000280static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400281cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000282{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400283 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000284
Joe Perchesf96637b2013-05-04 22:12:25 -0500285 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000286
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400287 memset(fattr, 0, sizeof(*fattr));
288 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
289 fattr->cf_uid = cifs_sb->mnt_uid;
290 fattr->cf_gid = cifs_sb->mnt_gid;
291 fattr->cf_atime = CURRENT_TIME;
292 fattr->cf_ctime = CURRENT_TIME;
293 fattr->cf_mtime = CURRENT_TIME;
294 fattr->cf_nlink = 2;
295 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000296}
297
Pavel Shilovsky4ad650442012-09-18 16:20:26 -0700298static int
299cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500300{
301 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400302 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500303 FILE_UNIX_BASIC_INFO find_data;
304 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500305 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500306 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700307 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000308 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500309
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400310 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700311 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500312 if (!rc) {
313 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
314 } else if (rc == -EREMOTE) {
315 cifs_create_dfs_fattr(&fattr, inode->i_sb);
316 rc = 0;
317 }
318
319 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400320 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500321 return rc;
322}
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400325 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400326 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400328 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000329 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400330 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000331 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400332 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
Joe Perchesf96637b2013-05-04 22:12:25 -0500335 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000336
Jeff Layton7ffec372010-09-29 19:51:11 -0400337 tlink = cifs_sb_tlink(cifs_sb);
338 if (IS_ERR(tlink))
339 return PTR_ERR(tlink);
340 tcon = tlink_tcon(tlink);
341
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400343 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Steve French737b7582005-04-28 22:41:06 -0700344 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
345 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400346 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400347
348 if (!rc) {
349 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
350 } else if (rc == -EREMOTE) {
351 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700352 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400353 } else {
354 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000355 }
356
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200357 /* check for Minshall+French symlinks */
358 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
359 int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
360 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500361 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200362 }
363
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400364 if (*pinode == NULL) {
365 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400366 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400367 *pinode = cifs_iget(sb, &fattr);
368 if (!*pinode)
369 rc = -ENOMEM;
370 } else {
371 /* we already have inode, update it */
372 cifs_fattr_to_inode(*pinode, &fattr);
373 }
Steve French0e4bbde2008-05-20 19:50:46 +0000374
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 return rc;
376}
377
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400378static int
379cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400380 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800381{
382 int rc;
Steve French4b18f2a2008-04-29 00:06:05 +0000383 int oplock = 0;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800384 __u16 netfid;
Jeff Layton7ffec372010-09-29 19:51:11 -0400385 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000386 struct cifs_tcon *tcon;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000387 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800388 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800389 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000390 char *pbuf;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800391
392 pbuf = buf;
393
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400394 fattr->cf_mode &= ~S_IFMT;
395
396 if (fattr->cf_eof == 0) {
397 fattr->cf_mode |= S_IFIFO;
398 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800399 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400400 } else if (fattr->cf_eof < 8) {
401 fattr->cf_mode |= S_IFREG;
402 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800403 return -EINVAL; /* EOPNOTSUPP? */
404 }
Steve French50c2f752007-07-13 00:33:32 +0000405
Jeff Layton7ffec372010-09-29 19:51:11 -0400406 tlink = cifs_sb_tlink(cifs_sb);
407 if (IS_ERR(tlink))
408 return PTR_ERR(tlink);
409 tcon = tlink_tcon(tlink);
410
411 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800412 CREATE_NOT_DIR, &netfid, &oplock, NULL,
413 cifs_sb->local_nls,
414 cifs_sb->mnt_cifs_flags &
415 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000416 if (rc == 0) {
Steve Frenchec637e32005-12-12 20:53:18 -0800417 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800418 /* Read header */
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000419 io_parms.netfid = netfid;
420 io_parms.pid = current->tgid;
421 io_parms.tcon = tcon;
422 io_parms.offset = 0;
423 io_parms.length = 24;
424 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
425 &buf_type);
Steve French4523cc32007-04-30 20:13:06 +0000426 if ((rc == 0) && (bytes_read >= 8)) {
427 if (memcmp("IntxBLK", pbuf, 8) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500428 cifs_dbg(FYI, "Block device\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400429 fattr->cf_mode |= S_IFBLK;
430 fattr->cf_dtype = DT_BLK;
Steve French4523cc32007-04-30 20:13:06 +0000431 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800432 /* we have enough to decode dev num */
433 __u64 mjr; /* major */
434 __u64 mnr; /* minor */
435 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
436 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400437 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve French86c96b42005-11-18 20:25:31 -0800438 }
Steve French4523cc32007-04-30 20:13:06 +0000439 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500440 cifs_dbg(FYI, "Char device\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400441 fattr->cf_mode |= S_IFCHR;
442 fattr->cf_dtype = DT_CHR;
Steve French4523cc32007-04-30 20:13:06 +0000443 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800444 /* we have enough to decode dev num */
445 __u64 mjr; /* major */
446 __u64 mnr; /* minor */
447 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
448 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400449 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000450 }
Steve French4523cc32007-04-30 20:13:06 +0000451 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500452 cifs_dbg(FYI, "Symlink\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400453 fattr->cf_mode |= S_IFLNK;
454 fattr->cf_dtype = DT_LNK;
Steve French86c96b42005-11-18 20:25:31 -0800455 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400456 fattr->cf_mode |= S_IFREG; /* file? */
457 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000458 rc = -EOPNOTSUPP;
Steve French86c96b42005-11-18 20:25:31 -0800459 }
Steve French3020a1f2005-11-18 11:31:10 -0800460 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400461 fattr->cf_mode |= S_IFREG; /* then it is a file */
462 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000463 rc = -EOPNOTSUPP; /* or some unknown SFU type */
464 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400465 CIFSSMBClose(xid, tcon, netfid);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800466 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400467 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800468 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800469}
470
Steve French9e294f12005-11-17 16:59:21 -0800471#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
472
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400473/*
474 * Fetch mode bits as provided by SFU.
475 *
476 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
477 */
478static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400479 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800480{
Steve French3020a1f2005-11-18 11:31:10 -0800481#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800482 ssize_t rc;
483 char ea_value[4];
484 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400485 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000486 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800487
Jeff Layton7ffec372010-09-29 19:51:11 -0400488 tlink = cifs_sb_tlink(cifs_sb);
489 if (IS_ERR(tlink))
490 return PTR_ERR(tlink);
491 tcon = tlink_tcon(tlink);
492
Steve French367d9642014-02-01 23:27:18 -0600493 if (tcon->ses->server->ops->query_all_EAs == NULL) {
494 cifs_put_tlink(tlink);
495 return -EOPNOTSUPP;
496 }
497
498 rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
499 "SETFILEBITS", ea_value, 4 /* size of buf */,
500 cifs_sb->local_nls,
501 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400502 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000503 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800504 return (int)rc;
505 else if (rc > 3) {
506 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400507 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500508 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
509 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400510 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500511 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800512 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400513
514 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800515#else
516 return -EOPNOTSUPP;
517#endif
Steve French9e294f12005-11-17 16:59:21 -0800518}
519
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400520/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000521static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400522cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
523 struct cifs_sb_info *cifs_sb, bool adjust_tz)
Steve Frenchb9a32602008-05-20 21:52:32 +0000524{
Steve French96daf2b2011-05-27 04:34:02 +0000525 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700526
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400527 memset(fattr, 0, sizeof(*fattr));
528 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
529 if (info->DeletePending)
530 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000531
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400532 if (info->LastAccessTime)
533 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
534 else
535 fattr->cf_atime = CURRENT_TIME;
536
537 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
538 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
539
540 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700541 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
542 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400543 }
544
545 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
546 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500547 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400548
549 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
550 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
551 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300552 /*
553 * Server can return wrong NumberOfLinks value for directories
554 * when Unix extensions are disabled - fake it.
555 */
556 fattr->cf_nlink = 2;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400557 } else {
558 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
559 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400560
Jeff Laytond0c280d2009-07-09 01:46:44 -0400561 /* clear write bits if ATTR_READONLY is set */
562 if (fattr->cf_cifsattrs & ATTR_READONLY)
563 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400564
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300565 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Steve Frenchcfe24e42013-07-04 14:38:48 -0500566 if (fattr->cf_nlink < 1) {
567 cifs_dbg(1, "replacing bogus file nlink value %u\n",
568 fattr->cf_nlink);
569 fattr->cf_nlink = 1;
570 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300571 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400572
573 fattr->cf_uid = cifs_sb->mnt_uid;
574 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000575}
576
Pavel Shilovsky4ad650442012-09-18 16:20:26 -0700577static int
578cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500579{
580 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400581 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500582 FILE_ALL_INFO find_data;
583 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500584 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500585 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700586 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000587 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad650442012-09-18 16:20:26 -0700588 struct TCP_Server_Info *server = tcon->ses->server;
589
590 if (!server->ops->query_file_info)
591 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500592
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400593 xid = get_xid();
Pavel Shilovsky4ad650442012-09-18 16:20:26 -0700594 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400595 switch (rc) {
596 case 0:
597 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
598 break;
599 case -EREMOTE:
600 cifs_create_dfs_fattr(&fattr, inode->i_sb);
601 rc = 0;
602 break;
603 case -EOPNOTSUPP:
604 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500605 /*
606 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000607 * for now, just skip revalidating and mark inode for
608 * immediate reval.
609 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500610 rc = 0;
611 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400612 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500613 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400614 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500615
616 /*
617 * don't bother with SFU junk here -- just mark inode as needing
618 * revalidation.
619 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500620 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
621 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
622 cifs_fattr_to_inode(inode, &fattr);
623cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400624 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500625 return rc;
626}
627
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400628int
629cifs_get_inode_info(struct inode **inode, const char *full_path,
630 FILE_ALL_INFO *data, struct super_block *sb, int xid,
631 const __u16 *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500633 bool validinum = false;
634 __u16 srchflgs;
635 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400636 struct cifs_tcon *tcon;
637 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400638 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400641 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400642 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500643 struct cifs_search_info *srchinf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Jeff Layton7ffec372010-09-29 19:51:11 -0400645 tlink = cifs_sb_tlink(cifs_sb);
646 if (IS_ERR(tlink))
647 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400648 tcon = tlink_tcon(tlink);
649 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400650
Joe Perchesf96637b2013-05-04 22:12:25 -0500651 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400653 if ((data == NULL) && (*inode != NULL)) {
654 if (CIFS_I(*inode)->clientCanCacheRead) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500655 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400656 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 }
658 }
659
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400660 /* if inode info is not passed, get it from server */
661 if (data == NULL) {
662 if (!server->ops->query_path_info) {
663 rc = -ENOSYS;
664 goto cgii_exit;
665 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400667 if (buf == NULL) {
668 rc = -ENOMEM;
669 goto cgii_exit;
670 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400671 data = (FILE_ALL_INFO *)buf;
672 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
673 data, &adjust_tz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400675
676 if (!rc) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400677 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb,
678 adjust_tz);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400679 } else if (rc == -EREMOTE) {
680 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000681 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500682 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
683 srchinf = kzalloc(sizeof(struct cifs_search_info),
684 GFP_KERNEL);
685 if (srchinf == NULL) {
686 rc = -ENOMEM;
687 goto cgii_exit;
688 }
689
690 srchinf->endOfSearch = false;
691 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
692
693 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
694 CIFS_SEARCH_CLOSE_AT_END |
695 CIFS_SEARCH_BACKUP_SEARCH;
696
697 rc = CIFSFindFirst(xid, tcon, full_path,
698 cifs_sb, NULL, srchflgs, srchinf, false);
699 if (!rc) {
700 data =
701 (FILE_ALL_INFO *)srchinf->srch_entries_start;
702
703 cifs_dir_info_to_fattr(&fattr,
704 (FILE_DIRECTORY_INFO *)data, cifs_sb);
705 fattr.cf_uniqueid = le64_to_cpu(
706 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
707 validinum = true;
708
709 cifs_buf_release(srchinf->ntwrk_buf_start);
710 }
711 kfree(srchinf);
712 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000713 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400715 /*
716 * If an inode wasn't passed in, then get the inode number
717 *
718 * Is an i_ino of zero legal? Can we use that to check if the server
719 * supports returning inode numbers? Are there other sanity checks we
720 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400721 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400722 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000723 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500724 if (validinum == false) {
725 if (server->ops->get_srv_inum)
726 tmprc = server->ops->get_srv_inum(xid,
727 tcon, cifs_sb, full_path,
728 &fattr.cf_uniqueid, data);
729 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500730 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
731 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500732 fattr.cf_uniqueid = iunique(sb, ROOT_I);
733 cifs_autodisable_serverino(cifs_sb);
734 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500735 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500736 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400737 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500738 } else
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400739 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000740
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400741 /* query for SFU type info if supported and needed */
742 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
743 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
744 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
745 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500746 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000747 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000748
Jeff Layton79df1ba2010-12-06 12:52:08 -0500749#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000750 /* fill in 0777 bits from ACL */
751 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400752 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600753 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500754 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
755 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600756 goto cgii_exit;
757 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000758 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500759#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400760
761 /* fill in remaining high mode bits e.g. SUID, VTX */
762 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
763 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
764
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200765 /* check for Minshall+French symlinks */
766 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
767 tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
768 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500769 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200770 }
771
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400772 if (!*inode) {
773 *inode = cifs_iget(sb, &fattr);
774 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400775 rc = -ENOMEM;
776 } else {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400777 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000778 }
779
Igor Mammedov79626702008-03-09 03:44:18 +0000780cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400782 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 return rc;
784}
785
Steve French7f8ed422007-09-28 22:28:55 +0000786static const struct inode_operations cifs_ipc_inode_ops = {
787 .lookup = cifs_lookup,
788};
789
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400790static int
791cifs_find_inode(struct inode *inode, void *opaque)
792{
793 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
794
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400795 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400796 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
797 return 0;
798
Jeff Layton20054bd2011-01-07 11:30:27 -0500799 /* use createtime like an i_generation field */
800 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
801 return 0;
802
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400803 /* don't match inode of different type */
804 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
805 return 0;
806
Jeff Layton5acfec22010-08-02 17:43:54 -0400807 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400808 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400809 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400810
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400811 return 1;
812}
813
814static int
815cifs_init_inode(struct inode *inode, void *opaque)
816{
817 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
818
819 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500820 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400821 return 0;
822}
823
Jeff Layton5acfec22010-08-02 17:43:54 -0400824/*
825 * walk dentry list for an inode and report whether it has aliases that
826 * are hashed. We use this to determine if a directory inode can actually
827 * be used.
828 */
829static bool
830inode_has_hashed_dentries(struct inode *inode)
831{
832 struct dentry *dentry;
833
Nick Piggin873feea2011-01-07 17:50:06 +1100834 spin_lock(&inode->i_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800835 hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400836 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100837 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400838 return true;
839 }
840 }
Nick Piggin873feea2011-01-07 17:50:06 +1100841 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400842 return false;
843}
844
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400845/* Given fattrs, get a corresponding inode */
846struct inode *
847cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
848{
849 unsigned long hash;
850 struct inode *inode;
851
Jeff Layton3d694382010-05-11 14:59:55 -0400852retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -0500853 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400854
855 /* hash down to 32-bits on 32-bit arch */
856 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
857
858 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400859 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400860 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400861 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400862 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400863
864 if (inode_has_hashed_dentries(inode)) {
865 cifs_autodisable_serverino(CIFS_SB(sb));
866 iput(inode);
867 fattr->cf_uniqueid = iunique(sb, ROOT_I);
868 goto retry_iget5_locked;
869 }
Jeff Layton3d694382010-05-11 14:59:55 -0400870 }
871
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400872 cifs_fattr_to_inode(inode, fattr);
873 if (sb->s_flags & MS_NOATIME)
874 inode->i_flags |= S_NOATIME | S_NOCMTIME;
875 if (inode->i_state & I_NEW) {
876 inode->i_ino = hash;
Jeff Layton522440e2010-09-29 09:49:54 -0400877 if (S_ISREG(inode->i_mode))
878 inode->i_data.backing_dev_info = sb->s_bdi;
Steve French0ccd4802010-07-16 04:31:02 +0000879#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530880 /* initialize per-inode cache cookie pointer */
881 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000882#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400883 unlock_new_inode(inode);
884 }
885 }
886
887 return inode;
888}
889
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600891struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400893 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700894 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400895 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800896 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000897 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800898
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400899 xid = get_xid();
Jeff Layton0d424ad2010-09-20 16:01:35 -0700900 if (tcon->unix_ext)
Steve Frenchf87d39d2011-05-27 03:50:55 +0000901 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400902 else
Steve Frenchf87d39d2011-05-27 03:50:55 +0000903 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400904
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000905 if (!inode) {
906 inode = ERR_PTR(rc);
907 goto out;
908 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400909
Steve French0ccd4802010-07-16 04:31:02 +0000910#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530911 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700912 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000913#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530914
Jeff Layton0d424ad2010-09-20 16:01:35 -0700915 if (rc && tcon->ipc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500916 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -0500917 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +0000918 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200919 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +0000920 inode->i_op = &cifs_ipc_inode_ops;
921 inode->i_fop = &simple_dir_operations;
922 inode->i_uid = cifs_sb->mnt_uid;
923 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -0500924 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +0000925 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800926 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000927 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000928 }
929
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000930out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400931 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -0800932 * TODO: This is no longer true
933 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400934 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -0800935 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936}
937
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700938int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400939cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700940 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +0000941{
Steve French388e57b2008-09-16 23:50:58 +0000942 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +0000943 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700944 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +0000945 FILE_BASIC_INFO info_buf;
946
Steve French1adcb712009-02-25 14:19:56 +0000947 if (attrs == NULL)
948 return -EINVAL;
949
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700950 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
951 if (!server->ops->set_file_info)
952 return -ENOSYS;
953
Steve French388e57b2008-09-16 23:50:58 +0000954 if (attrs->ia_valid & ATTR_ATIME) {
955 set_time = true;
956 info_buf.LastAccessTime =
957 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
958 } else
959 info_buf.LastAccessTime = 0;
960
961 if (attrs->ia_valid & ATTR_MTIME) {
962 set_time = true;
963 info_buf.LastWriteTime =
964 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
965 } else
966 info_buf.LastWriteTime = 0;
967
968 /*
969 * Samba throws this field away, but windows may actually use it.
970 * Do not set ctime unless other time stamps are changed explicitly
971 * (i.e. by utimes()) since we would then have a mix of client and
972 * server times.
973 */
974 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500975 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +0000976 info_buf.ChangeTime =
977 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
978 } else
979 info_buf.ChangeTime = 0;
980
981 info_buf.CreationTime = 0; /* don't change */
982 info_buf.Attributes = cpu_to_le32(dosattr);
983
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700984 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +0000985}
986
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400987/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700988 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400989 * and rename it to a random name that hopefully won't conflict with
990 * anything else.
991 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700992int
993cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
994 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400995{
996 int oplock = 0;
997 int rc;
998 __u16 netfid;
Steve French32709582008-10-20 00:44:19 +0000999 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001000 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1001 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001002 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001003 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001004 __u32 dosattr, origattr;
1005 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001006
Jeff Layton7ffec372010-09-29 19:51:11 -04001007 tlink = cifs_sb_tlink(cifs_sb);
1008 if (IS_ERR(tlink))
1009 return PTR_ERR(tlink);
1010 tcon = tlink_tcon(tlink);
1011
Sachin Prabhuc483a982013-03-05 19:25:56 +00001012 /*
1013 * We cannot rename the file if the server doesn't support
1014 * CAP_INFOLEVEL_PASSTHRU
1015 */
1016 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1017 rc = -EBUSY;
1018 goto out;
1019 }
1020
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001021 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001022 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001023 &netfid, &oplock, NULL, cifs_sb->local_nls,
1024 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1025 if (rc != 0)
1026 goto out;
1027
Steve French32709582008-10-20 00:44:19 +00001028 origattr = cifsInode->cifsAttrs;
1029 if (origattr == 0)
1030 origattr |= ATTR_NORMAL;
1031
1032 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001033 if (dosattr == 0)
1034 dosattr |= ATTR_NORMAL;
1035 dosattr |= ATTR_HIDDEN;
1036
Steve French32709582008-10-20 00:44:19 +00001037 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1038 if (dosattr != origattr) {
1039 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1040 if (info_buf == NULL) {
1041 rc = -ENOMEM;
1042 goto out_close;
1043 }
1044 info_buf->Attributes = cpu_to_le32(dosattr);
1045 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1046 current->tgid);
1047 /* although we would like to mark the file hidden
1048 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001049 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001050 cifsInode->cifsAttrs = dosattr;
1051 else
1052 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001053 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001054
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001055 /* rename the file */
1056 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001057 cifs_sb->mnt_cifs_flags &
1058 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French32709582008-10-20 00:44:19 +00001059 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001060 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001061 goto undo_setattr;
1062 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001063
Steve French32709582008-10-20 00:44:19 +00001064 /* try to set DELETE_ON_CLOSE */
1065 if (!cifsInode->delete_pending) {
1066 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
1067 current->tgid);
1068 /*
1069 * some samba versions return -ENOENT when we try to set the
1070 * file disposition here. Likely a samba bug, but work around
1071 * it for now. This means that some cifsXXX files may hang
1072 * around after they shouldn't.
1073 *
1074 * BB: remove this hack after more servers have the fix
1075 */
1076 if (rc == -ENOENT)
1077 rc = 0;
1078 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001079 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001080 goto undo_rename;
1081 }
1082 cifsInode->delete_pending = true;
1083 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001084
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001085out_close:
1086 CIFSSMBClose(xid, tcon, netfid);
1087out:
Steve French32709582008-10-20 00:44:19 +00001088 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001089 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001090 return rc;
Steve French32709582008-10-20 00:44:19 +00001091
1092 /*
1093 * reset everything back to the original state. Don't bother
1094 * dealing with errors here since we can't do anything about
1095 * them anyway.
1096 */
1097undo_rename:
1098 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
1099 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1100 CIFS_MOUNT_MAP_SPECIAL_CHR);
1101undo_setattr:
1102 if (dosattr != origattr) {
1103 info_buf->Attributes = cpu_to_le32(origattr);
1104 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1105 current->tgid))
1106 cifsInode->cifsAttrs = origattr;
1107 }
1108
1109 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001110}
1111
Steve Frenchb7ca6922012-08-03 08:43:01 -05001112/* copied from fs/nfs/dir.c with small changes */
1113static void
1114cifs_drop_nlink(struct inode *inode)
1115{
1116 spin_lock(&inode->i_lock);
1117 if (inode->i_nlink > 0)
1118 drop_nlink(inode);
1119 spin_unlock(&inode->i_lock);
1120}
Steve Frenchff694522009-04-20 19:45:13 +00001121
1122/*
1123 * If dentry->d_inode is null (usually meaning the cached dentry
1124 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001125 * if that fails we can not attempt the fall back mechanisms on EACCESS
1126 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001127 * unlink on negative dentries currently.
1128 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001129int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130{
1131 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001132 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001134 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001135 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001136 struct super_block *sb = dir->i_sb;
1137 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001138 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001139 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001140 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001141 struct iattr *attrs = NULL;
1142 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
Joe Perchesf96637b2013-05-04 22:12:25 -05001144 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
Jeff Layton7ffec372010-09-29 19:51:11 -04001146 tlink = cifs_sb_tlink(cifs_sb);
1147 if (IS_ERR(tlink))
1148 return PTR_ERR(tlink);
1149 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001150 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001151
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001152 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
Jeff Layton5f0319a2008-09-16 14:05:16 -04001154 /* Unlink can be called from rename so we can not take the
1155 * sb->s_vfs_rename_mutex here */
1156 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301158 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001159 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 }
Steve French2d785a52007-07-15 01:48:57 +00001161
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001162 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1163 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001164 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001165 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1166 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesf96637b2013-05-04 22:12:25 -05001167 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001168 if ((rc == 0) || (rc == -ENOENT))
1169 goto psx_del_no_retry;
1170 }
1171
Steve French60502472008-10-07 18:42:52 +00001172retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001173 if (!server->ops->unlink) {
1174 rc = -ENOSYS;
1175 goto psx_del_no_retry;
1176 }
1177
1178 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001179
Steve French2d785a52007-07-15 01:48:57 +00001180psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001182 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001183 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001185 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001186 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001187 if (server->ops->rename_pending_delete) {
1188 rc = server->ops->rename_pending_delete(full_path,
1189 dentry, xid);
1190 if (rc == 0)
1191 cifs_drop_nlink(inode);
1192 }
Steve Frenchff694522009-04-20 19:45:13 +00001193 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001194 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1195 if (attrs == NULL) {
1196 rc = -ENOMEM;
1197 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 }
Steve French388e57b2008-09-16 23:50:58 +00001199
1200 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001201 cifs_inode = CIFS_I(inode);
1202 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001203 if (origattr == 0)
1204 origattr |= ATTR_NORMAL;
1205 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001206 if (dosattr == 0)
1207 dosattr |= ATTR_NORMAL;
1208 dosattr |= ATTR_HIDDEN;
1209
1210 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001211 if (rc != 0)
1212 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001213
1214 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 }
Steve French60502472008-10-07 18:42:52 +00001216
1217 /* undo the setattr if we errored out and it's needed */
1218 if (rc != 0 && dosattr != 0)
1219 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1220
Steve French388e57b2008-09-16 23:50:58 +00001221out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001222 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001223 cifs_inode = CIFS_I(inode);
1224 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001225 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001226 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001227 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001228 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001229 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001230 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001231unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001233 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001234 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001235 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 return rc;
1237}
1238
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001239static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001240cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001241 const char *full_path, struct cifs_sb_info *cifs_sb,
1242 struct cifs_tcon *tcon, const unsigned int xid)
1243{
1244 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001245 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001246
1247 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001248 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001249 xid);
1250 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001251 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1252 xid, NULL);
1253
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001254 if (rc)
1255 return rc;
1256
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001257 /*
1258 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001259 * from the server or was set bogus. Also, since this is a brand new
1260 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001261 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001262 if (inode->i_nlink < 2)
1263 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001264 mode &= ~current_umask();
1265 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001266 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001267 mode |= S_ISGID;
1268
1269 if (tcon->unix_ext) {
1270 struct cifs_unix_set_info_args args = {
1271 .mode = mode,
1272 .ctime = NO_CHANGE_64,
1273 .atime = NO_CHANGE_64,
1274 .mtime = NO_CHANGE_64,
1275 .device = 0,
1276 };
1277 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001278 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001279 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001280 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001281 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001282 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001283 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001284 args.uid = INVALID_UID; /* no change */
1285 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001286 }
1287 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1288 cifs_sb->local_nls,
1289 cifs_sb->mnt_cifs_flags &
1290 CIFS_MOUNT_MAP_SPECIAL_CHR);
1291 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001292 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001293 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001294 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001295 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001296 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001297 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1298 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001299
Jeff Layton101b92d2012-09-19 06:22:45 -07001300 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1301 inode->i_uid = current_fsuid();
1302 if (inode->i_mode & S_ISGID)
1303 inode->i_gid = parent->i_gid;
1304 else
1305 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001306 }
1307 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001308 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001309 return rc;
1310}
1311
1312static int
1313cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1314 const char *full_path, struct cifs_sb_info *cifs_sb,
1315 struct cifs_tcon *tcon, const unsigned int xid)
1316{
1317 int rc = 0;
1318 u32 oplock = 0;
1319 FILE_UNIX_BASIC_INFO *info = NULL;
1320 struct inode *newinode = NULL;
1321 struct cifs_fattr fattr;
1322
1323 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1324 if (info == NULL) {
1325 rc = -ENOMEM;
1326 goto posix_mkdir_out;
1327 }
1328
1329 mode &= ~current_umask();
1330 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1331 NULL /* netfid */, info, &oplock, full_path,
1332 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1333 CIFS_MOUNT_MAP_SPECIAL_CHR);
1334 if (rc == -EOPNOTSUPP)
1335 goto posix_mkdir_out;
1336 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001337 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001338 d_drop(dentry);
1339 goto posix_mkdir_out;
1340 }
1341
1342 if (info->Type == cpu_to_le32(-1))
1343 /* no return info, go query for it */
1344 goto posix_mkdir_get_info;
1345 /*
1346 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1347 * need to set uid/gid.
1348 */
1349
1350 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1351 cifs_fill_uniqueid(inode->i_sb, &fattr);
1352 newinode = cifs_iget(inode->i_sb, &fattr);
1353 if (!newinode)
1354 goto posix_mkdir_get_info;
1355
1356 d_instantiate(dentry, newinode);
1357
1358#ifdef CONFIG_CIFS_DEBUG2
Joe Perchesf96637b2013-05-04 22:12:25 -05001359 cifs_dbg(FYI, "instantiated dentry %p %s to inode %p\n",
1360 dentry, dentry->d_name.name, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001361
1362 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001363 cifs_dbg(FYI, "unexpected number of links %d\n",
1364 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001365#endif
1366
1367posix_mkdir_out:
1368 kfree(info);
1369 return rc;
1370posix_mkdir_get_info:
1371 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1372 xid);
1373 goto posix_mkdir_out;
1374}
1375
Al Viro18bb1db2011-07-26 01:41:39 -04001376int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001378 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001379 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001381 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001382 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001383 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001384 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
Joe Perchesf96637b2013-05-04 22:12:25 -05001386 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1387 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001390 tlink = cifs_sb_tlink(cifs_sb);
1391 if (IS_ERR(tlink))
1392 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001393 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001394
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001395 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
Steve French7f573562005-08-30 11:32:14 -07001397 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301399 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001400 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 }
Steve French50c2f752007-07-13 00:33:32 +00001402
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001403 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1404 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001405 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1406 tcon, xid);
1407 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001408 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001409 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001410
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001411 server = tcon->ses->server;
1412
1413 if (!server->ops->mkdir) {
1414 rc = -ENOSYS;
1415 goto mkdir_out;
1416 }
1417
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001419 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001421 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001423 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001425
1426 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1427 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001428mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001429 /*
1430 * Force revalidate to get parent dir info when needed since cached
1431 * attributes are invalid now.
1432 */
1433 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001435 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001436 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 return rc;
1438}
1439
1440int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1441{
1442 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001443 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001445 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001446 struct cifs_tcon *tcon;
1447 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 char *full_path = NULL;
1449 struct cifsInodeInfo *cifsInode;
1450
Joe Perchesf96637b2013-05-04 22:12:25 -05001451 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001453 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
Steve French7f573562005-08-30 11:32:14 -07001455 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301457 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001458 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 }
1460
Jeff Layton7ffec372010-09-29 19:51:11 -04001461 cifs_sb = CIFS_SB(inode->i_sb);
1462 tlink = cifs_sb_tlink(cifs_sb);
1463 if (IS_ERR(tlink)) {
1464 rc = PTR_ERR(tlink);
1465 goto rmdir_exit;
1466 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001467 tcon = tlink_tcon(tlink);
1468 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001469
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001470 if (!server->ops->rmdir) {
1471 rc = -ENOSYS;
1472 cifs_put_tlink(tlink);
1473 goto rmdir_exit;
1474 }
1475
1476 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001477 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
1479 if (!rc) {
Steve French3677db12007-02-26 16:46:11 +00001480 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001481 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001482 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001483 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 }
1485
1486 cifsInode = CIFS_I(direntry->d_inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001487 /* force revalidate to go get info when needed */
1488 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001489
1490 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001491 /*
1492 * Force revalidate to get parent dir info when needed since cached
1493 * attributes are invalid now.
1494 */
1495 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001496
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1498 current_fs_time(inode->i_sb);
1499
Jeff Layton7ffec372010-09-29 19:51:11 -04001500rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001502 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 return rc;
1504}
1505
Steve Frenchee2fd962008-09-23 18:23:33 +00001506static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001507cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1508 const char *from_path, struct dentry *to_dentry,
1509 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001510{
1511 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001512 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001513 struct cifs_tcon *tcon;
1514 struct TCP_Server_Info *server;
Steve Frenchee2fd962008-09-23 18:23:33 +00001515 __u16 srcfid;
1516 int oplock, rc;
1517
Jeff Layton7ffec372010-09-29 19:51:11 -04001518 tlink = cifs_sb_tlink(cifs_sb);
1519 if (IS_ERR(tlink))
1520 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001521 tcon = tlink_tcon(tlink);
1522 server = tcon->ses->server;
1523
1524 if (!server->ops->rename)
1525 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001526
Steve Frenchee2fd962008-09-23 18:23:33 +00001527 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001528 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001529
1530 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001531 * Don't bother with rename by filehandle unless file is busy and
1532 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001533 * rename by filehandle to various Windows servers.
1534 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001535 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001536 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001537
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001538 /* open-file renames don't work across directories */
1539 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001540 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001541
Steve Frenchee2fd962008-09-23 18:23:33 +00001542 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001543 rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE,
Steve Frenchee2fd962008-09-23 18:23:33 +00001544 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1545 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1546 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchee2fd962008-09-23 18:23:33 +00001547 if (rc == 0) {
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001548 rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001549 (const char *) to_dentry->d_name.name,
1550 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1551 CIFS_MOUNT_MAP_SPECIAL_CHR);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001552 CIFSSMBClose(xid, tcon, srcfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001553 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001554do_rename_exit:
1555 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001556 return rc;
1557}
1558
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001559int
1560cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1561 struct inode *target_dir, struct dentry *target_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001563 char *from_name = NULL;
1564 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001565 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001566 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001567 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001568 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1569 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001570 unsigned int xid;
1571 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572
Jeff Layton639e7a92010-09-03 11:50:09 -04001573 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001574 tlink = cifs_sb_tlink(cifs_sb);
1575 if (IS_ERR(tlink))
1576 return PTR_ERR(tlink);
1577 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001579 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001580
1581 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001582 * we already have the rename sem so we do not need to
1583 * grab it again here to protect the path integrity
1584 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001585 from_name = build_path_from_dentry(source_dentry);
1586 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 rc = -ENOMEM;
1588 goto cifs_rename_exit;
1589 }
1590
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001591 to_name = build_path_from_dentry(target_dentry);
1592 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001593 rc = -ENOMEM;
1594 goto cifs_rename_exit;
1595 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001597 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1598 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001599
Jeff Layton14121bd2008-10-20 14:45:22 -04001600 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001601 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001602 * Are src and dst hardlinks of same inode? We can only tell
1603 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001604 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001605 info_buf_source =
1606 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1607 GFP_KERNEL);
1608 if (info_buf_source == NULL) {
1609 rc = -ENOMEM;
1610 goto cifs_rename_exit;
1611 }
1612
1613 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001614 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1615 info_buf_source,
1616 cifs_sb->local_nls,
1617 cifs_sb->mnt_cifs_flags &
1618 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton8d281ef2008-10-22 13:57:01 -04001619 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001620 goto unlink_target;
1621
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001622 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1623 info_buf_target,
1624 cifs_sb->local_nls,
1625 cifs_sb->mnt_cifs_flags &
1626 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton14121bd2008-10-20 14:45:22 -04001627
Jeff Layton8d281ef2008-10-22 13:57:01 -04001628 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001629 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001630 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001631 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001632 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001633 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001634 }
1635 /*
1636 * else ... BB we could add the same check for Windows by
1637 * checking the UniqueId via FILE_INTERNAL_INFO
1638 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001639
Jeff Layton14121bd2008-10-20 14:45:22 -04001640unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001641 /* Try unlinking the target dentry if it's not negative */
1642 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Jeff Layton8d281ef2008-10-22 13:57:01 -04001643 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001644 if (tmprc)
1645 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001646 rc = cifs_do_rename(xid, source_dentry, from_name,
1647 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 }
1649
1650cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001651 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001652 kfree(from_name);
1653 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001654 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001655 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 return rc;
1657}
1658
Jeff Laytondf2cf172010-02-12 07:44:16 -05001659static bool
1660cifs_inode_needs_reval(struct inode *inode)
1661{
1662 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301663 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001664
1665 if (cifs_i->clientCanCacheRead)
1666 return false;
1667
1668 if (!lookupCacheEnabled)
1669 return true;
1670
1671 if (cifs_i->time == 0)
1672 return true;
1673
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301674 if (!time_in_range(jiffies, cifs_i->time,
1675 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001676 return true;
1677
Jeff Laytondb192722010-05-17 14:51:49 -04001678 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301679 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001680 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1681 return true;
1682
Jeff Laytondf2cf172010-02-12 07:44:16 -05001683 return false;
1684}
1685
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301686/*
1687 * Zap the cache. Called when invalid_mapping flag is set.
1688 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001689int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001690cifs_invalidate_mapping(struct inode *inode)
1691{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001692 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001693 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1694
1695 cifs_i->invalid_mapping = false;
1696
Jeff Laytondf2cf172010-02-12 07:44:16 -05001697 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001698 rc = invalidate_inode_pages2(inode->i_mapping);
1699 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001700 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1701 __func__, inode);
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001702 cifs_i->invalid_mapping = true;
1703 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001704 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001705
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301706 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001707 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001708}
1709
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001710int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001711{
1712 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001713 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001714 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001715
1716 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001717 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001718
Jeff Layton13cfb732010-09-29 19:51:11 -04001719 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001720 rc = cifs_get_file_info_unix(filp);
1721 else
1722 rc = cifs_get_file_info(filp);
1723
Jeff Laytonabab0952010-02-12 07:44:18 -05001724 return rc;
1725}
1726
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001727int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001729 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001730 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001731 struct inode *inode = dentry->d_inode;
1732 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001733 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734
Jeff Laytondf2cf172010-02-12 07:44:16 -05001735 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 return -ENOENT;
1737
Jeff Laytondf2cf172010-02-12 07:44:16 -05001738 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001739 return rc;
1740
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001741 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742
1743 /* can not safely grab the rename sem here if rename calls revalidate
1744 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001745 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301747 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001748 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001750
Joe Perchesf96637b2013-05-04 22:12:25 -05001751 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1752 full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001753 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
Jeff Layton0d424ad2010-09-20 16:01:35 -07001755 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001756 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1757 else
1758 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1759 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001761out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001763 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 return rc;
1765}
1766
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001767int cifs_revalidate_file(struct file *filp)
1768{
1769 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001770 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001771
1772 rc = cifs_revalidate_file_attr(filp);
1773 if (rc)
1774 return rc;
1775
1776 if (CIFS_I(inode)->invalid_mapping)
1777 rc = cifs_invalidate_mapping(inode);
1778 return rc;
1779}
1780
1781/* revalidate a dentry's inode attributes */
1782int cifs_revalidate_dentry(struct dentry *dentry)
1783{
1784 int rc;
1785 struct inode *inode = dentry->d_inode;
1786
1787 rc = cifs_revalidate_dentry_attr(dentry);
1788 if (rc)
1789 return rc;
1790
1791 if (CIFS_I(inode)->invalid_mapping)
1792 rc = cifs_invalidate_mapping(inode);
1793 return rc;
1794}
1795
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001797 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001799 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001800 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001801 struct inode *inode = dentry->d_inode;
1802 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001803
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001804 /*
1805 * We need to be sure that all dirty pages are written and the server
1806 * has actual ctime, mtime and file length.
1807 */
1808 if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
1809 inode->i_mapping->nrpages != 0) {
1810 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001811 if (rc) {
1812 mapping_set_error(inode->i_mapping, rc);
1813 return rc;
1814 }
Steve French5fe14c82006-11-07 19:26:33 +00001815 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001816
1817 rc = cifs_revalidate_dentry_attr(dentry);
1818 if (rc)
1819 return rc;
1820
1821 generic_fillattr(inode, stat);
1822 stat->blksize = CIFS_MAX_MSGSIZE;
1823 stat->ino = CIFS_I(inode)->uniqueid;
1824
1825 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001826 * If on a multiuser mount without unix extensions or cifsacl being
1827 * enabled, and the admin hasn't overridden them, set the ownership
1828 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001829 */
1830 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001831 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001832 !tcon->unix_ext) {
1833 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1834 stat->uid = current_fsuid();
1835 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1836 stat->gid = current_fsgid();
1837 }
1838 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839}
1840
1841static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1842{
1843 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1844 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1845 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 int rc = 0;
1847
1848 page = grab_cache_page(mapping, index);
1849 if (!page)
1850 return -ENOMEM;
1851
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001852 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 unlock_page(page);
1854 page_cache_release(page);
1855 return rc;
1856}
1857
Christoph Hellwig1b947462010-07-18 17:51:21 -04001858static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001859{
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001860 loff_t oldsize;
Steve French3677db12007-02-26 16:46:11 +00001861
Steve Frenchba6a46a2007-02-26 20:06:29 +00001862 spin_lock(&inode->i_lock);
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001863 oldsize = inode->i_size;
Steve French3677db12007-02-26 16:46:11 +00001864 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001865 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001866
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001867 truncate_pagecache(inode, oldsize, offset);
Steve French3677db12007-02-26 16:46:11 +00001868}
1869
Jeff Layton8efdbde2008-07-23 21:28:12 +00001870static int
1871cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001872 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00001873{
1874 int rc;
1875 struct cifsFileInfo *open_file;
1876 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1877 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001878 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001879 struct cifs_tcon *tcon = NULL;
1880 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001881 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001882
1883 /*
1884 * To avoid spurious oplock breaks from server, in the case of
1885 * inodes that we already have open, avoid doing path based
1886 * setting of file size if we can do it by handle.
1887 * This keeps our caching token (oplock) and avoids timeouts
1888 * when the local oplock break takes longer to flush
1889 * writebehind data than the SMB timeout for the SetPathInfo
1890 * request would allow
1891 */
Jeff Layton6508d902010-09-29 19:51:11 -04001892 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001893 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001894 tcon = tlink_tcon(open_file->tlink);
1895 server = tcon->ses->server;
1896 if (server->ops->set_file_size)
1897 rc = server->ops->set_file_size(xid, tcon, open_file,
1898 attrs->ia_size, false);
1899 else
1900 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001901 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05001902 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001903 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1904 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001905
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001906 io_parms.netfid = open_file->fid.netfid;
1907 io_parms.pid = open_file->pid;
1908 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001909 io_parms.offset = 0;
1910 io_parms.length = attrs->ia_size;
1911 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1912 NULL, NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001913 cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001914 }
1915 } else
1916 rc = -EINVAL;
1917
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001918 if (!rc)
1919 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07001920
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001921 if (tcon == NULL) {
1922 tlink = cifs_sb_tlink(cifs_sb);
1923 if (IS_ERR(tlink))
1924 return PTR_ERR(tlink);
1925 tcon = tlink_tcon(tlink);
1926 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001927 }
1928
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001929 /*
1930 * Set file size by pathname rather than by handle either because no
1931 * valid, writeable file handle for it was found or because there was
1932 * an error setting it by handle.
1933 */
1934 if (server->ops->set_path_size)
1935 rc = server->ops->set_path_size(xid, tcon, full_path,
1936 attrs->ia_size, cifs_sb, false);
1937 else
1938 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05001939 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001940 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1941 __u16 netfid;
1942 int oplock = 0;
1943
1944 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
1945 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
1946 &oplock, NULL, cifs_sb->local_nls,
1947 cifs_sb->mnt_cifs_flags &
1948 CIFS_MOUNT_MAP_SPECIAL_CHR);
1949 if (rc == 0) {
1950 unsigned int bytes_written;
1951
1952 io_parms.netfid = netfid;
1953 io_parms.pid = current->tgid;
1954 io_parms.tcon = tcon;
1955 io_parms.offset = 0;
1956 io_parms.length = attrs->ia_size;
1957 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
1958 NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001959 cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001960 CIFSSMBClose(xid, tcon, netfid);
1961 }
1962 }
1963 if (tlink)
1964 cifs_put_tlink(tlink);
1965
1966set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00001967 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001968 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04001969 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001970 cifs_truncate_page(inode->i_mapping, inode->i_size);
1971 }
1972
1973 return rc;
1974}
1975
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001976static int
1977cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1978{
1979 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001980 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001981 char *full_path = NULL;
1982 struct inode *inode = direntry->d_inode;
1983 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1984 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001985 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001986 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001987 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04001988 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001989
Joe Perchesf96637b2013-05-04 22:12:25 -05001990 cifs_dbg(FYI, "setattr_unix on file %s attrs->ia_valid=0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00001991 direntry->d_name.name, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001992
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001993 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001994
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001995 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
1996 attrs->ia_valid |= ATTR_FORCE;
1997
1998 rc = inode_change_ok(inode, attrs);
1999 if (rc < 0)
2000 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002001
2002 full_path = build_path_from_dentry(direntry);
2003 if (full_path == NULL) {
2004 rc = -ENOMEM;
2005 goto out;
2006 }
2007
Jeff Layton0f4d6342009-03-26 13:35:37 -04002008 /*
2009 * Attempt to flush data before changing attributes. We need to do
2010 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2011 * ownership or mode then we may also need to do this. Here, we take
2012 * the safe way out and just do the flush on all setattr requests. If
2013 * the flush returns error, store it to report later and continue.
2014 *
2015 * BB: This should be smarter. Why bother flushing pages that
2016 * will be truncated anyway? Also, should we error out here if
2017 * the flush returns error?
2018 */
2019 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002020 mapping_set_error(inode->i_mapping, rc);
2021 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002022
2023 if (attrs->ia_valid & ATTR_SIZE) {
2024 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2025 if (rc != 0)
2026 goto out;
2027 }
2028
2029 /* skip mode change if it's just for clearing setuid/setgid */
2030 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2031 attrs->ia_valid &= ~ATTR_MODE;
2032
2033 args = kmalloc(sizeof(*args), GFP_KERNEL);
2034 if (args == NULL) {
2035 rc = -ENOMEM;
2036 goto out;
2037 }
2038
2039 /* set up the struct */
2040 if (attrs->ia_valid & ATTR_MODE)
2041 args->mode = attrs->ia_mode;
2042 else
2043 args->mode = NO_CHANGE_64;
2044
2045 if (attrs->ia_valid & ATTR_UID)
2046 args->uid = attrs->ia_uid;
2047 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002048 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002049
2050 if (attrs->ia_valid & ATTR_GID)
2051 args->gid = attrs->ia_gid;
2052 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002053 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002054
2055 if (attrs->ia_valid & ATTR_ATIME)
2056 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2057 else
2058 args->atime = NO_CHANGE_64;
2059
2060 if (attrs->ia_valid & ATTR_MTIME)
2061 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2062 else
2063 args->mtime = NO_CHANGE_64;
2064
2065 if (attrs->ia_valid & ATTR_CTIME)
2066 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2067 else
2068 args->ctime = NO_CHANGE_64;
2069
2070 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002071 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002072 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002073 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002074 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002075 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002076 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002077 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002078 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002079 tlink = cifs_sb_tlink(cifs_sb);
2080 if (IS_ERR(tlink)) {
2081 rc = PTR_ERR(tlink);
2082 goto out;
2083 }
2084 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002085 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002086 cifs_sb->local_nls,
2087 cifs_sb->mnt_cifs_flags &
2088 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002089 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002090 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002091
Christoph Hellwig10257742010-06-04 11:30:02 +02002092 if (rc)
2093 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002094
Christoph Hellwig10257742010-06-04 11:30:02 +02002095 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002096 attrs->ia_size != i_size_read(inode))
2097 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002098
2099 setattr_copy(inode, attrs);
2100 mark_inode_dirty(inode);
2101
2102 /* force revalidate when any of these times are set since some
2103 of the fs types (eg ext3, fat) do not have fine enough
2104 time granularity to match protocol, and we do not have a
2105 a way (yet) to query the server fs's time granularity (and
2106 whether it rounds times down).
2107 */
2108 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2109 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002110out:
2111 kfree(args);
2112 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002113 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002114 return rc;
2115}
2116
Jeff Layton0510eeb2008-08-02 07:26:12 -04002117static int
2118cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002120 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002121 kuid_t uid = INVALID_UID;
2122 kgid_t gid = INVALID_GID;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002123 struct inode *inode = direntry->d_inode;
2124 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002125 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 char *full_path = NULL;
2127 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002128 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002129 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002130
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002131 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132
Joe Perchesf96637b2013-05-04 22:12:25 -05002133 cifs_dbg(FYI, "setattr on file %s attrs->iavalid 0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002134 direntry->d_name.name, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002135
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002136 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2137 attrs->ia_valid |= ATTR_FORCE;
2138
2139 rc = inode_change_ok(inode, attrs);
2140 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002141 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002142 return rc;
Steve French6473a552005-11-29 20:20:10 -08002143 }
Steve French50c2f752007-07-13 00:33:32 +00002144
Steve French7f573562005-08-30 11:32:14 -07002145 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302147 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002148 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302149 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
Jeff Layton0f4d6342009-03-26 13:35:37 -04002152 /*
2153 * Attempt to flush data before changing attributes. We need to do
2154 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2155 * ownership or mode then we may also need to do this. Here, we take
2156 * the safe way out and just do the flush on all setattr requests. If
2157 * the flush returns error, store it to report later and continue.
2158 *
2159 * BB: This should be smarter. Why bother flushing pages that
2160 * will be truncated anyway? Also, should we error out here if
2161 * the flush returns error?
2162 */
2163 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002164 mapping_set_error(inode->i_mapping, rc);
2165 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002166
Steve French50531442008-03-14 19:21:31 +00002167 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002168 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2169 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002170 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002172
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002173 if (attrs->ia_valid & ATTR_UID)
2174 uid = attrs->ia_uid;
2175
2176 if (attrs->ia_valid & ATTR_GID)
2177 gid = attrs->ia_gid;
2178
2179#ifdef CONFIG_CIFS_ACL
2180 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002181 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002182 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2183 uid, gid);
2184 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002185 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2186 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002187 goto cifs_setattr_exit;
2188 }
2189 }
2190 } else
2191#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002192 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002193 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194
Jeff Laytond32c4f22007-10-18 03:05:22 -07002195 /* skip mode change if it's just for clearing setuid/setgid */
2196 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2197 attrs->ia_valid &= ~ATTR_MODE;
2198
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002201 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002202#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002203 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002204 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002205 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002206 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002207 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2208 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002209 goto cifs_setattr_exit;
2210 }
2211 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002212#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002213 if (((mode & S_IWUGO) == 0) &&
2214 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002215
2216 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2217
Jeff Layton51328612008-05-22 09:33:34 -04002218 /* fix up mode if we're not using dynperm */
2219 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2220 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2221 } else if ((mode & S_IWUGO) &&
2222 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002223
2224 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2225 /* Attributes of 0 are ignored */
2226 if (dosattr == 0)
2227 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002228
2229 /* reset local inode permissions to normal */
2230 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2231 attrs->ia_mode &= ~(S_IALLUGO);
2232 if (S_ISDIR(inode->i_mode))
2233 attrs->ia_mode |=
2234 cifs_sb->mnt_dir_mode;
2235 else
2236 attrs->ia_mode |=
2237 cifs_sb->mnt_file_mode;
2238 }
2239 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2240 /* ignore mode change - ATTR_READONLY hasn't changed */
2241 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 }
2244
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002245 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2246 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2247 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2248 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
Steve Frenche30dcf32005-09-20 20:49:16 -07002250 /* Even if error on time set, no sense failing the call if
2251 the server would set the time to a reasonable value anyway,
2252 and this check ensures that we are not being called from
2253 sys_utimes in which case we ought to fail the call back to
2254 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002255 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002256 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002257 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 }
2259
2260 /* do not need local check to inode_check_ok since the server does
2261 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002262 if (rc)
2263 goto cifs_setattr_exit;
2264
2265 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002266 attrs->ia_size != i_size_read(inode))
2267 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002268
2269 setattr_copy(inode, attrs);
2270 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002271
Steve Frenche30dcf32005-09-20 20:49:16 -07002272cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002274 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 return rc;
2276}
2277
Jeff Layton0510eeb2008-08-02 07:26:12 -04002278int
2279cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2280{
2281 struct inode *inode = direntry->d_inode;
2282 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002283 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002284
2285 if (pTcon->unix_ext)
2286 return cifs_setattr_unix(direntry, attrs);
2287
2288 return cifs_setattr_nounix(direntry, attrs);
2289
2290 /* BB: add cifs_setattr_legacy for really old servers */
2291}
2292
Steve French99ee4db2007-02-27 05:35:17 +00002293#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294void cifs_delete_inode(struct inode *inode)
2295{
Joe Perchesf96637b2013-05-04 22:12:25 -05002296 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 /* may have to add back in if and when safe distributed caching of
2298 directories added e.g. via FindNotify */
2299}
Steve French99ee4db2007-02-27 05:35:17 +00002300#endif