blob: 5793b5a557e9b59bd91b6fb0cc21d45771d9c73a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/inode.c
3 *
Steve Frenchf19159d2010-04-21 04:12:10 +00004 * Copyright (C) International Business Machines Corp., 2002,2010
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/stat.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/pagemap.h>
25#include <asm/div64.h>
26#include "cifsfs.h"
27#include "cifspdu.h"
28#include "cifsglob.h"
29#include "cifsproto.h"
30#include "cifs_debug.h"
31#include "cifs_fs_sb.h"
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +053032#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
Christoph Hellwig70eff552008-02-15 20:55:05 +000034
David Howells01c64fe2011-01-14 18:45:47 +000035static void cifs_set_ops(struct inode *inode)
Christoph Hellwig70eff552008-02-15 20:55:05 +000036{
37 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
38
39 switch (inode->i_mode & S_IFMT) {
40 case S_IFREG:
41 inode->i_op = &cifs_file_inode_ops;
42 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
43 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
44 inode->i_fop = &cifs_file_direct_nobrl_ops;
45 else
46 inode->i_fop = &cifs_file_direct_ops;
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +030047 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
48 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
49 inode->i_fop = &cifs_file_strict_nobrl_ops;
50 else
51 inode->i_fop = &cifs_file_strict_ops;
Christoph Hellwig70eff552008-02-15 20:55:05 +000052 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
53 inode->i_fop = &cifs_file_nobrl_ops;
54 else { /* not direct, send byte range locks */
55 inode->i_fop = &cifs_file_ops;
56 }
57
Christoph Hellwig70eff552008-02-15 20:55:05 +000058 /* check if server can support readpages */
Jeff Layton0d424ad2010-09-20 16:01:35 -070059 if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
Christoph Hellwig70eff552008-02-15 20:55:05 +000060 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
61 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
62 else
63 inode->i_data.a_ops = &cifs_addr_ops;
64 break;
65 case S_IFDIR:
Steve Frenchbc5b6e22008-03-11 21:07:48 +000066#ifdef CONFIG_CIFS_DFS_UPCALL
David Howells01c64fe2011-01-14 18:45:47 +000067 if (IS_AUTOMOUNT(inode)) {
Igor Mammedov79626702008-03-09 03:44:18 +000068 inode->i_op = &cifs_dfs_referral_inode_operations;
69 } else {
Steve Frenchbc5b6e22008-03-11 21:07:48 +000070#else /* NO DFS support, treat as a directory */
71 {
72#endif
Igor Mammedov79626702008-03-09 03:44:18 +000073 inode->i_op = &cifs_dir_inode_ops;
74 inode->i_fop = &cifs_dir_ops;
75 }
Christoph Hellwig70eff552008-02-15 20:55:05 +000076 break;
77 case S_IFLNK:
78 inode->i_op = &cifs_symlink_inode_ops;
79 break;
80 default:
81 init_special_inode(inode, inode->i_mode, inode->i_rdev);
82 break;
83 }
84}
85
Jeff Laytondf2cf172010-02-12 07:44:16 -050086/* check inode attributes against fattr. If they don't match, tag the
87 * inode for cache invalidation
88 */
89static void
90cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
91{
92 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
93
Joe Perchesf96637b2013-05-04 22:12:25 -050094 cifs_dbg(FYI, "%s: revalidating inode %llu\n",
95 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -050096
97 if (inode->i_state & I_NEW) {
Joe Perchesf96637b2013-05-04 22:12:25 -050098 cifs_dbg(FYI, "%s: inode %llu is new\n",
99 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500100 return;
101 }
102
103 /* don't bother with revalidation if we have an oplock */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400104 if (CIFS_CACHE_READ(cifs_i)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500105 cifs_dbg(FYI, "%s: inode %llu is oplocked\n",
106 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500107 return;
108 }
109
110 /* revalidate if mtime or size have changed */
111 if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
112 cifs_i->server_eof == fattr->cf_eof) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500113 cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
114 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500115 return;
116 }
117
Joe Perchesf96637b2013-05-04 22:12:25 -0500118 cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
119 __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500120 cifs_i->invalid_mapping = true;
121}
122
Jim McDonough74d290d2013-09-21 10:36:10 -0500123/*
124 * copy nlink to the inode, unless it wasn't provided. Provide
125 * sane values if we don't have an existing one and none was provided
126 */
127static void
128cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
129{
130 /*
131 * if we're in a situation where we can't trust what we
132 * got from the server (readdir, some non-unix cases)
133 * fake reasonable values
134 */
135 if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
136 /* only provide fake values on a new inode */
137 if (inode->i_state & I_NEW) {
138 if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
139 set_nlink(inode, 2);
140 else
141 set_nlink(inode, 1);
142 }
143 return;
144 }
145
146 /* we trust the server, so update it */
147 set_nlink(inode, fattr->cf_nlink);
148}
149
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400150/* populate an inode with info from a cifs_fattr struct */
151void
152cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
Christoph Hellwig75f12982008-02-25 20:25:21 +0000153{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400154 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400155 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000156
Jeff Laytondf2cf172010-02-12 07:44:16 -0500157 cifs_revalidate_cache(inode, fattr);
158
Steve Frenchb7ca6922012-08-03 08:43:01 -0500159 spin_lock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400160 inode->i_atime = fattr->cf_atime;
161 inode->i_mtime = fattr->cf_mtime;
162 inode->i_ctime = fattr->cf_ctime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400163 inode->i_rdev = fattr->cf_rdev;
Jim McDonough74d290d2013-09-21 10:36:10 -0500164 cifs_nlink_fattr_to_inode(inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400165 inode->i_uid = fattr->cf_uid;
166 inode->i_gid = fattr->cf_gid;
167
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400168 /* if dynperm is set, don't clobber existing mode */
169 if (inode->i_state & I_NEW ||
170 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
171 inode->i_mode = fattr->cf_mode;
172
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400173 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400174
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400175 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
176 cifs_i->time = 0;
177 else
178 cifs_i->time = jiffies;
179
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400180 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000181
Jeff Layton835a36c2010-02-10 16:21:33 -0500182 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000183 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400184 * Can't safely change the file size here if the client is writing to
185 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000186 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400187 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
188 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000189
190 /*
191 * i_blocks is not related to (i_size / i_blksize),
192 * but instead 512 byte (2**9) size is required for
193 * calculating num blocks.
194 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400195 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000196 }
197 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400198
David Howells01c64fe2011-01-14 18:45:47 +0000199 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
200 inode->i_flags |= S_AUTOMOUNT;
Jeff Laytonc2b93e02013-05-07 11:28:31 -0400201 if (inode->i_state & I_NEW)
202 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000203}
204
Jeff Layton4065c802010-05-17 07:18:58 -0400205void
206cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
207{
208 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
209
210 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
211 return;
212
213 fattr->cf_uniqueid = iunique(sb, ROOT_I);
214}
215
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400216/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
217void
218cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
219 struct cifs_sb_info *cifs_sb)
220{
221 memset(fattr, 0, sizeof(*fattr));
222 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
223 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
224 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
225
226 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
227 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
228 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
229 fattr->cf_mode = le64_to_cpu(info->Permissions);
230
231 /*
232 * Since we set the inode type below we need to mask off
233 * to avoid strange results if bits set above.
234 */
235 fattr->cf_mode &= ~S_IFMT;
236 switch (le32_to_cpu(info->Type)) {
237 case UNIX_FILE:
238 fattr->cf_mode |= S_IFREG;
239 fattr->cf_dtype = DT_REG;
240 break;
241 case UNIX_SYMLINK:
242 fattr->cf_mode |= S_IFLNK;
243 fattr->cf_dtype = DT_LNK;
244 break;
245 case UNIX_DIR:
246 fattr->cf_mode |= S_IFDIR;
247 fattr->cf_dtype = DT_DIR;
248 break;
249 case UNIX_CHARDEV:
250 fattr->cf_mode |= S_IFCHR;
251 fattr->cf_dtype = DT_CHR;
252 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
253 le64_to_cpu(info->DevMinor) & MINORMASK);
254 break;
255 case UNIX_BLOCKDEV:
256 fattr->cf_mode |= S_IFBLK;
257 fattr->cf_dtype = DT_BLK;
258 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
259 le64_to_cpu(info->DevMinor) & MINORMASK);
260 break;
261 case UNIX_FIFO:
262 fattr->cf_mode |= S_IFIFO;
263 fattr->cf_dtype = DT_FIFO;
264 break;
265 case UNIX_SOCKET:
266 fattr->cf_mode |= S_IFSOCK;
267 fattr->cf_dtype = DT_SOCK;
268 break;
269 default:
270 /* safest to call it a file if we do not know */
271 fattr->cf_mode |= S_IFREG;
272 fattr->cf_dtype = DT_REG;
Joe Perchesf96637b2013-05-04 22:12:25 -0500273 cifs_dbg(FYI, "unknown type %d\n", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400274 break;
275 }
276
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800277 fattr->cf_uid = cifs_sb->mnt_uid;
278 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
279 u64 id = le64_to_cpu(info->Uid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800280 if (id < ((uid_t)-1)) {
281 kuid_t uid = make_kuid(&init_user_ns, id);
282 if (uid_valid(uid))
283 fattr->cf_uid = uid;
284 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800285 }
286
287 fattr->cf_gid = cifs_sb->mnt_gid;
288 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
289 u64 id = le64_to_cpu(info->Gid);
Eric W. Biederman4a2c8cf2013-02-06 01:53:25 -0800290 if (id < ((gid_t)-1)) {
291 kgid_t gid = make_kgid(&init_user_ns, id);
292 if (gid_valid(gid))
293 fattr->cf_gid = gid;
294 }
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800295 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400296
297 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
298}
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000299
300/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400301 * Fill a cifs_fattr struct with fake inode info.
302 *
303 * Needed to setup cifs_fattr data for the directory which is the
304 * junction to the new submount (ie to setup the fake directory
305 * which represents a DFS referral).
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000306 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000307static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400308cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000309{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400310 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000311
Joe Perchesf96637b2013-05-04 22:12:25 -0500312 cifs_dbg(FYI, "creating fake fattr for DFS referral\n");
Steve French0e4bbde2008-05-20 19:50:46 +0000313
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400314 memset(fattr, 0, sizeof(*fattr));
315 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
316 fattr->cf_uid = cifs_sb->mnt_uid;
317 fattr->cf_gid = cifs_sb->mnt_gid;
318 fattr->cf_atime = CURRENT_TIME;
319 fattr->cf_ctime = CURRENT_TIME;
320 fattr->cf_mtime = CURRENT_TIME;
321 fattr->cf_nlink = 2;
322 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000323}
324
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700325static int
326cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500327{
328 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400329 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500330 FILE_UNIX_BASIC_INFO find_data;
331 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500332 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500333 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700334 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000335 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500336
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400337 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700338 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500339 if (!rc) {
340 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
341 } else if (rc == -EREMOTE) {
342 cifs_create_dfs_fattr(&fattr, inode->i_sb);
343 rc = 0;
344 }
345
346 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400347 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500348 return rc;
349}
350
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400352 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400353 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400355 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000356 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400357 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000358 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400359 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
Joe Perchesf96637b2013-05-04 22:12:25 -0500362 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000363
Jeff Layton7ffec372010-09-29 19:51:11 -0400364 tlink = cifs_sb_tlink(cifs_sb);
365 if (IS_ERR(tlink))
366 return PTR_ERR(tlink);
367 tcon = tlink_tcon(tlink);
368
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400370 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Steve French737b7582005-04-28 22:41:06 -0700371 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
372 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400373 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400374
375 if (!rc) {
376 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
377 } else if (rc == -EREMOTE) {
378 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700379 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400380 } else {
381 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000382 }
383
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200384 /* check for Minshall+French symlinks */
385 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000386 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
387 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200388 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000389 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200390 }
391
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400392 if (*pinode == NULL) {
393 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400394 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400395 *pinode = cifs_iget(sb, &fattr);
396 if (!*pinode)
397 rc = -ENOMEM;
398 } else {
399 /* we already have inode, update it */
400 cifs_fattr_to_inode(*pinode, &fattr);
401 }
Steve French0e4bbde2008-05-20 19:50:46 +0000402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 return rc;
404}
405
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400406static int
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400407cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400408 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800409{
410 int rc;
Steve French4b18f2a2008-04-29 00:06:05 +0000411 int oplock = 0;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800412 __u16 netfid;
Jeff Layton7ffec372010-09-29 19:51:11 -0400413 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000414 struct cifs_tcon *tcon;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000415 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800416 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800417 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000418 char *pbuf;
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400419 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800420
421 pbuf = buf;
422
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400423 fattr->cf_mode &= ~S_IFMT;
424
425 if (fattr->cf_eof == 0) {
426 fattr->cf_mode |= S_IFIFO;
427 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800428 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400429 } else if (fattr->cf_eof < 8) {
430 fattr->cf_mode |= S_IFREG;
431 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800432 return -EINVAL; /* EOPNOTSUPP? */
433 }
Steve French50c2f752007-07-13 00:33:32 +0000434
Jeff Layton7ffec372010-09-29 19:51:11 -0400435 tlink = cifs_sb_tlink(cifs_sb);
436 if (IS_ERR(tlink))
437 return PTR_ERR(tlink);
438 tcon = tlink_tcon(tlink);
439
440 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800441 CREATE_NOT_DIR, &netfid, &oplock, NULL,
442 cifs_sb->local_nls,
443 cifs_sb->mnt_cifs_flags &
444 CIFS_MOUNT_MAP_SPECIAL_CHR);
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400445 if (rc) {
446 cifs_put_tlink(tlink);
447 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800448 }
Pavel Shilovsky0360d602014-01-16 15:53:35 +0400449
450 /* Read header */
451 io_parms.netfid = netfid;
452 io_parms.pid = current->tgid;
453 io_parms.tcon = tcon;
454 io_parms.offset = 0;
455 io_parms.length = 24;
456
457 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
458 if ((rc == 0) && (bytes_read >= 8)) {
459 if (memcmp("IntxBLK", pbuf, 8) == 0) {
460 cifs_dbg(FYI, "Block device\n");
461 fattr->cf_mode |= S_IFBLK;
462 fattr->cf_dtype = DT_BLK;
463 if (bytes_read == 24) {
464 /* we have enough to decode dev num */
465 __u64 mjr; /* major */
466 __u64 mnr; /* minor */
467 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
468 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
469 fattr->cf_rdev = MKDEV(mjr, mnr);
470 }
471 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
472 cifs_dbg(FYI, "Char device\n");
473 fattr->cf_mode |= S_IFCHR;
474 fattr->cf_dtype = DT_CHR;
475 if (bytes_read == 24) {
476 /* we have enough to decode dev num */
477 __u64 mjr; /* major */
478 __u64 mnr; /* minor */
479 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
480 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
481 fattr->cf_rdev = MKDEV(mjr, mnr);
482 }
483 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
484 cifs_dbg(FYI, "Symlink\n");
485 fattr->cf_mode |= S_IFLNK;
486 fattr->cf_dtype = DT_LNK;
487 } else {
488 fattr->cf_mode |= S_IFREG; /* file? */
489 fattr->cf_dtype = DT_REG;
490 rc = -EOPNOTSUPP;
491 }
492 } else {
493 fattr->cf_mode |= S_IFREG; /* then it is a file */
494 fattr->cf_dtype = DT_REG;
495 rc = -EOPNOTSUPP; /* or some unknown SFU type */
496 }
497 CIFSSMBClose(xid, tcon, netfid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400498 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800499 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800500}
501
Steve French9e294f12005-11-17 16:59:21 -0800502#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
503
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400504/*
505 * Fetch mode bits as provided by SFU.
506 *
507 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
508 */
509static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400510 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800511{
Steve French3020a1f2005-11-18 11:31:10 -0800512#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800513 ssize_t rc;
514 char ea_value[4];
515 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400516 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000517 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800518
Jeff Layton7ffec372010-09-29 19:51:11 -0400519 tlink = cifs_sb_tlink(cifs_sb);
520 if (IS_ERR(tlink))
521 return PTR_ERR(tlink);
522 tcon = tlink_tcon(tlink);
523
524 rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400525 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
526 cifs_sb->mnt_cifs_flags &
527 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400528 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000529 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800530 return (int)rc;
531 else if (rc > 3) {
532 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400533 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesf96637b2013-05-04 22:12:25 -0500534 cifs_dbg(FYI, "special bits 0%o org mode 0%o\n",
535 mode, fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400536 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -0500537 cifs_dbg(FYI, "special mode bits 0%o\n", mode);
Steve French9e294f12005-11-17 16:59:21 -0800538 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400539
540 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800541#else
542 return -EOPNOTSUPP;
543#endif
Steve French9e294f12005-11-17 16:59:21 -0800544}
545
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400546/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000547static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400548cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400549 struct cifs_sb_info *cifs_sb, bool adjust_tz,
550 bool symlink)
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000551{
Steve French96daf2b2011-05-27 04:34:02 +0000552 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700553
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400554 memset(fattr, 0, sizeof(*fattr));
555 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
556 if (info->DeletePending)
557 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000558
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400559 if (info->LastAccessTime)
560 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
561 else
562 fattr->cf_atime = CURRENT_TIME;
563
564 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
565 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
566
567 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700568 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
569 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400570 }
571
572 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
573 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500574 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400575
Jim McDonough74d290d2013-09-21 10:36:10 -0500576 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400577
578 if (symlink) {
579 fattr->cf_mode = S_IFLNK;
580 fattr->cf_dtype = DT_LNK;
581 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400582 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
583 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300584 /*
585 * Server can return wrong NumberOfLinks value for directories
586 * when Unix extensions are disabled - fake it.
587 */
Jim McDonough74d290d2013-09-21 10:36:10 -0500588 if (!tcon->unix_ext)
589 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400590 } else {
591 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
592 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400593
Jeff Laytond0c280d2009-07-09 01:46:44 -0400594 /* clear write bits if ATTR_READONLY is set */
595 if (fattr->cf_cifsattrs & ATTR_READONLY)
596 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400597
Jim McDonough74d290d2013-09-21 10:36:10 -0500598 /*
599 * Don't accept zero nlink from non-unix servers unless
600 * delete is pending. Instead mark it as unknown.
601 */
602 if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
603 !info->DeletePending) {
604 cifs_dbg(1, "bogus file nlink value %u\n",
Steve French6658b9f2013-07-04 14:38:48 -0500605 fattr->cf_nlink);
Jim McDonough74d290d2013-09-21 10:36:10 -0500606 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
Steve French6658b9f2013-07-04 14:38:48 -0500607 }
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300608 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400609
610 fattr->cf_uid = cifs_sb->mnt_uid;
611 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000612}
613
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700614static int
615cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500616{
617 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400618 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500619 FILE_ALL_INFO find_data;
620 struct cifs_fattr fattr;
Al Viro496ad9a2013-01-23 17:07:38 -0500621 struct inode *inode = file_inode(filp);
Jeff Laytonabab0952010-02-12 07:44:18 -0500622 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700623 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000624 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700625 struct TCP_Server_Info *server = tcon->ses->server;
626
627 if (!server->ops->query_file_info)
628 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500629
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400630 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700631 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400632 switch (rc) {
633 case 0:
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400634 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false,
635 false);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400636 break;
637 case -EREMOTE:
638 cifs_create_dfs_fattr(&fattr, inode->i_sb);
639 rc = 0;
640 break;
641 case -EOPNOTSUPP:
642 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500643 /*
644 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000645 * for now, just skip revalidating and mark inode for
646 * immediate reval.
647 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500648 rc = 0;
649 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400650 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500651 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400652 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500653
654 /*
655 * don't bother with SFU junk here -- just mark inode as needing
656 * revalidation.
657 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500658 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
659 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
660 cifs_fattr_to_inode(inode, &fattr);
661cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400662 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500663 return rc;
664}
665
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400666int
667cifs_get_inode_info(struct inode **inode, const char *full_path,
668 FILE_ALL_INFO *data, struct super_block *sb, int xid,
669 const __u16 *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500671 bool validinum = false;
672 __u16 srchflgs;
673 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400674 struct cifs_tcon *tcon;
675 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400676 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400679 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400680 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500681 struct cifs_search_info *srchinf = NULL;
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400682 bool symlink = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683
Jeff Layton7ffec372010-09-29 19:51:11 -0400684 tlink = cifs_sb_tlink(cifs_sb);
685 if (IS_ERR(tlink))
686 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400687 tcon = tlink_tcon(tlink);
688 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400689
Joe Perchesf96637b2013-05-04 22:12:25 -0500690 cifs_dbg(FYI, "Getting info on %s\n", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400692 if ((data == NULL) && (*inode != NULL)) {
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400693 if (CIFS_CACHE_READ(CIFS_I(*inode))) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500694 cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
Jeff Layton7ffec372010-09-29 19:51:11 -0400695 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 }
697 }
698
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400699 /* if inode info is not passed, get it from server */
700 if (data == NULL) {
701 if (!server->ops->query_path_info) {
702 rc = -ENOSYS;
703 goto cgii_exit;
704 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400706 if (buf == NULL) {
707 rc = -ENOMEM;
708 goto cgii_exit;
709 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400710 data = (FILE_ALL_INFO *)buf;
711 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400712 data, &adjust_tz, &symlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400714
715 if (!rc) {
Pavel Shilovskyeb85d94b2013-10-23 17:49:47 +0400716 cifs_all_info_to_fattr(&fattr, data, cifs_sb, adjust_tz,
717 symlink);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400718 } else if (rc == -EREMOTE) {
719 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000720 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500721 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
722 srchinf = kzalloc(sizeof(struct cifs_search_info),
723 GFP_KERNEL);
724 if (srchinf == NULL) {
725 rc = -ENOMEM;
726 goto cgii_exit;
727 }
728
729 srchinf->endOfSearch = false;
730 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
731
732 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
733 CIFS_SEARCH_CLOSE_AT_END |
734 CIFS_SEARCH_BACKUP_SEARCH;
735
736 rc = CIFSFindFirst(xid, tcon, full_path,
737 cifs_sb, NULL, srchflgs, srchinf, false);
738 if (!rc) {
739 data =
740 (FILE_ALL_INFO *)srchinf->srch_entries_start;
741
742 cifs_dir_info_to_fattr(&fattr,
743 (FILE_DIRECTORY_INFO *)data, cifs_sb);
744 fattr.cf_uniqueid = le64_to_cpu(
745 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
746 validinum = true;
747
748 cifs_buf_release(srchinf->ntwrk_buf_start);
749 }
750 kfree(srchinf);
751 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000752 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400754 /*
755 * If an inode wasn't passed in, then get the inode number
756 *
757 * Is an i_ino of zero legal? Can we use that to check if the server
758 * supports returning inode numbers? Are there other sanity checks we
759 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400760 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400761 if (*inode == NULL) {
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000762 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500763 if (validinum == false) {
764 if (server->ops->get_srv_inum)
765 tmprc = server->ops->get_srv_inum(xid,
766 tcon, cifs_sb, full_path,
767 &fattr.cf_uniqueid, data);
768 if (tmprc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500769 cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
770 tmprc);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500771 fattr.cf_uniqueid = iunique(sb, ROOT_I);
772 cifs_autodisable_serverino(cifs_sb);
773 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500774 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500775 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400776 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500777 } else
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400778 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000779
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400780 /* query for SFU type info if supported and needed */
781 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
782 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
783 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
784 if (tmprc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500785 cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000786 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000787
Jeff Layton79df1ba2010-12-06 12:52:08 -0500788#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000789 /* fill in 0777 bits from ACL */
790 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400791 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600792 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500793 cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
794 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600795 goto cgii_exit;
796 }
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000797 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500798#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400799
800 /* fill in remaining high mode bits e.g. SUID, VTX */
801 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
802 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
803
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200804 /* check for Minshall+French symlinks */
805 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
Sachin Prabhucb084b12013-11-25 17:09:50 +0000806 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
807 full_path);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200808 if (tmprc)
Sachin Prabhucb084b12013-11-25 17:09:50 +0000809 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200810 }
811
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400812 if (!*inode) {
813 *inode = cifs_iget(sb, &fattr);
814 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400815 rc = -ENOMEM;
816 } else {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400817 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a3260f2008-05-20 21:52:32 +0000818 }
819
Igor Mammedov79626702008-03-09 03:44:18 +0000820cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400822 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 return rc;
824}
825
Steve French7f8ed422007-09-28 22:28:55 +0000826static const struct inode_operations cifs_ipc_inode_ops = {
827 .lookup = cifs_lookup,
828};
829
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400830static int
831cifs_find_inode(struct inode *inode, void *opaque)
832{
833 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
834
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400835 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400836 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
837 return 0;
838
Jeff Layton20054bd2011-01-07 11:30:27 -0500839 /* use createtime like an i_generation field */
840 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
841 return 0;
842
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400843 /* don't match inode of different type */
844 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
845 return 0;
846
Jeff Layton5acfec22010-08-02 17:43:54 -0400847 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400848 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400849 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400850
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400851 return 1;
852}
853
854static int
855cifs_init_inode(struct inode *inode, void *opaque)
856{
857 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
858
859 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500860 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400861 return 0;
862}
863
Jeff Layton5acfec22010-08-02 17:43:54 -0400864/*
865 * walk dentry list for an inode and report whether it has aliases that
866 * are hashed. We use this to determine if a directory inode can actually
867 * be used.
868 */
869static bool
870inode_has_hashed_dentries(struct inode *inode)
871{
872 struct dentry *dentry;
873
Nick Piggin873feea2011-01-07 17:50:06 +1100874 spin_lock(&inode->i_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800875 hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400876 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100877 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400878 return true;
879 }
880 }
Nick Piggin873feea2011-01-07 17:50:06 +1100881 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400882 return false;
883}
884
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400885/* Given fattrs, get a corresponding inode */
886struct inode *
887cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
888{
889 unsigned long hash;
890 struct inode *inode;
891
Jeff Layton3d694382010-05-11 14:59:55 -0400892retry_iget5_locked:
Joe Perchesf96637b2013-05-04 22:12:25 -0500893 cifs_dbg(FYI, "looking for uniqueid=%llu\n", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400894
895 /* hash down to 32-bits on 32-bit arch */
896 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
897
898 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400899 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400900 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400901 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400902 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400903
904 if (inode_has_hashed_dentries(inode)) {
905 cifs_autodisable_serverino(CIFS_SB(sb));
906 iput(inode);
907 fattr->cf_uniqueid = iunique(sb, ROOT_I);
908 goto retry_iget5_locked;
909 }
Jeff Layton3d694382010-05-11 14:59:55 -0400910 }
911
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400912 cifs_fattr_to_inode(inode, fattr);
913 if (sb->s_flags & MS_NOATIME)
914 inode->i_flags |= S_NOATIME | S_NOCMTIME;
915 if (inode->i_state & I_NEW) {
916 inode->i_ino = hash;
Jeff Layton522440e2010-09-29 09:49:54 -0400917 if (S_ISREG(inode->i_mode))
918 inode->i_data.backing_dev_info = sb->s_bdi;
Steve French0ccd4802010-07-16 04:31:02 +0000919#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530920 /* initialize per-inode cache cookie pointer */
921 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000922#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400923 unlock_new_inode(inode);
924 }
925 }
926
927 return inode;
928}
929
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600931struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400933 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700934 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400935 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800936 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000937 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800938
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400939 xid = get_xid();
Jeff Layton0d424ad2010-09-20 16:01:35 -0700940 if (tcon->unix_ext)
Steve Frenchf87d39d2011-05-27 03:50:55 +0000941 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400942 else
Steve Frenchf87d39d2011-05-27 03:50:55 +0000943 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400944
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000945 if (!inode) {
946 inode = ERR_PTR(rc);
947 goto out;
948 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400949
Steve French0ccd4802010-07-16 04:31:02 +0000950#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530951 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700952 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000953#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530954
Jeff Layton0d424ad2010-09-20 16:01:35 -0700955 if (rc && tcon->ipc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500956 cifs_dbg(FYI, "ipc connection - fake read inode\n");
Steve Frenchb7ca6922012-08-03 08:43:01 -0500957 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +0000958 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200959 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +0000960 inode->i_op = &cifs_ipc_inode_ops;
961 inode->i_fop = &simple_dir_operations;
962 inode->i_uid = cifs_sb->mnt_uid;
963 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -0500964 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +0000965 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800966 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000967 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000968 }
969
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000970out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400971 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -0800972 * TODO: This is no longer true
973 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400974 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -0800975 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976}
977
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700978int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400979cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700980 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +0000981{
Steve French388e57b2008-09-16 23:50:58 +0000982 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +0000983 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700984 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +0000985 FILE_BASIC_INFO info_buf;
986
Steve French1adcb712009-02-25 14:19:56 +0000987 if (attrs == NULL)
988 return -EINVAL;
989
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700990 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
991 if (!server->ops->set_file_info)
992 return -ENOSYS;
993
Steve French388e57b2008-09-16 23:50:58 +0000994 if (attrs->ia_valid & ATTR_ATIME) {
995 set_time = true;
996 info_buf.LastAccessTime =
997 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
998 } else
999 info_buf.LastAccessTime = 0;
1000
1001 if (attrs->ia_valid & ATTR_MTIME) {
1002 set_time = true;
1003 info_buf.LastWriteTime =
1004 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1005 } else
1006 info_buf.LastWriteTime = 0;
1007
1008 /*
1009 * Samba throws this field away, but windows may actually use it.
1010 * Do not set ctime unless other time stamps are changed explicitly
1011 * (i.e. by utimes()) since we would then have a mix of client and
1012 * server times.
1013 */
1014 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001015 cifs_dbg(FYI, "CIFS - CTIME changed\n");
Steve French388e57b2008-09-16 23:50:58 +00001016 info_buf.ChangeTime =
1017 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1018 } else
1019 info_buf.ChangeTime = 0;
1020
1021 info_buf.CreationTime = 0; /* don't change */
1022 info_buf.Attributes = cpu_to_le32(dosattr);
1023
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -07001024 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +00001025}
1026
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001027/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001028 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001029 * and rename it to a random name that hopefully won't conflict with
1030 * anything else.
1031 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001032int
1033cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1034 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001035{
1036 int oplock = 0;
1037 int rc;
1038 __u16 netfid;
Steve French32709582008-10-20 00:44:19 +00001039 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001040 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1041 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001042 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001043 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001044 __u32 dosattr, origattr;
1045 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001046
Jeff Layton7ffec372010-09-29 19:51:11 -04001047 tlink = cifs_sb_tlink(cifs_sb);
1048 if (IS_ERR(tlink))
1049 return PTR_ERR(tlink);
1050 tcon = tlink_tcon(tlink);
1051
Sachin Prabhuc483a982013-03-05 19:25:56 +00001052 /*
1053 * We cannot rename the file if the server doesn't support
1054 * CAP_INFOLEVEL_PASSTHRU
1055 */
1056 if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
1057 rc = -EBUSY;
1058 goto out;
1059 }
1060
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001061 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001062 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001063 &netfid, &oplock, NULL, cifs_sb->local_nls,
1064 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1065 if (rc != 0)
1066 goto out;
1067
Steve French32709582008-10-20 00:44:19 +00001068 origattr = cifsInode->cifsAttrs;
1069 if (origattr == 0)
1070 origattr |= ATTR_NORMAL;
1071
1072 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001073 if (dosattr == 0)
1074 dosattr |= ATTR_NORMAL;
1075 dosattr |= ATTR_HIDDEN;
1076
Steve French32709582008-10-20 00:44:19 +00001077 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1078 if (dosattr != origattr) {
1079 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1080 if (info_buf == NULL) {
1081 rc = -ENOMEM;
1082 goto out_close;
1083 }
1084 info_buf->Attributes = cpu_to_le32(dosattr);
1085 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1086 current->tgid);
1087 /* although we would like to mark the file hidden
1088 if that fails we will still try to rename it */
Sachin Prabhu72d282d2013-03-05 19:25:55 +00001089 if (!rc)
Steve French32709582008-10-20 00:44:19 +00001090 cifsInode->cifsAttrs = dosattr;
1091 else
1092 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001093 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001094
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001095 /* rename the file */
1096 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001097 cifs_sb->mnt_cifs_flags &
1098 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French32709582008-10-20 00:44:19 +00001099 if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001100 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001101 goto undo_setattr;
1102 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001103
Steve French32709582008-10-20 00:44:19 +00001104 /* try to set DELETE_ON_CLOSE */
1105 if (!cifsInode->delete_pending) {
1106 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
1107 current->tgid);
1108 /*
1109 * some samba versions return -ENOENT when we try to set the
1110 * file disposition here. Likely a samba bug, but work around
1111 * it for now. This means that some cifsXXX files may hang
1112 * around after they shouldn't.
1113 *
1114 * BB: remove this hack after more servers have the fix
1115 */
1116 if (rc == -ENOENT)
1117 rc = 0;
1118 else if (rc != 0) {
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001119 rc = -EBUSY;
Steve French32709582008-10-20 00:44:19 +00001120 goto undo_rename;
1121 }
1122 cifsInode->delete_pending = true;
1123 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001124
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001125out_close:
1126 CIFSSMBClose(xid, tcon, netfid);
1127out:
Steve French32709582008-10-20 00:44:19 +00001128 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001129 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001130 return rc;
Steve French32709582008-10-20 00:44:19 +00001131
1132 /*
1133 * reset everything back to the original state. Don't bother
1134 * dealing with errors here since we can't do anything about
1135 * them anyway.
1136 */
1137undo_rename:
1138 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
1139 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1140 CIFS_MOUNT_MAP_SPECIAL_CHR);
1141undo_setattr:
1142 if (dosattr != origattr) {
1143 info_buf->Attributes = cpu_to_le32(origattr);
1144 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1145 current->tgid))
1146 cifsInode->cifsAttrs = origattr;
1147 }
1148
1149 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001150}
1151
Steve Frenchb7ca6922012-08-03 08:43:01 -05001152/* copied from fs/nfs/dir.c with small changes */
1153static void
1154cifs_drop_nlink(struct inode *inode)
1155{
1156 spin_lock(&inode->i_lock);
1157 if (inode->i_nlink > 0)
1158 drop_nlink(inode);
1159 spin_unlock(&inode->i_lock);
1160}
Steve Frenchff694522009-04-20 19:45:13 +00001161
1162/*
1163 * If dentry->d_inode is null (usually meaning the cached dentry
1164 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001165 * if that fails we can not attempt the fall back mechanisms on EACCESS
1166 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001167 * unlink on negative dentries currently.
1168 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001169int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170{
1171 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001172 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001174 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001175 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001176 struct super_block *sb = dir->i_sb;
1177 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001178 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001179 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001180 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001181 struct iattr *attrs = NULL;
1182 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
Joe Perchesf96637b2013-05-04 22:12:25 -05001184 cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
Jeff Layton7ffec372010-09-29 19:51:11 -04001186 tlink = cifs_sb_tlink(cifs_sb);
1187 if (IS_ERR(tlink))
1188 return PTR_ERR(tlink);
1189 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001190 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001191
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001192 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
Jeff Layton5f0319a2008-09-16 14:05:16 -04001194 /* Unlink can be called from rename so we can not take the
1195 * sb->s_vfs_rename_mutex here */
1196 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301198 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001199 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 }
Steve French2d785a52007-07-15 01:48:57 +00001201
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001202 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1203 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001204 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001205 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1206 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesf96637b2013-05-04 22:12:25 -05001207 cifs_dbg(FYI, "posix del rc %d\n", rc);
Steve French2d785a52007-07-15 01:48:57 +00001208 if ((rc == 0) || (rc == -ENOENT))
1209 goto psx_del_no_retry;
1210 }
1211
Steve French60502472008-10-07 18:42:52 +00001212retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001213 if (!server->ops->unlink) {
1214 rc = -ENOSYS;
1215 goto psx_del_no_retry;
1216 }
1217
1218 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001219
Steve French2d785a52007-07-15 01:48:57 +00001220psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001222 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001223 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001225 d_drop(dentry);
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001226 } else if (rc == -EBUSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001227 if (server->ops->rename_pending_delete) {
1228 rc = server->ops->rename_pending_delete(full_path,
1229 dentry, xid);
1230 if (rc == 0)
1231 cifs_drop_nlink(inode);
1232 }
Steve Frenchff694522009-04-20 19:45:13 +00001233 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001234 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1235 if (attrs == NULL) {
1236 rc = -ENOMEM;
1237 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 }
Steve French388e57b2008-09-16 23:50:58 +00001239
1240 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001241 cifs_inode = CIFS_I(inode);
1242 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001243 if (origattr == 0)
1244 origattr |= ATTR_NORMAL;
1245 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001246 if (dosattr == 0)
1247 dosattr |= ATTR_NORMAL;
1248 dosattr |= ATTR_HIDDEN;
1249
1250 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001251 if (rc != 0)
1252 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001253
1254 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 }
Steve French60502472008-10-07 18:42:52 +00001256
1257 /* undo the setattr if we errored out and it's needed */
1258 if (rc != 0 && dosattr != 0)
1259 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1260
Steve French388e57b2008-09-16 23:50:58 +00001261out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001262 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001263 cifs_inode = CIFS_I(inode);
1264 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001265 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001266 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001267 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001268 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001269 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001270 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001271unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001273 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001274 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001275 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 return rc;
1277}
1278
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001279static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001280cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001281 const char *full_path, struct cifs_sb_info *cifs_sb,
1282 struct cifs_tcon *tcon, const unsigned int xid)
1283{
1284 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001285 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001286
1287 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001288 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001289 xid);
1290 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001291 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1292 xid, NULL);
1293
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001294 if (rc)
1295 return rc;
1296
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001297 /*
1298 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001299 * from the server or was set bogus. Also, since this is a brand new
1300 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001301 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001302 if (inode->i_nlink < 2)
1303 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001304 mode &= ~current_umask();
1305 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001306 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001307 mode |= S_ISGID;
1308
1309 if (tcon->unix_ext) {
1310 struct cifs_unix_set_info_args args = {
1311 .mode = mode,
1312 .ctime = NO_CHANGE_64,
1313 .atime = NO_CHANGE_64,
1314 .mtime = NO_CHANGE_64,
1315 .device = 0,
1316 };
1317 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001318 args.uid = current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001319 if (parent->i_mode & S_ISGID)
Eric W. Biederman49418b22013-02-06 00:57:56 -08001320 args.gid = parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001321 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08001322 args.gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001323 } else {
Eric W. Biederman49418b22013-02-06 00:57:56 -08001324 args.uid = INVALID_UID; /* no change */
1325 args.gid = INVALID_GID; /* no change */
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001326 }
1327 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1328 cifs_sb->local_nls,
1329 cifs_sb->mnt_cifs_flags &
1330 CIFS_MOUNT_MAP_SPECIAL_CHR);
1331 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001332 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001333 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001334 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001335 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001336 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001337 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1338 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001339
Jeff Layton101b92d2012-09-19 06:22:45 -07001340 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1341 inode->i_uid = current_fsuid();
1342 if (inode->i_mode & S_ISGID)
1343 inode->i_gid = parent->i_gid;
1344 else
1345 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001346 }
1347 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001348 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001349 return rc;
1350}
1351
1352static int
1353cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1354 const char *full_path, struct cifs_sb_info *cifs_sb,
1355 struct cifs_tcon *tcon, const unsigned int xid)
1356{
1357 int rc = 0;
1358 u32 oplock = 0;
1359 FILE_UNIX_BASIC_INFO *info = NULL;
1360 struct inode *newinode = NULL;
1361 struct cifs_fattr fattr;
1362
1363 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1364 if (info == NULL) {
1365 rc = -ENOMEM;
1366 goto posix_mkdir_out;
1367 }
1368
1369 mode &= ~current_umask();
1370 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1371 NULL /* netfid */, info, &oplock, full_path,
1372 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1373 CIFS_MOUNT_MAP_SPECIAL_CHR);
1374 if (rc == -EOPNOTSUPP)
1375 goto posix_mkdir_out;
1376 else if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001377 cifs_dbg(FYI, "posix mkdir returned 0x%x\n", rc);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001378 d_drop(dentry);
1379 goto posix_mkdir_out;
1380 }
1381
1382 if (info->Type == cpu_to_le32(-1))
1383 /* no return info, go query for it */
1384 goto posix_mkdir_get_info;
1385 /*
1386 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1387 * need to set uid/gid.
1388 */
1389
1390 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1391 cifs_fill_uniqueid(inode->i_sb, &fattr);
1392 newinode = cifs_iget(inode->i_sb, &fattr);
1393 if (!newinode)
1394 goto posix_mkdir_get_info;
1395
1396 d_instantiate(dentry, newinode);
1397
1398#ifdef CONFIG_CIFS_DEBUG2
Joe Perchesf96637b2013-05-04 22:12:25 -05001399 cifs_dbg(FYI, "instantiated dentry %p %s to inode %p\n",
1400 dentry, dentry->d_name.name, newinode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001401
1402 if (newinode->i_nlink != 2)
Joe Perchesf96637b2013-05-04 22:12:25 -05001403 cifs_dbg(FYI, "unexpected number of links %d\n",
1404 newinode->i_nlink);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001405#endif
1406
1407posix_mkdir_out:
1408 kfree(info);
1409 return rc;
1410posix_mkdir_get_info:
1411 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1412 xid);
1413 goto posix_mkdir_out;
1414}
1415
Al Viro18bb1db2011-07-26 01:41:39 -04001416int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001418 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001419 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001421 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001422 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001423 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001424 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
Joe Perchesf96637b2013-05-04 22:12:25 -05001426 cifs_dbg(FYI, "In cifs_mkdir, mode = 0x%hx inode = 0x%p\n",
1427 mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001430 tlink = cifs_sb_tlink(cifs_sb);
1431 if (IS_ERR(tlink))
1432 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001433 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001434
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001435 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
Steve French7f573562005-08-30 11:32:14 -07001437 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301439 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001440 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 }
Steve French50c2f752007-07-13 00:33:32 +00001442
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001443 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1444 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001445 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1446 tcon, xid);
1447 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001448 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001449 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001450
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001451 server = tcon->ses->server;
1452
1453 if (!server->ops->mkdir) {
1454 rc = -ENOSYS;
1455 goto mkdir_out;
1456 }
1457
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001459 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001461 cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001463 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001465
1466 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1467 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001468mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001469 /*
1470 * Force revalidate to get parent dir info when needed since cached
1471 * attributes are invalid now.
1472 */
1473 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001475 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001476 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 return rc;
1478}
1479
1480int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1481{
1482 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001483 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001485 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001486 struct cifs_tcon *tcon;
1487 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 char *full_path = NULL;
1489 struct cifsInodeInfo *cifsInode;
1490
Joe Perchesf96637b2013-05-04 22:12:25 -05001491 cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001493 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
Steve French7f573562005-08-30 11:32:14 -07001495 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301497 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001498 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 }
1500
Jeff Layton7ffec372010-09-29 19:51:11 -04001501 cifs_sb = CIFS_SB(inode->i_sb);
1502 tlink = cifs_sb_tlink(cifs_sb);
1503 if (IS_ERR(tlink)) {
1504 rc = PTR_ERR(tlink);
1505 goto rmdir_exit;
1506 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001507 tcon = tlink_tcon(tlink);
1508 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001509
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001510 if (!server->ops->rmdir) {
1511 rc = -ENOSYS;
1512 cifs_put_tlink(tlink);
1513 goto rmdir_exit;
1514 }
1515
1516 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001517 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518
1519 if (!rc) {
Steve French3677db12007-02-26 16:46:11 +00001520 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001521 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001522 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001523 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 }
1525
1526 cifsInode = CIFS_I(direntry->d_inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001527 /* force revalidate to go get info when needed */
1528 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001529
1530 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001531 /*
1532 * Force revalidate to get parent dir info when needed since cached
1533 * attributes are invalid now.
1534 */
1535 cifsInode->time = 0;
Steve French42c245442009-01-13 22:03:55 +00001536
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1538 current_fs_time(inode->i_sb);
1539
Jeff Layton7ffec372010-09-29 19:51:11 -04001540rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001542 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 return rc;
1544}
1545
Steve Frenchee2fd962008-09-23 18:23:33 +00001546static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001547cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1548 const char *from_path, struct dentry *to_dentry,
1549 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001550{
1551 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001552 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001553 struct cifs_tcon *tcon;
1554 struct TCP_Server_Info *server;
Steve Frenchee2fd962008-09-23 18:23:33 +00001555 __u16 srcfid;
1556 int oplock, rc;
1557
Jeff Layton7ffec372010-09-29 19:51:11 -04001558 tlink = cifs_sb_tlink(cifs_sb);
1559 if (IS_ERR(tlink))
1560 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001561 tcon = tlink_tcon(tlink);
1562 server = tcon->ses->server;
1563
1564 if (!server->ops->rename)
1565 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001566
Steve Frenchee2fd962008-09-23 18:23:33 +00001567 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001568 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001569
1570 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001571 * Don't bother with rename by filehandle unless file is busy and
1572 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001573 * rename by filehandle to various Windows servers.
1574 */
Sachin Prabhu47c78f42013-03-11 13:08:49 +00001575 if (rc == 0 || rc != -EBUSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001576 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001577
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001578 /* open-file renames don't work across directories */
1579 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001580 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001581
Steve Frenchee2fd962008-09-23 18:23:33 +00001582 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001583 rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE,
Steve Frenchee2fd962008-09-23 18:23:33 +00001584 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1585 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1586 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchee2fd962008-09-23 18:23:33 +00001587 if (rc == 0) {
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001588 rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001589 (const char *) to_dentry->d_name.name,
1590 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1591 CIFS_MOUNT_MAP_SPECIAL_CHR);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001592 CIFSSMBClose(xid, tcon, srcfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001593 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001594do_rename_exit:
1595 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001596 return rc;
1597}
1598
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001599int
1600cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1601 struct inode *target_dir, struct dentry *target_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001603 char *from_name = NULL;
1604 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001605 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001606 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001607 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001608 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1609 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001610 unsigned int xid;
1611 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612
Jeff Layton639e7a92010-09-03 11:50:09 -04001613 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001614 tlink = cifs_sb_tlink(cifs_sb);
1615 if (IS_ERR(tlink))
1616 return PTR_ERR(tlink);
1617 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001619 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001620
1621 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001622 * we already have the rename sem so we do not need to
1623 * grab it again here to protect the path integrity
1624 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001625 from_name = build_path_from_dentry(source_dentry);
1626 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 rc = -ENOMEM;
1628 goto cifs_rename_exit;
1629 }
1630
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001631 to_name = build_path_from_dentry(target_dentry);
1632 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001633 rc = -ENOMEM;
1634 goto cifs_rename_exit;
1635 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001637 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1638 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001639
Jeff Layton14121bd2008-10-20 14:45:22 -04001640 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001641 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001642 * Are src and dst hardlinks of same inode? We can only tell
1643 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001644 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001645 info_buf_source =
1646 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1647 GFP_KERNEL);
1648 if (info_buf_source == NULL) {
1649 rc = -ENOMEM;
1650 goto cifs_rename_exit;
1651 }
1652
1653 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001654 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1655 info_buf_source,
1656 cifs_sb->local_nls,
1657 cifs_sb->mnt_cifs_flags &
1658 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton8d281ef2008-10-22 13:57:01 -04001659 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001660 goto unlink_target;
1661
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001662 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1663 info_buf_target,
1664 cifs_sb->local_nls,
1665 cifs_sb->mnt_cifs_flags &
1666 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton14121bd2008-10-20 14:45:22 -04001667
Jeff Layton8d281ef2008-10-22 13:57:01 -04001668 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001669 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001670 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001671 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001672 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001673 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001674 }
1675 /*
1676 * else ... BB we could add the same check for Windows by
1677 * checking the UniqueId via FILE_INTERNAL_INFO
1678 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001679
Jeff Layton14121bd2008-10-20 14:45:22 -04001680unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001681 /* Try unlinking the target dentry if it's not negative */
1682 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Jeff Layton8d281ef2008-10-22 13:57:01 -04001683 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001684 if (tmprc)
1685 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001686 rc = cifs_do_rename(xid, source_dentry, from_name,
1687 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 }
1689
1690cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001691 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001692 kfree(from_name);
1693 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001694 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001695 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 return rc;
1697}
1698
Jeff Laytondf2cf172010-02-12 07:44:16 -05001699static bool
1700cifs_inode_needs_reval(struct inode *inode)
1701{
1702 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301703 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001704
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001705 if (CIFS_CACHE_READ(cifs_i))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001706 return false;
1707
1708 if (!lookupCacheEnabled)
1709 return true;
1710
1711 if (cifs_i->time == 0)
1712 return true;
1713
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301714 if (!time_in_range(jiffies, cifs_i->time,
1715 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001716 return true;
1717
Jeff Laytondb192722010-05-17 14:51:49 -04001718 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301719 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001720 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1721 return true;
1722
Jeff Laytondf2cf172010-02-12 07:44:16 -05001723 return false;
1724}
1725
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301726/*
1727 * Zap the cache. Called when invalid_mapping flag is set.
1728 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001729int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001730cifs_invalidate_mapping(struct inode *inode)
1731{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001732 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001733 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1734
1735 cifs_i->invalid_mapping = false;
1736
Jeff Laytondf2cf172010-02-12 07:44:16 -05001737 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001738 rc = invalidate_inode_pages2(inode->i_mapping);
1739 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001740 cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
1741 __func__, inode);
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001742 cifs_i->invalid_mapping = true;
1743 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001744 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001745
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301746 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001747 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001748}
1749
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001750int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001751{
1752 int rc = 0;
Al Viro496ad9a2013-01-23 17:07:38 -05001753 struct inode *inode = file_inode(filp);
Jeff Laytonba00ba642010-09-20 16:01:31 -07001754 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001755
1756 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001757 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001758
Jeff Layton13cfb732010-09-29 19:51:11 -04001759 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001760 rc = cifs_get_file_info_unix(filp);
1761 else
1762 rc = cifs_get_file_info(filp);
1763
Jeff Laytonabab0952010-02-12 07:44:18 -05001764 return rc;
1765}
1766
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001767int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001769 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001770 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001771 struct inode *inode = dentry->d_inode;
1772 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001773 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774
Jeff Laytondf2cf172010-02-12 07:44:16 -05001775 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 return -ENOENT;
1777
Jeff Laytondf2cf172010-02-12 07:44:16 -05001778 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001779 return rc;
1780
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001781 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
1783 /* can not safely grab the rename sem here if rename calls revalidate
1784 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001785 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301787 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001788 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001790
Joe Perchesf96637b2013-05-04 22:12:25 -05001791 cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
1792 full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001793 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794
Jeff Layton0d424ad2010-09-20 16:01:35 -07001795 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001796 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1797 else
1798 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1799 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001801out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001803 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 return rc;
1805}
1806
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001807int cifs_revalidate_file(struct file *filp)
1808{
1809 int rc;
Al Viro496ad9a2013-01-23 17:07:38 -05001810 struct inode *inode = file_inode(filp);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001811
1812 rc = cifs_revalidate_file_attr(filp);
1813 if (rc)
1814 return rc;
1815
1816 if (CIFS_I(inode)->invalid_mapping)
1817 rc = cifs_invalidate_mapping(inode);
1818 return rc;
1819}
1820
1821/* revalidate a dentry's inode attributes */
1822int cifs_revalidate_dentry(struct dentry *dentry)
1823{
1824 int rc;
1825 struct inode *inode = dentry->d_inode;
1826
1827 rc = cifs_revalidate_dentry_attr(dentry);
1828 if (rc)
1829 return rc;
1830
1831 if (CIFS_I(inode)->invalid_mapping)
1832 rc = cifs_invalidate_mapping(inode);
1833 return rc;
1834}
1835
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001837 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001839 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001840 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001841 struct inode *inode = dentry->d_inode;
1842 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001843
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001844 /*
1845 * We need to be sure that all dirty pages are written and the server
1846 * has actual ctime, mtime and file length.
1847 */
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001848 if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001849 inode->i_mapping->nrpages != 0) {
1850 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001851 if (rc) {
1852 mapping_set_error(inode->i_mapping, rc);
1853 return rc;
1854 }
Steve French5fe14c82006-11-07 19:26:33 +00001855 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001856
1857 rc = cifs_revalidate_dentry_attr(dentry);
1858 if (rc)
1859 return rc;
1860
1861 generic_fillattr(inode, stat);
1862 stat->blksize = CIFS_MAX_MSGSIZE;
1863 stat->ino = CIFS_I(inode)->uniqueid;
1864
1865 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001866 * If on a multiuser mount without unix extensions or cifsacl being
1867 * enabled, and the admin hasn't overridden them, set the ownership
1868 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001869 */
1870 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001871 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001872 !tcon->unix_ext) {
1873 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1874 stat->uid = current_fsuid();
1875 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1876 stat->gid = current_fsgid();
1877 }
1878 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879}
1880
1881static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1882{
1883 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1884 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1885 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 int rc = 0;
1887
1888 page = grab_cache_page(mapping, index);
1889 if (!page)
1890 return -ENOMEM;
1891
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001892 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 unlock_page(page);
1894 page_cache_release(page);
1895 return rc;
1896}
1897
Christoph Hellwig1b947462010-07-18 17:51:21 -04001898static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001899{
Steve Frenchba6a46a2007-02-26 20:06:29 +00001900 spin_lock(&inode->i_lock);
Steve French3677db12007-02-26 16:46:11 +00001901 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001902 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001903
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001904 truncate_pagecache(inode, offset);
Steve French3677db12007-02-26 16:46:11 +00001905}
1906
Jeff Layton8efdbde2008-07-23 21:28:12 +00001907static int
1908cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001909 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00001910{
1911 int rc;
1912 struct cifsFileInfo *open_file;
1913 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1914 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001915 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001916 struct cifs_tcon *tcon = NULL;
1917 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001918 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001919
1920 /*
1921 * To avoid spurious oplock breaks from server, in the case of
1922 * inodes that we already have open, avoid doing path based
1923 * setting of file size if we can do it by handle.
1924 * This keeps our caching token (oplock) and avoids timeouts
1925 * when the local oplock break takes longer to flush
1926 * writebehind data than the SMB timeout for the SetPathInfo
1927 * request would allow
1928 */
Jeff Layton6508d902010-09-29 19:51:11 -04001929 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001930 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001931 tcon = tlink_tcon(open_file->tlink);
1932 server = tcon->ses->server;
1933 if (server->ops->set_file_size)
1934 rc = server->ops->set_file_size(xid, tcon, open_file,
1935 attrs->ia_size, false);
1936 else
1937 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001938 cifsFileInfo_put(open_file);
Joe Perchesf96637b2013-05-04 22:12:25 -05001939 cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001940 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1941 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001942
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001943 io_parms.netfid = open_file->fid.netfid;
1944 io_parms.pid = open_file->pid;
1945 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001946 io_parms.offset = 0;
1947 io_parms.length = attrs->ia_size;
1948 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1949 NULL, NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001950 cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001951 }
1952 } else
1953 rc = -EINVAL;
1954
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001955 if (!rc)
1956 goto set_size_out;
Jeff Laytonba00ba642010-09-20 16:01:31 -07001957
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001958 if (tcon == NULL) {
1959 tlink = cifs_sb_tlink(cifs_sb);
1960 if (IS_ERR(tlink))
1961 return PTR_ERR(tlink);
1962 tcon = tlink_tcon(tlink);
1963 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001964 }
1965
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001966 /*
1967 * Set file size by pathname rather than by handle either because no
1968 * valid, writeable file handle for it was found or because there was
1969 * an error setting it by handle.
1970 */
1971 if (server->ops->set_path_size)
1972 rc = server->ops->set_path_size(xid, tcon, full_path,
1973 attrs->ia_size, cifs_sb, false);
1974 else
1975 rc = -ENOSYS;
Joe Perchesf96637b2013-05-04 22:12:25 -05001976 cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001977 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1978 __u16 netfid;
1979 int oplock = 0;
1980
1981 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
1982 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
1983 &oplock, NULL, cifs_sb->local_nls,
1984 cifs_sb->mnt_cifs_flags &
1985 CIFS_MOUNT_MAP_SPECIAL_CHR);
1986 if (rc == 0) {
1987 unsigned int bytes_written;
1988
1989 io_parms.netfid = netfid;
1990 io_parms.pid = current->tgid;
1991 io_parms.tcon = tcon;
1992 io_parms.offset = 0;
1993 io_parms.length = attrs->ia_size;
1994 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
1995 NULL, 1);
Joe Perchesf96637b2013-05-04 22:12:25 -05001996 cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001997 CIFSSMBClose(xid, tcon, netfid);
1998 }
1999 }
2000 if (tlink)
2001 cifs_put_tlink(tlink);
2002
2003set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00002004 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04002005 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04002006 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00002007 cifs_truncate_page(inode->i_mapping, inode->i_size);
2008 }
2009
2010 return rc;
2011}
2012
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002013static int
2014cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2015{
2016 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002017 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002018 char *full_path = NULL;
2019 struct inode *inode = direntry->d_inode;
2020 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2021 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04002022 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00002023 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002024 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002025 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002026
Joe Perchesf96637b2013-05-04 22:12:25 -05002027 cifs_dbg(FYI, "setattr_unix on file %s attrs->ia_valid=0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002028 direntry->d_name.name, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002029
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002030 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002031
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002032 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2033 attrs->ia_valid |= ATTR_FORCE;
2034
2035 rc = inode_change_ok(inode, attrs);
2036 if (rc < 0)
2037 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002038
2039 full_path = build_path_from_dentry(direntry);
2040 if (full_path == NULL) {
2041 rc = -ENOMEM;
2042 goto out;
2043 }
2044
Jeff Layton0f4d6342009-03-26 13:35:37 -04002045 /*
2046 * Attempt to flush data before changing attributes. We need to do
2047 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2048 * ownership or mode then we may also need to do this. Here, we take
2049 * the safe way out and just do the flush on all setattr requests. If
2050 * the flush returns error, store it to report later and continue.
2051 *
2052 * BB: This should be smarter. Why bother flushing pages that
2053 * will be truncated anyway? Also, should we error out here if
2054 * the flush returns error?
2055 */
2056 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002057 mapping_set_error(inode->i_mapping, rc);
2058 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002059
2060 if (attrs->ia_valid & ATTR_SIZE) {
2061 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2062 if (rc != 0)
2063 goto out;
2064 }
2065
2066 /* skip mode change if it's just for clearing setuid/setgid */
2067 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2068 attrs->ia_valid &= ~ATTR_MODE;
2069
2070 args = kmalloc(sizeof(*args), GFP_KERNEL);
2071 if (args == NULL) {
2072 rc = -ENOMEM;
2073 goto out;
2074 }
2075
2076 /* set up the struct */
2077 if (attrs->ia_valid & ATTR_MODE)
2078 args->mode = attrs->ia_mode;
2079 else
2080 args->mode = NO_CHANGE_64;
2081
2082 if (attrs->ia_valid & ATTR_UID)
2083 args->uid = attrs->ia_uid;
2084 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002085 args->uid = INVALID_UID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002086
2087 if (attrs->ia_valid & ATTR_GID)
2088 args->gid = attrs->ia_gid;
2089 else
Eric W. Biederman49418b22013-02-06 00:57:56 -08002090 args->gid = INVALID_GID; /* no change */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002091
2092 if (attrs->ia_valid & ATTR_ATIME)
2093 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2094 else
2095 args->atime = NO_CHANGE_64;
2096
2097 if (attrs->ia_valid & ATTR_MTIME)
2098 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2099 else
2100 args->mtime = NO_CHANGE_64;
2101
2102 if (attrs->ia_valid & ATTR_CTIME)
2103 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2104 else
2105 args->ctime = NO_CHANGE_64;
2106
2107 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002108 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002109 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002110 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002111 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002112 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002113 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002114 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002115 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002116 tlink = cifs_sb_tlink(cifs_sb);
2117 if (IS_ERR(tlink)) {
2118 rc = PTR_ERR(tlink);
2119 goto out;
2120 }
2121 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002122 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002123 cifs_sb->local_nls,
2124 cifs_sb->mnt_cifs_flags &
2125 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002126 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002127 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002128
Christoph Hellwig10257742010-06-04 11:30:02 +02002129 if (rc)
2130 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002131
Christoph Hellwig10257742010-06-04 11:30:02 +02002132 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002133 attrs->ia_size != i_size_read(inode))
2134 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002135
2136 setattr_copy(inode, attrs);
2137 mark_inode_dirty(inode);
2138
2139 /* force revalidate when any of these times are set since some
2140 of the fs types (eg ext3, fat) do not have fine enough
2141 time granularity to match protocol, and we do not have a
2142 a way (yet) to query the server fs's time granularity (and
2143 whether it rounds times down).
2144 */
2145 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2146 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002147out:
2148 kfree(args);
2149 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002150 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002151 return rc;
2152}
2153
Jeff Layton0510eeb2008-08-02 07:26:12 -04002154static int
2155cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002157 unsigned int xid;
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002158 kuid_t uid = INVALID_UID;
2159 kgid_t gid = INVALID_GID;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002160 struct inode *inode = direntry->d_inode;
2161 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002162 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 char *full_path = NULL;
2164 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002165 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002166 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002167
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002168 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
Joe Perchesf96637b2013-05-04 22:12:25 -05002170 cifs_dbg(FYI, "setattr on file %s attrs->iavalid 0x%x\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00002171 direntry->d_name.name, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002172
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002173 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2174 attrs->ia_valid |= ATTR_FORCE;
2175
2176 rc = inode_change_ok(inode, attrs);
2177 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002178 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002179 return rc;
Steve French6473a552005-11-29 20:20:10 -08002180 }
Steve French50c2f752007-07-13 00:33:32 +00002181
Steve French7f573562005-08-30 11:32:14 -07002182 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302184 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002185 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302186 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188
Jeff Layton0f4d6342009-03-26 13:35:37 -04002189 /*
2190 * Attempt to flush data before changing attributes. We need to do
2191 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2192 * ownership or mode then we may also need to do this. Here, we take
2193 * the safe way out and just do the flush on all setattr requests. If
2194 * the flush returns error, store it to report later and continue.
2195 *
2196 * BB: This should be smarter. Why bother flushing pages that
2197 * will be truncated anyway? Also, should we error out here if
2198 * the flush returns error?
2199 */
2200 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002201 mapping_set_error(inode->i_mapping, rc);
2202 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002203
Steve French50531442008-03-14 19:21:31 +00002204 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002205 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2206 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002207 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002209
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002210 if (attrs->ia_valid & ATTR_UID)
2211 uid = attrs->ia_uid;
2212
2213 if (attrs->ia_valid & ATTR_GID)
2214 gid = attrs->ia_gid;
2215
2216#ifdef CONFIG_CIFS_ACL
2217 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002218 if (uid_valid(uid) || gid_valid(gid)) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002219 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2220 uid, gid);
2221 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002222 cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
2223 __func__, rc);
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002224 goto cifs_setattr_exit;
2225 }
2226 }
2227 } else
2228#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002229 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002230 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231
Jeff Laytond32c4f22007-10-18 03:05:22 -07002232 /* skip mode change if it's just for clearing setuid/setgid */
2233 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2234 attrs->ia_valid &= ~ATTR_MODE;
2235
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 mode = attrs->ia_mode;
Steve Frenchcdbce9c82005-11-19 21:04:52 -08002238 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002239#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002240 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002241 rc = id_mode_to_cifs_acl(inode, full_path, mode,
Eric W. Biederman8abf2772013-02-06 00:33:17 -08002242 INVALID_UID, INVALID_GID);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002243 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002244 cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
2245 __func__, rc);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002246 goto cifs_setattr_exit;
2247 }
2248 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002249#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002250 if (((mode & S_IWUGO) == 0) &&
2251 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002252
2253 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2254
Jeff Layton51328612008-05-22 09:33:34 -04002255 /* fix up mode if we're not using dynperm */
2256 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2257 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2258 } else if ((mode & S_IWUGO) &&
2259 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002260
2261 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2262 /* Attributes of 0 are ignored */
2263 if (dosattr == 0)
2264 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002265
2266 /* reset local inode permissions to normal */
2267 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2268 attrs->ia_mode &= ~(S_IALLUGO);
2269 if (S_ISDIR(inode->i_mode))
2270 attrs->ia_mode |=
2271 cifs_sb->mnt_dir_mode;
2272 else
2273 attrs->ia_mode |=
2274 cifs_sb->mnt_file_mode;
2275 }
2276 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2277 /* ignore mode change - ATTR_READONLY hasn't changed */
2278 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 }
2281
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002282 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2283 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2284 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2285 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
Steve Frenche30dcf32005-09-20 20:49:16 -07002287 /* Even if error on time set, no sense failing the call if
2288 the server would set the time to a reasonable value anyway,
2289 and this check ensures that we are not being called from
2290 sys_utimes in which case we ought to fail the call back to
2291 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002292 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002293 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002294 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 }
2296
2297 /* do not need local check to inode_check_ok since the server does
2298 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002299 if (rc)
2300 goto cifs_setattr_exit;
2301
2302 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002303 attrs->ia_size != i_size_read(inode))
2304 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002305
2306 setattr_copy(inode, attrs);
2307 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002308
Steve Frenche30dcf32005-09-20 20:49:16 -07002309cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002311 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 return rc;
2313}
2314
Jeff Layton0510eeb2008-08-02 07:26:12 -04002315int
2316cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2317{
2318 struct inode *inode = direntry->d_inode;
2319 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002320 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002321
2322 if (pTcon->unix_ext)
2323 return cifs_setattr_unix(direntry, attrs);
2324
2325 return cifs_setattr_nounix(direntry, attrs);
2326
2327 /* BB: add cifs_setattr_legacy for really old servers */
2328}
2329
Steve French99ee4db2007-02-27 05:35:17 +00002330#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331void cifs_delete_inode(struct inode *inode)
2332{
Joe Perchesf96637b2013-05-04 22:12:25 -05002333 cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 /* may have to add back in if and when safe distributed caching of
2335 directories added e.g. via FindNotify */
2336}
Steve French99ee4db2007-02-27 05:35:17 +00002337#endif