blob: c9bce9b43855f573e3bcdfcc183e8cf58e99e821 [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
Pavel Shilovsky4cf2ef682014-08-18 20:49:58 +04001650 /* force revalidate to go get info when needed */
1651 CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
1652
1653 source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
1654 target_dir->i_mtime = current_fs_time(source_dir->i_sb);
1655
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001657 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001658 kfree(from_name);
1659 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001660 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001661 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 return rc;
1663}
1664
Jeff Laytondf2cf172010-02-12 07:44:16 -05001665static bool
1666cifs_inode_needs_reval(struct inode *inode)
1667{
1668 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301669 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001670
1671 if (cifs_i->clientCanCacheRead)
1672 return false;
1673
1674 if (!lookupCacheEnabled)
1675 return true;
1676
1677 if (cifs_i->time == 0)
1678 return true;
1679
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301680 if (!time_in_range(jiffies, cifs_i->time,
1681 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001682 return true;
1683
Jeff Laytondb192722010-05-17 14:51:49 -04001684 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301685 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001686 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1687 return true;
1688
Jeff Laytondf2cf172010-02-12 07:44:16 -05001689 return false;
1690}
1691
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301692/*
1693 * Zap the cache. Called when invalid_mapping flag is set.
1694 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001695int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001696cifs_invalidate_mapping(struct inode *inode)
1697{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001698 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001699 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1700
1701 cifs_i->invalid_mapping = false;
1702
Jeff Laytondf2cf172010-02-12 07:44:16 -05001703 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001704 rc = invalidate_inode_pages2(inode->i_mapping);
1705 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001706 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1707 __func__, inode);
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001708 cifs_i->invalid_mapping = true;
1709 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001710 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001711
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301712 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001713 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001714}
1715
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001716int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001717{
1718 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001719 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001720 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001721
1722 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001723 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001724
Jeff Layton13cfb732010-09-29 19:51:11 -04001725 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001726 rc = cifs_get_file_info_unix(filp);
1727 else
1728 rc = cifs_get_file_info(filp);
1729
Jeff Laytonabab0952010-02-12 07:44:18 -05001730 return rc;
1731}
1732
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001733int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001735 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001736 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001737 struct inode *inode = dentry->d_inode;
1738 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001739 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
Jeff Laytondf2cf172010-02-12 07:44:16 -05001741 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 return -ENOENT;
1743
Jeff Laytondf2cf172010-02-12 07:44:16 -05001744 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001745 return rc;
1746
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001747 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748
1749 /* can not safely grab the rename sem here if rename calls revalidate
1750 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001751 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301753 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001754 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001756
Joe Perchesf96637b2013-05-04 22:12:25 -05001757 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1758 full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001759 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
Jeff Layton0d424ad2010-09-20 16:01:35 -07001761 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001762 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1763 else
1764 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1765 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001767out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001769 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 return rc;
1771}
1772
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001773int cifs_revalidate_file(struct file *filp)
1774{
1775 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001776 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001777
1778 rc = cifs_revalidate_file_attr(filp);
1779 if (rc)
1780 return rc;
1781
1782 if (CIFS_I(inode)->invalid_mapping)
1783 rc = cifs_invalidate_mapping(inode);
1784 return rc;
1785}
1786
1787/* revalidate a dentry's inode attributes */
1788int cifs_revalidate_dentry(struct dentry *dentry)
1789{
1790 int rc;
1791 struct inode *inode = dentry->d_inode;
1792
1793 rc = cifs_revalidate_dentry_attr(dentry);
1794 if (rc)
1795 return rc;
1796
1797 if (CIFS_I(inode)->invalid_mapping)
1798 rc = cifs_invalidate_mapping(inode);
1799 return rc;
1800}
1801
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001803 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001805 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001806 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001807 struct inode *inode = dentry->d_inode;
1808 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001809
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001810 /*
1811 * We need to be sure that all dirty pages are written and the server
1812 * has actual ctime, mtime and file length.
1813 */
1814 if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
1815 inode->i_mapping->nrpages != 0) {
1816 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001817 if (rc) {
1818 mapping_set_error(inode->i_mapping, rc);
1819 return rc;
1820 }
Steve French5fe14c82006-11-07 19:26:33 +00001821 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001822
1823 rc = cifs_revalidate_dentry_attr(dentry);
1824 if (rc)
1825 return rc;
1826
1827 generic_fillattr(inode, stat);
1828 stat->blksize = CIFS_MAX_MSGSIZE;
1829 stat->ino = CIFS_I(inode)->uniqueid;
1830
1831 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001832 * If on a multiuser mount without unix extensions or cifsacl being
1833 * enabled, and the admin hasn't overridden them, set the ownership
1834 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001835 */
1836 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001837 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001838 !tcon->unix_ext) {
1839 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1840 stat->uid = current_fsuid();
1841 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1842 stat->gid = current_fsgid();
1843 }
1844 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845}
1846
1847static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1848{
1849 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1850 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1851 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 int rc = 0;
1853
1854 page = grab_cache_page(mapping, index);
1855 if (!page)
1856 return -ENOMEM;
1857
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001858 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 unlock_page(page);
1860 page_cache_release(page);
1861 return rc;
1862}
1863
Christoph Hellwig1b947462010-07-18 17:51:21 -04001864static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001865{
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001866 loff_t oldsize;
Steve French3677db12007-02-26 16:46:11 +00001867
Steve Frenchba6a46a2007-02-26 20:06:29 +00001868 spin_lock(&inode->i_lock);
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001869 oldsize = inode->i_size;
Steve French3677db12007-02-26 16:46:11 +00001870 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001871 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001872
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001873 truncate_pagecache(inode, oldsize, offset);
Steve French3677db12007-02-26 16:46:11 +00001874}
1875
Jeff Layton8efdbde2008-07-23 21:28:12 +00001876static int
1877cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001878 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00001879{
1880 int rc;
1881 struct cifsFileInfo *open_file;
1882 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1883 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001884 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001885 struct cifs_tcon *tcon = NULL;
1886 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001887 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001888
1889 /*
1890 * To avoid spurious oplock breaks from server, in the case of
1891 * inodes that we already have open, avoid doing path based
1892 * setting of file size if we can do it by handle.
1893 * This keeps our caching token (oplock) and avoids timeouts
1894 * when the local oplock break takes longer to flush
1895 * writebehind data than the SMB timeout for the SetPathInfo
1896 * request would allow
1897 */
Jeff Layton6508d902010-09-29 19:51:11 -04001898 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001899 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001900 tcon = tlink_tcon(open_file->tlink);
1901 server = tcon->ses->server;
1902 if (server->ops->set_file_size)
1903 rc = server->ops->set_file_size(xid, tcon, open_file,
1904 attrs->ia_size, false);
1905 else
1906 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001907 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05001908 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001909 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1910 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001911
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001912 io_parms.netfid = open_file->fid.netfid;
1913 io_parms.pid = open_file->pid;
1914 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001915 io_parms.offset = 0;
1916 io_parms.length = attrs->ia_size;
1917 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1918 NULL, NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001919 cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001920 }
1921 } else
1922 rc = -EINVAL;
1923
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001924 if (!rc)
1925 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07001926
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001927 if (tcon == NULL) {
1928 tlink = cifs_sb_tlink(cifs_sb);
1929 if (IS_ERR(tlink))
1930 return PTR_ERR(tlink);
1931 tcon = tlink_tcon(tlink);
1932 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001933 }
1934
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001935 /*
1936 * Set file size by pathname rather than by handle either because no
1937 * valid, writeable file handle for it was found or because there was
1938 * an error setting it by handle.
1939 */
1940 if (server->ops->set_path_size)
1941 rc = server->ops->set_path_size(xid, tcon, full_path,
1942 attrs->ia_size, cifs_sb, false);
1943 else
1944 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05001945 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001946 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1947 __u16 netfid;
1948 int oplock = 0;
1949
1950 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
1951 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
1952 &oplock, NULL, cifs_sb->local_nls,
1953 cifs_sb->mnt_cifs_flags &
1954 CIFS_MOUNT_MAP_SPECIAL_CHR);
1955 if (rc == 0) {
1956 unsigned int bytes_written;
1957
1958 io_parms.netfid = netfid;
1959 io_parms.pid = current->tgid;
1960 io_parms.tcon = tcon;
1961 io_parms.offset = 0;
1962 io_parms.length = attrs->ia_size;
1963 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
1964 NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001965 cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001966 CIFSSMBClose(xid, tcon, netfid);
1967 }
1968 }
1969 if (tlink)
1970 cifs_put_tlink(tlink);
1971
1972set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00001973 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001974 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04001975 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001976 cifs_truncate_page(inode->i_mapping, inode->i_size);
1977 }
1978
1979 return rc;
1980}
1981
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001982static int
1983cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1984{
1985 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001986 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001987 char *full_path = NULL;
1988 struct inode *inode = direntry->d_inode;
1989 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1990 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001991 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001992 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001993 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04001994 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001995
Joe Perchesf96637b2013-05-04 22:12:25 -05001996 cifs_dbg(FYI, "setattr_unix on file %s attrs->ia_valid=0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00001997 direntry->d_name.name, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001998
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001999 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002000
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002001 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2002 attrs->ia_valid |= ATTR_FORCE;
2003
2004 rc = inode_change_ok(inode, attrs);
2005 if (rc < 0)
2006 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002007
2008 full_path = build_path_from_dentry(direntry);
2009 if (full_path == NULL) {
2010 rc = -ENOMEM;
2011 goto out;
2012 }
2013
Jeff Layton0f4d6342009-03-26 13:35:37 -04002014 /*
2015 * Attempt to flush data before changing attributes. We need to do
2016 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2017 * ownership or mode then we may also need to do this. Here, we take
2018 * the safe way out and just do the flush on all setattr requests. If
2019 * the flush returns error, store it to report later and continue.
2020 *
2021 * BB: This should be smarter. Why bother flushing pages that
2022 * will be truncated anyway? Also, should we error out here if
2023 * the flush returns error?
2024 */
2025 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002026 mapping_set_error(inode->i_mapping, rc);
2027 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002028
2029 if (attrs->ia_valid & ATTR_SIZE) {
2030 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2031 if (rc != 0)
2032 goto out;
2033 }
2034
2035 /* skip mode change if it's just for clearing setuid/setgid */
2036 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2037 attrs->ia_valid &= ~ATTR_MODE;
2038
2039 args = kmalloc(sizeof(*args), GFP_KERNEL);
2040 if (args == NULL) {
2041 rc = -ENOMEM;
2042 goto out;
2043 }
2044
2045 /* set up the struct */
2046 if (attrs->ia_valid & ATTR_MODE)
2047 args->mode = attrs->ia_mode;
2048 else
2049 args->mode = NO_CHANGE_64;
2050
2051 if (attrs->ia_valid & ATTR_UID)
2052 args->uid = attrs->ia_uid;
2053 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002054 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002055
2056 if (attrs->ia_valid & ATTR_GID)
2057 args->gid = attrs->ia_gid;
2058 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002059 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002060
2061 if (attrs->ia_valid & ATTR_ATIME)
2062 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2063 else
2064 args->atime = NO_CHANGE_64;
2065
2066 if (attrs->ia_valid & ATTR_MTIME)
2067 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2068 else
2069 args->mtime = NO_CHANGE_64;
2070
2071 if (attrs->ia_valid & ATTR_CTIME)
2072 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2073 else
2074 args->ctime = NO_CHANGE_64;
2075
2076 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002077 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002078 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002079 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002080 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002081 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002082 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002083 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002084 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002085 tlink = cifs_sb_tlink(cifs_sb);
2086 if (IS_ERR(tlink)) {
2087 rc = PTR_ERR(tlink);
2088 goto out;
2089 }
2090 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002091 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002092 cifs_sb->local_nls,
2093 cifs_sb->mnt_cifs_flags &
2094 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002095 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002096 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002097
Christoph Hellwig10257742010-06-04 11:30:02 +02002098 if (rc)
2099 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002100
Christoph Hellwig10257742010-06-04 11:30:02 +02002101 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002102 attrs->ia_size != i_size_read(inode))
2103 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002104
2105 setattr_copy(inode, attrs);
2106 mark_inode_dirty(inode);
2107
2108 /* force revalidate when any of these times are set since some
2109 of the fs types (eg ext3, fat) do not have fine enough
2110 time granularity to match protocol, and we do not have a
2111 a way (yet) to query the server fs's time granularity (and
2112 whether it rounds times down).
2113 */
2114 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2115 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002116out:
2117 kfree(args);
2118 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002119 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002120 return rc;
2121}
2122
Jeff Layton0510eeb2008-08-02 07:26:12 -04002123static int
2124cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002126 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002127 kuid_t uid = INVALID_UID;
2128 kgid_t gid = INVALID_GID;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002129 struct inode *inode = direntry->d_inode;
2130 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002131 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 char *full_path = NULL;
2133 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002134 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002135 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002136
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002137 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138
Joe Perchesf96637b2013-05-04 22:12:25 -05002139 cifs_dbg(FYI, "setattr on file %s attrs->iavalid 0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002140 direntry->d_name.name, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002141
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002142 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2143 attrs->ia_valid |= ATTR_FORCE;
2144
2145 rc = inode_change_ok(inode, attrs);
2146 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002147 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002148 return rc;
Steve French6473a552005-11-29 20:20:10 -08002149 }
Steve French50c2f752007-07-13 00:33:32 +00002150
Steve French7f573562005-08-30 11:32:14 -07002151 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302153 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002154 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302155 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157
Jeff Layton0f4d6342009-03-26 13:35:37 -04002158 /*
2159 * Attempt to flush data before changing attributes. We need to do
2160 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2161 * ownership or mode then we may also need to do this. Here, we take
2162 * the safe way out and just do the flush on all setattr requests. If
2163 * the flush returns error, store it to report later and continue.
2164 *
2165 * BB: This should be smarter. Why bother flushing pages that
2166 * will be truncated anyway? Also, should we error out here if
2167 * the flush returns error?
2168 */
2169 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002170 mapping_set_error(inode->i_mapping, rc);
2171 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002172
Steve French50531442008-03-14 19:21:31 +00002173 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002174 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2175 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002176 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002178
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002179 if (attrs->ia_valid & ATTR_UID)
2180 uid = attrs->ia_uid;
2181
2182 if (attrs->ia_valid & ATTR_GID)
2183 gid = attrs->ia_gid;
2184
2185#ifdef CONFIG_CIFS_ACL
2186 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002187 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002188 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2189 uid, gid);
2190 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002191 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2192 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002193 goto cifs_setattr_exit;
2194 }
2195 }
2196 } else
2197#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002198 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002199 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
Jeff Laytond32c4f22007-10-18 03:05:22 -07002201 /* skip mode change if it's just for clearing setuid/setgid */
2202 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2203 attrs->ia_valid &= ~ATTR_MODE;
2204
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002207 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002208#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002209 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002210 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002211 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002212 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002213 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2214 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002215 goto cifs_setattr_exit;
2216 }
2217 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002218#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002219 if (((mode & S_IWUGO) == 0) &&
2220 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002221
2222 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2223
Jeff Layton51328612008-05-22 09:33:34 -04002224 /* fix up mode if we're not using dynperm */
2225 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2226 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2227 } else if ((mode & S_IWUGO) &&
2228 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002229
2230 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2231 /* Attributes of 0 are ignored */
2232 if (dosattr == 0)
2233 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002234
2235 /* reset local inode permissions to normal */
2236 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2237 attrs->ia_mode &= ~(S_IALLUGO);
2238 if (S_ISDIR(inode->i_mode))
2239 attrs->ia_mode |=
2240 cifs_sb->mnt_dir_mode;
2241 else
2242 attrs->ia_mode |=
2243 cifs_sb->mnt_file_mode;
2244 }
2245 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2246 /* ignore mode change - ATTR_READONLY hasn't changed */
2247 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 }
2250
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002251 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2252 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2253 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2254 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255
Steve Frenche30dcf32005-09-20 20:49:16 -07002256 /* Even if error on time set, no sense failing the call if
2257 the server would set the time to a reasonable value anyway,
2258 and this check ensures that we are not being called from
2259 sys_utimes in which case we ought to fail the call back to
2260 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002261 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002262 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002263 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 }
2265
2266 /* do not need local check to inode_check_ok since the server does
2267 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002268 if (rc)
2269 goto cifs_setattr_exit;
2270
2271 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002272 attrs->ia_size != i_size_read(inode))
2273 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002274
2275 setattr_copy(inode, attrs);
2276 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002277
Steve Frenche30dcf32005-09-20 20:49:16 -07002278cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002280 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 return rc;
2282}
2283
Jeff Layton0510eeb2008-08-02 07:26:12 -04002284int
2285cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2286{
2287 struct inode *inode = direntry->d_inode;
2288 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002289 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002290
2291 if (pTcon->unix_ext)
2292 return cifs_setattr_unix(direntry, attrs);
2293
2294 return cifs_setattr_nounix(direntry, attrs);
2295
2296 /* BB: add cifs_setattr_legacy for really old servers */
2297}
2298
Steve French99ee4db2007-02-27 05:35:17 +00002299#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300void cifs_delete_inode(struct inode *inode)
2301{
Joe Perchesf96637b2013-05-04 22:12:25 -05002302 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 /* may have to add back in if and when safe distributed caching of
2304 directories added e.g. via FindNotify */
2305}
Steve French99ee4db2007-02-27 05:35:17 +00002306#endif