blob: 20efd81266c643338bcd81b434edfe9fbcacc0ac [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 Shilovsky4ad65042012-09-18 16:20:26 -0700298static int
299cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500300{
301 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400302 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500303 FILE_UNIX_BASIC_INFO find_data;
304 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500305 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500306 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700307 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000308 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500309
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400310 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700311 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500312 if (!rc) {
313 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
314 } else if (rc == -EREMOTE) {
315 cifs_create_dfs_fattr(&fattr, inode->i_sb);
316 rc = 0;
317 }
318
319 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400320 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500321 return rc;
322}
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400325 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400326 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400328 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000329 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400330 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000331 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400332 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
Joe Perchesf96637b2013-05-04 22:12:25 -0500335 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000336
Jeff Layton7ffec372010-09-29 19:51:11 -0400337 tlink = cifs_sb_tlink(cifs_sb);
338 if (IS_ERR(tlink))
339 return PTR_ERR(tlink);
340 tcon = tlink_tcon(tlink);
341
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400343 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Steve French737b7582005-04-28 22:41:06 -0700344 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
345 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400346 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400347
348 if (!rc) {
349 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
350 } else if (rc == -EREMOTE) {
351 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700352 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400353 } else {
354 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000355 }
356
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200357 /* check for Minshall+French symlinks */
358 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
359 int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
360 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500361 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200362 }
363
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400364 if (*pinode == NULL) {
365 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400366 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400367 *pinode = cifs_iget(sb, &fattr);
368 if (!*pinode)
369 rc = -ENOMEM;
370 } else {
371 /* we already have inode, update it */
372 cifs_fattr_to_inode(*pinode, &fattr);
373 }
Steve French0e4bbde2008-05-20 19:50:46 +0000374
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 return rc;
376}
377
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400378static int
379cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400380 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800381{
382 int rc;
Steve French4b18f2a2008-04-29 00:06:05 +0000383 int oplock = 0;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800384 __u16 netfid;
Jeff Layton7ffec372010-09-29 19:51:11 -0400385 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000386 struct cifs_tcon *tcon;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000387 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800388 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800389 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000390 char *pbuf;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800391
392 pbuf = buf;
393
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400394 fattr->cf_mode &= ~S_IFMT;
395
396 if (fattr->cf_eof == 0) {
397 fattr->cf_mode |= S_IFIFO;
398 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800399 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400400 } else if (fattr->cf_eof < 8) {
401 fattr->cf_mode |= S_IFREG;
402 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800403 return -EINVAL; /* EOPNOTSUPP? */
404 }
Steve French50c2f752007-07-13 00:33:32 +0000405
Jeff Layton7ffec372010-09-29 19:51:11 -0400406 tlink = cifs_sb_tlink(cifs_sb);
407 if (IS_ERR(tlink))
408 return PTR_ERR(tlink);
409 tcon = tlink_tcon(tlink);
410
411 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800412 CREATE_NOT_DIR, &netfid, &oplock, NULL,
413 cifs_sb->local_nls,
414 cifs_sb->mnt_cifs_flags &
415 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000416 if (rc == 0) {
Steve Frenchec637e32005-12-12 20:53:18 -0800417 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800418 /* Read header */
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000419 io_parms.netfid = netfid;
420 io_parms.pid = current->tgid;
421 io_parms.tcon = tcon;
422 io_parms.offset = 0;
423 io_parms.length = 24;
424 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
425 &buf_type);
Steve French4523cc32007-04-30 20:13:06 +0000426 if ((rc == 0) && (bytes_read >= 8)) {
427 if (memcmp("IntxBLK", pbuf, 8) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500428 cifs_dbg(FYI, "Block device\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400429 fattr->cf_mode |= S_IFBLK;
430 fattr->cf_dtype = DT_BLK;
Steve French4523cc32007-04-30 20:13:06 +0000431 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800432 /* we have enough to decode dev num */
433 __u64 mjr; /* major */
434 __u64 mnr; /* minor */
435 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
436 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400437 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve French86c96b42005-11-18 20:25:31 -0800438 }
Steve French4523cc32007-04-30 20:13:06 +0000439 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500440 cifs_dbg(FYI, "Char device\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400441 fattr->cf_mode |= S_IFCHR;
442 fattr->cf_dtype = DT_CHR;
Steve French4523cc32007-04-30 20:13:06 +0000443 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800444 /* we have enough to decode dev num */
445 __u64 mjr; /* major */
446 __u64 mnr; /* minor */
447 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
448 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400449 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000450 }
Steve French4523cc32007-04-30 20:13:06 +0000451 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500452 cifs_dbg(FYI, "Symlink\n");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400453 fattr->cf_mode |= S_IFLNK;
454 fattr->cf_dtype = DT_LNK;
Steve French86c96b42005-11-18 20:25:31 -0800455 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400456 fattr->cf_mode |= S_IFREG; /* file? */
457 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000458 rc = -EOPNOTSUPP;
Steve French86c96b42005-11-18 20:25:31 -0800459 }
Steve French3020a1f2005-11-18 11:31:10 -0800460 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400461 fattr->cf_mode |= S_IFREG; /* then it is a file */
462 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000463 rc = -EOPNOTSUPP; /* or some unknown SFU type */
464 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400465 CIFSSMBClose(xid, tcon, netfid);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800466 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400467 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800468 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800469}
470
Steve French9e294f12005-11-17 16:59:21 -0800471#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
472
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400473/*
474 * Fetch mode bits as provided by SFU.
475 *
476 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
477 */
478static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400479 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800480{
Steve French3020a1f2005-11-18 11:31:10 -0800481#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800482 ssize_t rc;
483 char ea_value[4];
484 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400485 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000486 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800487
Jeff Layton7ffec372010-09-29 19:51:11 -0400488 tlink = cifs_sb_tlink(cifs_sb);
489 if (IS_ERR(tlink))
490 return PTR_ERR(tlink);
491 tcon = tlink_tcon(tlink);
492
493 rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400494 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
495 cifs_sb->mnt_cifs_flags &
496 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400497 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000498 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800499 return (int)rc;
500 else if (rc > 3) {
501 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400502 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500503 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
504 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400505 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500506 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800507 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400508
509 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800510#else
511 return -EOPNOTSUPP;
512#endif
Steve French9e294f12005-11-17 16:59:21 -0800513}
514
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400515/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000516static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400517cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
518 struct cifs_sb_info *cifs_sb, bool adjust_tz)
Steve Frenchb9a32602008-05-20 21:52:32 +0000519{
Steve French96daf2b2011-05-27 04:34:02 +0000520 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700521
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400522 memset(fattr, 0, sizeof(*fattr));
523 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
524 if (info->DeletePending)
525 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000526
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400527 if (info->LastAccessTime)
528 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
529 else
530 fattr->cf_atime = CURRENT_TIME;
531
532 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
533 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
534
535 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700536 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
537 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400538 }
539
540 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
541 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500542 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400543
544 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
545 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
546 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300547 /*
548 * Server can return wrong NumberOfLinks value for directories
549 * when Unix extensions are disabled - fake it.
550 */
551 fattr->cf_nlink = 2;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400552 } else {
553 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
554 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400555
Jeff Laytond0c280d2009-07-09 01:46:44 -0400556 /* clear write bits if ATTR_READONLY is set */
557 if (fattr->cf_cifsattrs & ATTR_READONLY)
558 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400559
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300560 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
561 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400562
563 fattr->cf_uid = cifs_sb->mnt_uid;
564 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000565}
566
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700567static int
568cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500569{
570 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400571 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500572 FILE_ALL_INFO find_data;
573 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500574 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500575 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700576 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000577 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700578 struct TCP_Server_Info *server = tcon->ses->server;
579
580 if (!server->ops->query_file_info)
581 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500582
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400583 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700584 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400585 switch (rc) {
586 case 0:
587 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
588 break;
589 case -EREMOTE:
590 cifs_create_dfs_fattr(&fattr, inode->i_sb);
591 rc = 0;
592 break;
593 case -EOPNOTSUPP:
594 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500595 /*
596 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000597 * for now, just skip revalidating and mark inode for
598 * immediate reval.
599 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500600 rc = 0;
601 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400602 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500603 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400604 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500605
606 /*
607 * don't bother with SFU junk here -- just mark inode as needing
608 * revalidation.
609 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500610 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
611 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
612 cifs_fattr_to_inode(inode, &fattr);
613cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400614 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500615 return rc;
616}
617
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400618int
619cifs_get_inode_info(struct inode **inode, const char *full_path,
620 FILE_ALL_INFO *data, struct super_block *sb, int xid,
621 const __u16 *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500623 bool validinum = false;
624 __u16 srchflgs;
625 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400626 struct cifs_tcon *tcon;
627 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400628 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400631 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400632 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500633 struct cifs_search_info *srchinf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634
Jeff Layton7ffec372010-09-29 19:51:11 -0400635 tlink = cifs_sb_tlink(cifs_sb);
636 if (IS_ERR(tlink))
637 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400638 tcon = tlink_tcon(tlink);
639 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400640
Joe Perchesf96637b2013-05-04 22:12:25 -0500641 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400643 if ((data == NULL) && (*inode != NULL)) {
644 if (CIFS_I(*inode)->clientCanCacheRead) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500645 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400646 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 }
648 }
649
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400650 /* if inode info is not passed, get it from server */
651 if (data == NULL) {
652 if (!server->ops->query_path_info) {
653 rc = -ENOSYS;
654 goto cgii_exit;
655 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400657 if (buf == NULL) {
658 rc = -ENOMEM;
659 goto cgii_exit;
660 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400661 data = (FILE_ALL_INFO *)buf;
662 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
663 data, &adjust_tz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400665
666 if (!rc) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400667 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb,
668 adjust_tz);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400669 } else if (rc == -EREMOTE) {
670 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000671 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500672 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
673 srchinf = kzalloc(sizeof(struct cifs_search_info),
674 GFP_KERNEL);
675 if (srchinf == NULL) {
676 rc = -ENOMEM;
677 goto cgii_exit;
678 }
679
680 srchinf->endOfSearch = false;
681 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
682
683 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
684 CIFS_SEARCH_CLOSE_AT_END |
685 CIFS_SEARCH_BACKUP_SEARCH;
686
687 rc = CIFSFindFirst(xid, tcon, full_path,
688 cifs_sb, NULL, srchflgs, srchinf, false);
689 if (!rc) {
690 data =
691 (FILE_ALL_INFO *)srchinf->srch_entries_start;
692
693 cifs_dir_info_to_fattr(&fattr,
694 (FILE_DIRECTORY_INFO *)data, cifs_sb);
695 fattr.cf_uniqueid = le64_to_cpu(
696 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
697 validinum = true;
698
699 cifs_buf_release(srchinf->ntwrk_buf_start);
700 }
701 kfree(srchinf);
702 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000703 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400705 /*
706 * If an inode wasn't passed in, then get the inode number
707 *
708 * Is an i_ino of zero legal? Can we use that to check if the server
709 * supports returning inode numbers? Are there other sanity checks we
710 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400711 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400712 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000713 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500714 if (validinum == false) {
715 if (server->ops->get_srv_inum)
716 tmprc = server->ops->get_srv_inum(xid,
717 tcon, cifs_sb, full_path,
718 &fattr.cf_uniqueid, data);
719 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500720 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
721 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500722 fattr.cf_uniqueid = iunique(sb, ROOT_I);
723 cifs_autodisable_serverino(cifs_sb);
724 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500725 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500726 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400727 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500728 } else
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400729 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000730
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400731 /* query for SFU type info if supported and needed */
732 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
733 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
734 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
735 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500736 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000737 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000738
Jeff Layton79df1ba2010-12-06 12:52:08 -0500739#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000740 /* fill in 0777 bits from ACL */
741 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400742 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600743 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500744 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
745 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600746 goto cgii_exit;
747 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000748 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500749#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400750
751 /* fill in remaining high mode bits e.g. SUID, VTX */
752 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
753 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
754
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200755 /* check for Minshall+French symlinks */
756 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
757 tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
758 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500759 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200760 }
761
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400762 if (!*inode) {
763 *inode = cifs_iget(sb, &fattr);
764 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400765 rc = -ENOMEM;
766 } else {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400767 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000768 }
769
Igor Mammedov79626702008-03-09 03:44:18 +0000770cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400772 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 return rc;
774}
775
Steve French7f8ed422007-09-28 22:28:55 +0000776static const struct inode_operations cifs_ipc_inode_ops = {
777 .lookup = cifs_lookup,
778};
779
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400780static int
781cifs_find_inode(struct inode *inode, void *opaque)
782{
783 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
784
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400785 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400786 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
787 return 0;
788
Jeff Layton20054bd2011-01-07 11:30:27 -0500789 /* use createtime like an i_generation field */
790 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
791 return 0;
792
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400793 /* don't match inode of different type */
794 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
795 return 0;
796
Jeff Layton5acfec22010-08-02 17:43:54 -0400797 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400798 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400799 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400800
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400801 return 1;
802}
803
804static int
805cifs_init_inode(struct inode *inode, void *opaque)
806{
807 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
808
809 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500810 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400811 return 0;
812}
813
Jeff Layton5acfec22010-08-02 17:43:54 -0400814/*
815 * walk dentry list for an inode and report whether it has aliases that
816 * are hashed. We use this to determine if a directory inode can actually
817 * be used.
818 */
819static bool
820inode_has_hashed_dentries(struct inode *inode)
821{
822 struct dentry *dentry;
823
Nick Piggin873feea2011-01-07 17:50:06 +1100824 spin_lock(&inode->i_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800825 hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400826 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100827 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400828 return true;
829 }
830 }
Nick Piggin873feea2011-01-07 17:50:06 +1100831 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400832 return false;
833}
834
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400835/* Given fattrs, get a corresponding inode */
836struct inode *
837cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
838{
839 unsigned long hash;
840 struct inode *inode;
841
Jeff Layton3d694382010-05-11 14:59:55 -0400842retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -0500843 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400844
845 /* hash down to 32-bits on 32-bit arch */
846 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
847
848 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400849 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400850 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400851 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400852 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400853
854 if (inode_has_hashed_dentries(inode)) {
855 cifs_autodisable_serverino(CIFS_SB(sb));
856 iput(inode);
857 fattr->cf_uniqueid = iunique(sb, ROOT_I);
858 goto retry_iget5_locked;
859 }
Jeff Layton3d694382010-05-11 14:59:55 -0400860 }
861
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400862 cifs_fattr_to_inode(inode, fattr);
863 if (sb->s_flags & MS_NOATIME)
864 inode->i_flags |= S_NOATIME | S_NOCMTIME;
865 if (inode->i_state & I_NEW) {
866 inode->i_ino = hash;
Jeff Layton522440e2010-09-29 09:49:54 -0400867 if (S_ISREG(inode->i_mode))
868 inode->i_data.backing_dev_info = sb->s_bdi;
Steve French0ccd4802010-07-16 04:31:02 +0000869#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530870 /* initialize per-inode cache cookie pointer */
871 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000872#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400873 unlock_new_inode(inode);
874 }
875 }
876
877 return inode;
878}
879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600881struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400883 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700884 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400885 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800886 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000887 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800888
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400889 xid = get_xid();
Jeff Layton0d424ad2010-09-20 16:01:35 -0700890 if (tcon->unix_ext)
Steve Frenchf87d39d2011-05-27 03:50:55 +0000891 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400892 else
Steve Frenchf87d39d2011-05-27 03:50:55 +0000893 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400894
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000895 if (!inode) {
896 inode = ERR_PTR(rc);
897 goto out;
898 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400899
Steve French0ccd4802010-07-16 04:31:02 +0000900#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530901 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700902 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000903#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530904
Jeff Layton0d424ad2010-09-20 16:01:35 -0700905 if (rc && tcon->ipc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500906 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -0500907 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +0000908 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200909 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +0000910 inode->i_op = &cifs_ipc_inode_ops;
911 inode->i_fop = &simple_dir_operations;
912 inode->i_uid = cifs_sb->mnt_uid;
913 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -0500914 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +0000915 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800916 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000917 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000918 }
919
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000920out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400921 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -0800922 * TODO: This is no longer true
923 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400924 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -0800925 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926}
927
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700928int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400929cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700930 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +0000931{
Steve French388e57b2008-09-16 23:50:58 +0000932 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +0000933 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700934 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +0000935 FILE_BASIC_INFO info_buf;
936
Steve French1adcb712009-02-25 14:19:56 +0000937 if (attrs == NULL)
938 return -EINVAL;
939
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700940 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
941 if (!server->ops->set_file_info)
942 return -ENOSYS;
943
Steve French388e57b2008-09-16 23:50:58 +0000944 if (attrs->ia_valid & ATTR_ATIME) {
945 set_time = true;
946 info_buf.LastAccessTime =
947 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
948 } else
949 info_buf.LastAccessTime = 0;
950
951 if (attrs->ia_valid & ATTR_MTIME) {
952 set_time = true;
953 info_buf.LastWriteTime =
954 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
955 } else
956 info_buf.LastWriteTime = 0;
957
958 /*
959 * Samba throws this field away, but windows may actually use it.
960 * Do not set ctime unless other time stamps are changed explicitly
961 * (i.e. by utimes()) since we would then have a mix of client and
962 * server times.
963 */
964 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500965 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +0000966 info_buf.ChangeTime =
967 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
968 } else
969 info_buf.ChangeTime = 0;
970
971 info_buf.CreationTime = 0; /* don't change */
972 info_buf.Attributes = cpu_to_le32(dosattr);
973
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700974 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +0000975}
976
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400977/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700978 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400979 * and rename it to a random name that hopefully won't conflict with
980 * anything else.
981 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700982int
983cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
984 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400985{
986 int oplock = 0;
987 int rc;
988 __u16 netfid;
Steve French32709582008-10-20 00:44:19 +0000989 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400990 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
991 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400992 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000993 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +0000994 __u32 dosattr, origattr;
995 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400996
Jeff Layton7ffec372010-09-29 19:51:11 -0400997 tlink = cifs_sb_tlink(cifs_sb);
998 if (IS_ERR(tlink))
999 return PTR_ERR(tlink);
1000 tcon = tlink_tcon(tlink);
1001
Sachin Prabhuc483a982013-03-05 19:25:56 +00001002 /*
1003 * We cannot rename the file if the server doesn't support
1004 * CAP_INFOLEVEL_PASSTHRU
1005 */
1006 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1007 rc = -EBUSY;
1008 goto out;
1009 }
1010
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001011 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001012 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001013 &netfid, &oplock, NULL, cifs_sb->local_nls,
1014 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1015 if (rc != 0)
1016 goto out;
1017
Steve French32709582008-10-20 00:44:19 +00001018 origattr = cifsInode->cifsAttrs;
1019 if (origattr == 0)
1020 origattr |= ATTR_NORMAL;
1021
1022 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001023 if (dosattr == 0)
1024 dosattr |= ATTR_NORMAL;
1025 dosattr |= ATTR_HIDDEN;
1026
Steve French32709582008-10-20 00:44:19 +00001027 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1028 if (dosattr != origattr) {
1029 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1030 if (info_buf == NULL) {
1031 rc = -ENOMEM;
1032 goto out_close;
1033 }
1034 info_buf->Attributes = cpu_to_le32(dosattr);
1035 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1036 current->tgid);
1037 /* although we would like to mark the file hidden
1038 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001039 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001040 cifsInode->cifsAttrs = dosattr;
1041 else
1042 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001043 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001044
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001045 /* rename the file */
1046 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001047 cifs_sb->mnt_cifs_flags &
1048 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French32709582008-10-20 00:44:19 +00001049 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001050 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001051 goto undo_setattr;
1052 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001053
Steve French32709582008-10-20 00:44:19 +00001054 /* try to set DELETE_ON_CLOSE */
1055 if (!cifsInode->delete_pending) {
1056 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
1057 current->tgid);
1058 /*
1059 * some samba versions return -ENOENT when we try to set the
1060 * file disposition here. Likely a samba bug, but work around
1061 * it for now. This means that some cifsXXX files may hang
1062 * around after they shouldn't.
1063 *
1064 * BB: remove this hack after more servers have the fix
1065 */
1066 if (rc == -ENOENT)
1067 rc = 0;
1068 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001069 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001070 goto undo_rename;
1071 }
1072 cifsInode->delete_pending = true;
1073 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001074
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001075out_close:
1076 CIFSSMBClose(xid, tcon, netfid);
1077out:
Steve French32709582008-10-20 00:44:19 +00001078 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001079 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001080 return rc;
Steve French32709582008-10-20 00:44:19 +00001081
1082 /*
1083 * reset everything back to the original state. Don't bother
1084 * dealing with errors here since we can't do anything about
1085 * them anyway.
1086 */
1087undo_rename:
1088 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
1089 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1090 CIFS_MOUNT_MAP_SPECIAL_CHR);
1091undo_setattr:
1092 if (dosattr != origattr) {
1093 info_buf->Attributes = cpu_to_le32(origattr);
1094 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1095 current->tgid))
1096 cifsInode->cifsAttrs = origattr;
1097 }
1098
1099 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001100}
1101
Steve Frenchb7ca6922012-08-03 08:43:01 -05001102/* copied from fs/nfs/dir.c with small changes */
1103static void
1104cifs_drop_nlink(struct inode *inode)
1105{
1106 spin_lock(&inode->i_lock);
1107 if (inode->i_nlink > 0)
1108 drop_nlink(inode);
1109 spin_unlock(&inode->i_lock);
1110}
Steve Frenchff694522009-04-20 19:45:13 +00001111
1112/*
1113 * If dentry->d_inode is null (usually meaning the cached dentry
1114 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001115 * if that fails we can not attempt the fall back mechanisms on EACCESS
1116 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001117 * unlink on negative dentries currently.
1118 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001119int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120{
1121 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001122 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001124 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001125 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001126 struct super_block *sb = dir->i_sb;
1127 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001128 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001129 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001130 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001131 struct iattr *attrs = NULL;
1132 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
Joe Perchesf96637b2013-05-04 22:12:25 -05001134 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
Jeff Layton7ffec372010-09-29 19:51:11 -04001136 tlink = cifs_sb_tlink(cifs_sb);
1137 if (IS_ERR(tlink))
1138 return PTR_ERR(tlink);
1139 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001140 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001141
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001142 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
Jeff Layton5f0319a2008-09-16 14:05:16 -04001144 /* Unlink can be called from rename so we can not take the
1145 * sb->s_vfs_rename_mutex here */
1146 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301148 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001149 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
Steve French2d785a52007-07-15 01:48:57 +00001151
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001152 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1153 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001154 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001155 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1156 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesf96637b2013-05-04 22:12:25 -05001157 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001158 if ((rc == 0) || (rc == -ENOENT))
1159 goto psx_del_no_retry;
1160 }
1161
Steve French60502472008-10-07 18:42:52 +00001162retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001163 if (!server->ops->unlink) {
1164 rc = -ENOSYS;
1165 goto psx_del_no_retry;
1166 }
1167
1168 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001169
Steve French2d785a52007-07-15 01:48:57 +00001170psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001172 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001173 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001175 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001176 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001177 if (server->ops->rename_pending_delete) {
1178 rc = server->ops->rename_pending_delete(full_path,
1179 dentry, xid);
1180 if (rc == 0)
1181 cifs_drop_nlink(inode);
1182 }
Steve Frenchff694522009-04-20 19:45:13 +00001183 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001184 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1185 if (attrs == NULL) {
1186 rc = -ENOMEM;
1187 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
Steve French388e57b2008-09-16 23:50:58 +00001189
1190 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001191 cifs_inode = CIFS_I(inode);
1192 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001193 if (origattr == 0)
1194 origattr |= ATTR_NORMAL;
1195 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001196 if (dosattr == 0)
1197 dosattr |= ATTR_NORMAL;
1198 dosattr |= ATTR_HIDDEN;
1199
1200 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001201 if (rc != 0)
1202 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001203
1204 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 }
Steve French60502472008-10-07 18:42:52 +00001206
1207 /* undo the setattr if we errored out and it's needed */
1208 if (rc != 0 && dosattr != 0)
1209 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1210
Steve French388e57b2008-09-16 23:50:58 +00001211out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001212 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001213 cifs_inode = CIFS_I(inode);
1214 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001215 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001216 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001217 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001218 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001219 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001220 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001221unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001223 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001224 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001225 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 return rc;
1227}
1228
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001229static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001230cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001231 const char *full_path, struct cifs_sb_info *cifs_sb,
1232 struct cifs_tcon *tcon, const unsigned int xid)
1233{
1234 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001235 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001236
1237 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001238 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001239 xid);
1240 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001241 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1242 xid, NULL);
1243
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001244 if (rc)
1245 return rc;
1246
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001247 /*
1248 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001249 * from the server or was set bogus. Also, since this is a brand new
1250 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001251 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001252 if (inode->i_nlink < 2)
1253 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001254 mode &= ~current_umask();
1255 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001256 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001257 mode |= S_ISGID;
1258
1259 if (tcon->unix_ext) {
1260 struct cifs_unix_set_info_args args = {
1261 .mode = mode,
1262 .ctime = NO_CHANGE_64,
1263 .atime = NO_CHANGE_64,
1264 .mtime = NO_CHANGE_64,
1265 .device = 0,
1266 };
1267 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001268 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001269 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001270 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001271 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001272 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001273 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001274 args.uid = INVALID_UID; /* no change */
1275 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001276 }
1277 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1278 cifs_sb->local_nls,
1279 cifs_sb->mnt_cifs_flags &
1280 CIFS_MOUNT_MAP_SPECIAL_CHR);
1281 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001282 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001283 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001284 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001285 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001286 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001287 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1288 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001289
Jeff Layton101b92d2012-09-19 06:22:45 -07001290 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1291 inode->i_uid = current_fsuid();
1292 if (inode->i_mode & S_ISGID)
1293 inode->i_gid = parent->i_gid;
1294 else
1295 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001296 }
1297 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001298 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001299 return rc;
1300}
1301
1302static int
1303cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1304 const char *full_path, struct cifs_sb_info *cifs_sb,
1305 struct cifs_tcon *tcon, const unsigned int xid)
1306{
1307 int rc = 0;
1308 u32 oplock = 0;
1309 FILE_UNIX_BASIC_INFO *info = NULL;
1310 struct inode *newinode = NULL;
1311 struct cifs_fattr fattr;
1312
1313 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1314 if (info == NULL) {
1315 rc = -ENOMEM;
1316 goto posix_mkdir_out;
1317 }
1318
1319 mode &= ~current_umask();
1320 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1321 NULL /* netfid */, info, &oplock, full_path,
1322 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1323 CIFS_MOUNT_MAP_SPECIAL_CHR);
1324 if (rc == -EOPNOTSUPP)
1325 goto posix_mkdir_out;
1326 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001327 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001328 d_drop(dentry);
1329 goto posix_mkdir_out;
1330 }
1331
1332 if (info->Type == cpu_to_le32(-1))
1333 /* no return info, go query for it */
1334 goto posix_mkdir_get_info;
1335 /*
1336 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1337 * need to set uid/gid.
1338 */
1339
1340 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1341 cifs_fill_uniqueid(inode->i_sb, &fattr);
1342 newinode = cifs_iget(inode->i_sb, &fattr);
1343 if (!newinode)
1344 goto posix_mkdir_get_info;
1345
1346 d_instantiate(dentry, newinode);
1347
1348#ifdef CONFIG_CIFS_DEBUG2
Joe Perchesf96637b2013-05-04 22:12:25 -05001349 cifs_dbg(FYI, "instantiated dentry %p %s to inode %p\n",
1350 dentry, dentry->d_name.name, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001351
1352 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001353 cifs_dbg(FYI, "unexpected number of links %d\n",
1354 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001355#endif
1356
1357posix_mkdir_out:
1358 kfree(info);
1359 return rc;
1360posix_mkdir_get_info:
1361 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1362 xid);
1363 goto posix_mkdir_out;
1364}
1365
Al Viro18bb1db2011-07-26 01:41:39 -04001366int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001368 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001369 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001371 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001372 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001373 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001374 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Joe Perchesf96637b2013-05-04 22:12:25 -05001376 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1377 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001380 tlink = cifs_sb_tlink(cifs_sb);
1381 if (IS_ERR(tlink))
1382 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001383 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001384
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001385 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Steve French7f573562005-08-30 11:32:14 -07001387 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301389 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001390 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 }
Steve French50c2f752007-07-13 00:33:32 +00001392
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001393 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1394 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001395 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1396 tcon, xid);
1397 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001398 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001399 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001400
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001401 server = tcon->ses->server;
1402
1403 if (!server->ops->mkdir) {
1404 rc = -ENOSYS;
1405 goto mkdir_out;
1406 }
1407
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001409 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001411 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001413 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001415
1416 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1417 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001418mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001419 /*
1420 * Force revalidate to get parent dir info when needed since cached
1421 * attributes are invalid now.
1422 */
1423 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001425 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001426 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 return rc;
1428}
1429
1430int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1431{
1432 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001433 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001435 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001436 struct cifs_tcon *tcon;
1437 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 char *full_path = NULL;
1439 struct cifsInodeInfo *cifsInode;
1440
Joe Perchesf96637b2013-05-04 22:12:25 -05001441 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001443 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Steve French7f573562005-08-30 11:32:14 -07001445 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301447 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001448 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 }
1450
Jeff Layton7ffec372010-09-29 19:51:11 -04001451 cifs_sb = CIFS_SB(inode->i_sb);
1452 tlink = cifs_sb_tlink(cifs_sb);
1453 if (IS_ERR(tlink)) {
1454 rc = PTR_ERR(tlink);
1455 goto rmdir_exit;
1456 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001457 tcon = tlink_tcon(tlink);
1458 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001459
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001460 if (!server->ops->rmdir) {
1461 rc = -ENOSYS;
1462 cifs_put_tlink(tlink);
1463 goto rmdir_exit;
1464 }
1465
1466 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001467 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
1469 if (!rc) {
Steve French3677db12007-02-26 16:46:11 +00001470 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001471 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001472 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001473 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 }
1475
1476 cifsInode = CIFS_I(direntry->d_inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001477 /* force revalidate to go get info when needed */
1478 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001479
1480 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001481 /*
1482 * Force revalidate to get parent dir info when needed since cached
1483 * attributes are invalid now.
1484 */
1485 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001486
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1488 current_fs_time(inode->i_sb);
1489
Jeff Layton7ffec372010-09-29 19:51:11 -04001490rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001492 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 return rc;
1494}
1495
Steve Frenchee2fd962008-09-23 18:23:33 +00001496static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001497cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1498 const char *from_path, struct dentry *to_dentry,
1499 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001500{
1501 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001502 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001503 struct cifs_tcon *tcon;
1504 struct TCP_Server_Info *server;
Steve Frenchee2fd962008-09-23 18:23:33 +00001505 __u16 srcfid;
1506 int oplock, rc;
1507
Jeff Layton7ffec372010-09-29 19:51:11 -04001508 tlink = cifs_sb_tlink(cifs_sb);
1509 if (IS_ERR(tlink))
1510 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001511 tcon = tlink_tcon(tlink);
1512 server = tcon->ses->server;
1513
1514 if (!server->ops->rename)
1515 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001516
Steve Frenchee2fd962008-09-23 18:23:33 +00001517 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001518 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001519
1520 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001521 * Don't bother with rename by filehandle unless file is busy and
1522 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001523 * rename by filehandle to various Windows servers.
1524 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001525 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001526 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001527
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001528 /* open-file renames don't work across directories */
1529 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001530 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001531
Steve Frenchee2fd962008-09-23 18:23:33 +00001532 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001533 rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE,
Steve Frenchee2fd962008-09-23 18:23:33 +00001534 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1535 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1536 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchee2fd962008-09-23 18:23:33 +00001537 if (rc == 0) {
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001538 rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001539 (const char *) to_dentry->d_name.name,
1540 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1541 CIFS_MOUNT_MAP_SPECIAL_CHR);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001542 CIFSSMBClose(xid, tcon, srcfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001543 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001544do_rename_exit:
1545 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001546 return rc;
1547}
1548
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001549int
1550cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1551 struct inode *target_dir, struct dentry *target_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001553 char *from_name = NULL;
1554 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001555 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001556 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001557 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001558 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1559 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001560 unsigned int xid;
1561 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
Jeff Layton639e7a92010-09-03 11:50:09 -04001563 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001564 tlink = cifs_sb_tlink(cifs_sb);
1565 if (IS_ERR(tlink))
1566 return PTR_ERR(tlink);
1567 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001569 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001570
1571 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001572 * we already have the rename sem so we do not need to
1573 * grab it again here to protect the path integrity
1574 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001575 from_name = build_path_from_dentry(source_dentry);
1576 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 rc = -ENOMEM;
1578 goto cifs_rename_exit;
1579 }
1580
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001581 to_name = build_path_from_dentry(target_dentry);
1582 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001583 rc = -ENOMEM;
1584 goto cifs_rename_exit;
1585 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001587 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1588 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001589
Jeff Layton14121bd2008-10-20 14:45:22 -04001590 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001591 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001592 * Are src and dst hardlinks of same inode? We can only tell
1593 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001594 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001595 info_buf_source =
1596 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1597 GFP_KERNEL);
1598 if (info_buf_source == NULL) {
1599 rc = -ENOMEM;
1600 goto cifs_rename_exit;
1601 }
1602
1603 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001604 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1605 info_buf_source,
1606 cifs_sb->local_nls,
1607 cifs_sb->mnt_cifs_flags &
1608 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton8d281ef2008-10-22 13:57:01 -04001609 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001610 goto unlink_target;
1611
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001612 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1613 info_buf_target,
1614 cifs_sb->local_nls,
1615 cifs_sb->mnt_cifs_flags &
1616 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton14121bd2008-10-20 14:45:22 -04001617
Jeff Layton8d281ef2008-10-22 13:57:01 -04001618 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001619 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001620 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001621 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001622 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001623 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001624 }
1625 /*
1626 * else ... BB we could add the same check for Windows by
1627 * checking the UniqueId via FILE_INTERNAL_INFO
1628 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001629
Jeff Layton14121bd2008-10-20 14:45:22 -04001630unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001631 /* Try unlinking the target dentry if it's not negative */
1632 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Jeff Layton8d281ef2008-10-22 13:57:01 -04001633 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001634 if (tmprc)
1635 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001636 rc = cifs_do_rename(xid, source_dentry, from_name,
1637 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 }
1639
1640cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001641 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001642 kfree(from_name);
1643 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001644 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001645 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 return rc;
1647}
1648
Jeff Laytondf2cf172010-02-12 07:44:16 -05001649static bool
1650cifs_inode_needs_reval(struct inode *inode)
1651{
1652 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301653 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001654
1655 if (cifs_i->clientCanCacheRead)
1656 return false;
1657
1658 if (!lookupCacheEnabled)
1659 return true;
1660
1661 if (cifs_i->time == 0)
1662 return true;
1663
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301664 if (!time_in_range(jiffies, cifs_i->time,
1665 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001666 return true;
1667
Jeff Laytondb192722010-05-17 14:51:49 -04001668 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301669 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001670 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1671 return true;
1672
Jeff Laytondf2cf172010-02-12 07:44:16 -05001673 return false;
1674}
1675
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301676/*
1677 * Zap the cache. Called when invalid_mapping flag is set.
1678 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001679int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001680cifs_invalidate_mapping(struct inode *inode)
1681{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001682 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001683 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1684
1685 cifs_i->invalid_mapping = false;
1686
Jeff Laytondf2cf172010-02-12 07:44:16 -05001687 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001688 rc = invalidate_inode_pages2(inode->i_mapping);
1689 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001690 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1691 __func__, inode);
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001692 cifs_i->invalid_mapping = true;
1693 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001694 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001695
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301696 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001697 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001698}
1699
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001700int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001701{
1702 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001703 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba62010-09-20 16:01:31 -07001704 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001705
1706 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001707 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001708
Jeff Layton13cfb732010-09-29 19:51:11 -04001709 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001710 rc = cifs_get_file_info_unix(filp);
1711 else
1712 rc = cifs_get_file_info(filp);
1713
Jeff Laytonabab0952010-02-12 07:44:18 -05001714 return rc;
1715}
1716
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001717int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001719 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001720 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001721 struct inode *inode = dentry->d_inode;
1722 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001723 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
Jeff Laytondf2cf172010-02-12 07:44:16 -05001725 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 return -ENOENT;
1727
Jeff Laytondf2cf172010-02-12 07:44:16 -05001728 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001729 return rc;
1730
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001731 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
1733 /* can not safely grab the rename sem here if rename calls revalidate
1734 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001735 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301737 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001738 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001740
Joe Perchesf96637b2013-05-04 22:12:25 -05001741 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1742 full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001743 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744
Jeff Layton0d424ad2010-09-20 16:01:35 -07001745 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001746 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1747 else
1748 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1749 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001751out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001753 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 return rc;
1755}
1756
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001757int cifs_revalidate_file(struct file *filp)
1758{
1759 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001760 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001761
1762 rc = cifs_revalidate_file_attr(filp);
1763 if (rc)
1764 return rc;
1765
1766 if (CIFS_I(inode)->invalid_mapping)
1767 rc = cifs_invalidate_mapping(inode);
1768 return rc;
1769}
1770
1771/* revalidate a dentry's inode attributes */
1772int cifs_revalidate_dentry(struct dentry *dentry)
1773{
1774 int rc;
1775 struct inode *inode = dentry->d_inode;
1776
1777 rc = cifs_revalidate_dentry_attr(dentry);
1778 if (rc)
1779 return rc;
1780
1781 if (CIFS_I(inode)->invalid_mapping)
1782 rc = cifs_invalidate_mapping(inode);
1783 return rc;
1784}
1785
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001787 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001789 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001790 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001791 struct inode *inode = dentry->d_inode;
1792 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001793
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001794 /*
1795 * We need to be sure that all dirty pages are written and the server
1796 * has actual ctime, mtime and file length.
1797 */
1798 if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
1799 inode->i_mapping->nrpages != 0) {
1800 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001801 if (rc) {
1802 mapping_set_error(inode->i_mapping, rc);
1803 return rc;
1804 }
Steve French5fe14c82006-11-07 19:26:33 +00001805 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001806
1807 rc = cifs_revalidate_dentry_attr(dentry);
1808 if (rc)
1809 return rc;
1810
1811 generic_fillattr(inode, stat);
1812 stat->blksize = CIFS_MAX_MSGSIZE;
1813 stat->ino = CIFS_I(inode)->uniqueid;
1814
1815 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001816 * If on a multiuser mount without unix extensions or cifsacl being
1817 * enabled, and the admin hasn't overridden them, set the ownership
1818 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001819 */
1820 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001821 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001822 !tcon->unix_ext) {
1823 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1824 stat->uid = current_fsuid();
1825 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1826 stat->gid = current_fsgid();
1827 }
1828 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829}
1830
1831static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1832{
1833 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1834 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1835 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 int rc = 0;
1837
1838 page = grab_cache_page(mapping, index);
1839 if (!page)
1840 return -ENOMEM;
1841
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001842 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 unlock_page(page);
1844 page_cache_release(page);
1845 return rc;
1846}
1847
Christoph Hellwig1b947462010-07-18 17:51:21 -04001848static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001849{
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001850 loff_t oldsize;
Steve French3677db12007-02-26 16:46:11 +00001851
Steve Frenchba6a46a2007-02-26 20:06:29 +00001852 spin_lock(&inode->i_lock);
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001853 oldsize = inode->i_size;
Steve French3677db12007-02-26 16:46:11 +00001854 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001855 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001856
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001857 truncate_pagecache(inode, oldsize, offset);
Steve French3677db12007-02-26 16:46:11 +00001858}
1859
Jeff Layton8efdbde2008-07-23 21:28:12 +00001860static int
1861cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001862 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00001863{
1864 int rc;
1865 struct cifsFileInfo *open_file;
1866 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1867 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001868 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001869 struct cifs_tcon *tcon = NULL;
1870 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001871 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001872
1873 /*
1874 * To avoid spurious oplock breaks from server, in the case of
1875 * inodes that we already have open, avoid doing path based
1876 * setting of file size if we can do it by handle.
1877 * This keeps our caching token (oplock) and avoids timeouts
1878 * when the local oplock break takes longer to flush
1879 * writebehind data than the SMB timeout for the SetPathInfo
1880 * request would allow
1881 */
Jeff Layton6508d902010-09-29 19:51:11 -04001882 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001883 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001884 tcon = tlink_tcon(open_file->tlink);
1885 server = tcon->ses->server;
1886 if (server->ops->set_file_size)
1887 rc = server->ops->set_file_size(xid, tcon, open_file,
1888 attrs->ia_size, false);
1889 else
1890 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001891 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05001892 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001893 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1894 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001895
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001896 io_parms.netfid = open_file->fid.netfid;
1897 io_parms.pid = open_file->pid;
1898 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001899 io_parms.offset = 0;
1900 io_parms.length = attrs->ia_size;
1901 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1902 NULL, NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001903 cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001904 }
1905 } else
1906 rc = -EINVAL;
1907
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001908 if (!rc)
1909 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07001910
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001911 if (tcon == NULL) {
1912 tlink = cifs_sb_tlink(cifs_sb);
1913 if (IS_ERR(tlink))
1914 return PTR_ERR(tlink);
1915 tcon = tlink_tcon(tlink);
1916 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001917 }
1918
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001919 /*
1920 * Set file size by pathname rather than by handle either because no
1921 * valid, writeable file handle for it was found or because there was
1922 * an error setting it by handle.
1923 */
1924 if (server->ops->set_path_size)
1925 rc = server->ops->set_path_size(xid, tcon, full_path,
1926 attrs->ia_size, cifs_sb, false);
1927 else
1928 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05001929 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001930 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1931 __u16 netfid;
1932 int oplock = 0;
1933
1934 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
1935 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
1936 &oplock, NULL, cifs_sb->local_nls,
1937 cifs_sb->mnt_cifs_flags &
1938 CIFS_MOUNT_MAP_SPECIAL_CHR);
1939 if (rc == 0) {
1940 unsigned int bytes_written;
1941
1942 io_parms.netfid = netfid;
1943 io_parms.pid = current->tgid;
1944 io_parms.tcon = tcon;
1945 io_parms.offset = 0;
1946 io_parms.length = attrs->ia_size;
1947 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
1948 NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001949 cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001950 CIFSSMBClose(xid, tcon, netfid);
1951 }
1952 }
1953 if (tlink)
1954 cifs_put_tlink(tlink);
1955
1956set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00001957 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001958 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04001959 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001960 cifs_truncate_page(inode->i_mapping, inode->i_size);
1961 }
1962
1963 return rc;
1964}
1965
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001966static int
1967cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1968{
1969 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001970 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001971 char *full_path = NULL;
1972 struct inode *inode = direntry->d_inode;
1973 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1974 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001975 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001976 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001977 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04001978 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001979
Joe Perchesf96637b2013-05-04 22:12:25 -05001980 cifs_dbg(FYI, "setattr_unix on file %s attrs->ia_valid=0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00001981 direntry->d_name.name, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001982
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001983 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001984
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001985 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
1986 attrs->ia_valid |= ATTR_FORCE;
1987
1988 rc = inode_change_ok(inode, attrs);
1989 if (rc < 0)
1990 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001991
1992 full_path = build_path_from_dentry(direntry);
1993 if (full_path == NULL) {
1994 rc = -ENOMEM;
1995 goto out;
1996 }
1997
Jeff Layton0f4d6342009-03-26 13:35:37 -04001998 /*
1999 * Attempt to flush data before changing attributes. We need to do
2000 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2001 * ownership or mode then we may also need to do this. Here, we take
2002 * the safe way out and just do the flush on all setattr requests. If
2003 * the flush returns error, store it to report later and continue.
2004 *
2005 * BB: This should be smarter. Why bother flushing pages that
2006 * will be truncated anyway? Also, should we error out here if
2007 * the flush returns error?
2008 */
2009 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002010 mapping_set_error(inode->i_mapping, rc);
2011 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002012
2013 if (attrs->ia_valid & ATTR_SIZE) {
2014 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2015 if (rc != 0)
2016 goto out;
2017 }
2018
2019 /* skip mode change if it's just for clearing setuid/setgid */
2020 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2021 attrs->ia_valid &= ~ATTR_MODE;
2022
2023 args = kmalloc(sizeof(*args), GFP_KERNEL);
2024 if (args == NULL) {
2025 rc = -ENOMEM;
2026 goto out;
2027 }
2028
2029 /* set up the struct */
2030 if (attrs->ia_valid & ATTR_MODE)
2031 args->mode = attrs->ia_mode;
2032 else
2033 args->mode = NO_CHANGE_64;
2034
2035 if (attrs->ia_valid & ATTR_UID)
2036 args->uid = attrs->ia_uid;
2037 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002038 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002039
2040 if (attrs->ia_valid & ATTR_GID)
2041 args->gid = attrs->ia_gid;
2042 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002043 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002044
2045 if (attrs->ia_valid & ATTR_ATIME)
2046 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2047 else
2048 args->atime = NO_CHANGE_64;
2049
2050 if (attrs->ia_valid & ATTR_MTIME)
2051 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2052 else
2053 args->mtime = NO_CHANGE_64;
2054
2055 if (attrs->ia_valid & ATTR_CTIME)
2056 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2057 else
2058 args->ctime = NO_CHANGE_64;
2059
2060 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002061 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002062 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002063 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002064 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002065 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002066 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002067 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002068 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002069 tlink = cifs_sb_tlink(cifs_sb);
2070 if (IS_ERR(tlink)) {
2071 rc = PTR_ERR(tlink);
2072 goto out;
2073 }
2074 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002075 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002076 cifs_sb->local_nls,
2077 cifs_sb->mnt_cifs_flags &
2078 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002079 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002080 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002081
Christoph Hellwig10257742010-06-04 11:30:02 +02002082 if (rc)
2083 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002084
Christoph Hellwig10257742010-06-04 11:30:02 +02002085 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002086 attrs->ia_size != i_size_read(inode))
2087 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002088
2089 setattr_copy(inode, attrs);
2090 mark_inode_dirty(inode);
2091
2092 /* force revalidate when any of these times are set since some
2093 of the fs types (eg ext3, fat) do not have fine enough
2094 time granularity to match protocol, and we do not have a
2095 a way (yet) to query the server fs's time granularity (and
2096 whether it rounds times down).
2097 */
2098 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2099 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002100out:
2101 kfree(args);
2102 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002103 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002104 return rc;
2105}
2106
Jeff Layton0510eeb2008-08-02 07:26:12 -04002107static int
2108cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002110 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002111 kuid_t uid = INVALID_UID;
2112 kgid_t gid = INVALID_GID;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002113 struct inode *inode = direntry->d_inode;
2114 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002115 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 char *full_path = NULL;
2117 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002118 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002119 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002120
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002121 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122
Joe Perchesf96637b2013-05-04 22:12:25 -05002123 cifs_dbg(FYI, "setattr on file %s attrs->iavalid 0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002124 direntry->d_name.name, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002125
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002126 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2127 attrs->ia_valid |= ATTR_FORCE;
2128
2129 rc = inode_change_ok(inode, attrs);
2130 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002131 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002132 return rc;
Steve French6473a552005-11-29 20:20:10 -08002133 }
Steve French50c2f752007-07-13 00:33:32 +00002134
Steve French7f573562005-08-30 11:32:14 -07002135 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302137 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002138 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302139 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141
Jeff Layton0f4d6342009-03-26 13:35:37 -04002142 /*
2143 * Attempt to flush data before changing attributes. We need to do
2144 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2145 * ownership or mode then we may also need to do this. Here, we take
2146 * the safe way out and just do the flush on all setattr requests. If
2147 * the flush returns error, store it to report later and continue.
2148 *
2149 * BB: This should be smarter. Why bother flushing pages that
2150 * will be truncated anyway? Also, should we error out here if
2151 * the flush returns error?
2152 */
2153 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002154 mapping_set_error(inode->i_mapping, rc);
2155 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002156
Steve French50531442008-03-14 19:21:31 +00002157 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002158 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2159 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002160 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002162
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002163 if (attrs->ia_valid & ATTR_UID)
2164 uid = attrs->ia_uid;
2165
2166 if (attrs->ia_valid & ATTR_GID)
2167 gid = attrs->ia_gid;
2168
2169#ifdef CONFIG_CIFS_ACL
2170 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002171 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002172 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2173 uid, gid);
2174 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002175 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2176 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002177 goto cifs_setattr_exit;
2178 }
2179 }
2180 } else
2181#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002182 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002183 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184
Jeff Laytond32c4f22007-10-18 03:05:22 -07002185 /* skip mode change if it's just for clearing setuid/setgid */
2186 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2187 attrs->ia_valid &= ~ATTR_MODE;
2188
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002191 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002192#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002193 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002194 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002195 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002196 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002197 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2198 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002199 goto cifs_setattr_exit;
2200 }
2201 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002202#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002203 if (((mode & S_IWUGO) == 0) &&
2204 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002205
2206 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2207
Jeff Layton51328612008-05-22 09:33:34 -04002208 /* fix up mode if we're not using dynperm */
2209 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2210 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2211 } else if ((mode & S_IWUGO) &&
2212 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002213
2214 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2215 /* Attributes of 0 are ignored */
2216 if (dosattr == 0)
2217 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002218
2219 /* reset local inode permissions to normal */
2220 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2221 attrs->ia_mode &= ~(S_IALLUGO);
2222 if (S_ISDIR(inode->i_mode))
2223 attrs->ia_mode |=
2224 cifs_sb->mnt_dir_mode;
2225 else
2226 attrs->ia_mode |=
2227 cifs_sb->mnt_file_mode;
2228 }
2229 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2230 /* ignore mode change - ATTR_READONLY hasn't changed */
2231 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 }
2234
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002235 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2236 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2237 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2238 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239
Steve Frenche30dcf32005-09-20 20:49:16 -07002240 /* Even if error on time set, no sense failing the call if
2241 the server would set the time to a reasonable value anyway,
2242 and this check ensures that we are not being called from
2243 sys_utimes in which case we ought to fail the call back to
2244 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002245 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002246 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002247 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 }
2249
2250 /* do not need local check to inode_check_ok since the server does
2251 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002252 if (rc)
2253 goto cifs_setattr_exit;
2254
2255 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002256 attrs->ia_size != i_size_read(inode))
2257 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002258
2259 setattr_copy(inode, attrs);
2260 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002261
Steve Frenche30dcf32005-09-20 20:49:16 -07002262cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002264 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 return rc;
2266}
2267
Jeff Layton0510eeb2008-08-02 07:26:12 -04002268int
2269cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2270{
2271 struct inode *inode = direntry->d_inode;
2272 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002273 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002274
2275 if (pTcon->unix_ext)
2276 return cifs_setattr_unix(direntry, attrs);
2277
2278 return cifs_setattr_nounix(direntry, attrs);
2279
2280 /* BB: add cifs_setattr_legacy for really old servers */
2281}
2282
Steve French99ee4db2007-02-27 05:35:17 +00002283#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284void cifs_delete_inode(struct inode *inode)
2285{
Joe Perchesf96637b2013-05-04 22:12:25 -05002286 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 /* may have to add back in if and when safe distributed caching of
2288 directories added e.g. via FindNotify */
2289}
Steve French99ee4db2007-02-27 05:35:17 +00002290#endif