blob: d7ea2a6eaead910595f3c7b8e3252b21a34398d2 [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
Steve Frenchf19159d2010-04-21 04:12:10 +000094 cFYI(1, "%s: revalidating inode %llu", __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -050095
96 if (inode->i_state & I_NEW) {
Steve Frenchf19159d2010-04-21 04:12:10 +000097 cFYI(1, "%s: inode %llu is new", __func__, cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -050098 return;
99 }
100
101 /* don't bother with revalidation if we have an oplock */
102 if (cifs_i->clientCanCacheRead) {
Steve Frenchf19159d2010-04-21 04:12:10 +0000103 cFYI(1, "%s: inode %llu is oplocked", __func__,
104 cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500105 return;
106 }
107
108 /* revalidate if mtime or size have changed */
109 if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
110 cifs_i->server_eof == fattr->cf_eof) {
Steve Frenchf19159d2010-04-21 04:12:10 +0000111 cFYI(1, "%s: inode %llu is unchanged", __func__,
112 cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500113 return;
114 }
115
Steve Frenchf19159d2010-04-21 04:12:10 +0000116 cFYI(1, "%s: invalidating inode %llu mapping", __func__,
117 cifs_i->uniqueid);
Jeff Laytondf2cf172010-02-12 07:44:16 -0500118 cifs_i->invalid_mapping = true;
119}
120
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400121/* populate an inode with info from a cifs_fattr struct */
122void
123cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
Christoph Hellwig75f12982008-02-25 20:25:21 +0000124{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400125 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400126 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000127
Jeff Laytondf2cf172010-02-12 07:44:16 -0500128 cifs_revalidate_cache(inode, fattr);
129
Steve Frenchb7ca6922012-08-03 08:43:01 -0500130 spin_lock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400131 inode->i_atime = fattr->cf_atime;
132 inode->i_mtime = fattr->cf_mtime;
133 inode->i_ctime = fattr->cf_ctime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400134 inode->i_rdev = fattr->cf_rdev;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200135 set_nlink(inode, fattr->cf_nlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400136 inode->i_uid = fattr->cf_uid;
137 inode->i_gid = fattr->cf_gid;
138
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400139 /* if dynperm is set, don't clobber existing mode */
140 if (inode->i_state & I_NEW ||
141 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
142 inode->i_mode = fattr->cf_mode;
143
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400144 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400145
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400146 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
147 cifs_i->time = 0;
148 else
149 cifs_i->time = jiffies;
150
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400151 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000152
Jeff Layton835a36c2010-02-10 16:21:33 -0500153 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000154 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400155 * Can't safely change the file size here if the client is writing to
156 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000157 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400158 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
159 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000160
161 /*
162 * i_blocks is not related to (i_size / i_blksize),
163 * but instead 512 byte (2**9) size is required for
164 * calculating num blocks.
165 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400166 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000167 }
168 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400169
David Howells01c64fe2011-01-14 18:45:47 +0000170 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
171 inode->i_flags |= S_AUTOMOUNT;
172 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000173}
174
Jeff Layton4065c802010-05-17 07:18:58 -0400175void
176cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
177{
178 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
179
180 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
181 return;
182
183 fattr->cf_uniqueid = iunique(sb, ROOT_I);
184}
185
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400186/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
187void
188cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
189 struct cifs_sb_info *cifs_sb)
190{
191 memset(fattr, 0, sizeof(*fattr));
192 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
193 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
194 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
195
196 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
197 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
198 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
199 fattr->cf_mode = le64_to_cpu(info->Permissions);
200
201 /*
202 * Since we set the inode type below we need to mask off
203 * to avoid strange results if bits set above.
204 */
205 fattr->cf_mode &= ~S_IFMT;
206 switch (le32_to_cpu(info->Type)) {
207 case UNIX_FILE:
208 fattr->cf_mode |= S_IFREG;
209 fattr->cf_dtype = DT_REG;
210 break;
211 case UNIX_SYMLINK:
212 fattr->cf_mode |= S_IFLNK;
213 fattr->cf_dtype = DT_LNK;
214 break;
215 case UNIX_DIR:
216 fattr->cf_mode |= S_IFDIR;
217 fattr->cf_dtype = DT_DIR;
218 break;
219 case UNIX_CHARDEV:
220 fattr->cf_mode |= S_IFCHR;
221 fattr->cf_dtype = DT_CHR;
222 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
223 le64_to_cpu(info->DevMinor) & MINORMASK);
224 break;
225 case UNIX_BLOCKDEV:
226 fattr->cf_mode |= S_IFBLK;
227 fattr->cf_dtype = DT_BLK;
228 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
229 le64_to_cpu(info->DevMinor) & MINORMASK);
230 break;
231 case UNIX_FIFO:
232 fattr->cf_mode |= S_IFIFO;
233 fattr->cf_dtype = DT_FIFO;
234 break;
235 case UNIX_SOCKET:
236 fattr->cf_mode |= S_IFSOCK;
237 fattr->cf_dtype = DT_SOCK;
238 break;
239 default:
240 /* safest to call it a file if we do not know */
241 fattr->cf_mode |= S_IFREG;
242 fattr->cf_dtype = DT_REG;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000243 cFYI(1, "unknown type %d", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400244 break;
245 }
246
Eric W. Biederman46bbc252013-02-05 23:55:44 -0800247 fattr->cf_uid = cifs_sb->mnt_uid;
248 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
249 u64 id = le64_to_cpu(info->Uid);
250 if (id < ((uid_t)-1))
251 fattr->cf_uid = id;
252 }
253
254 fattr->cf_gid = cifs_sb->mnt_gid;
255 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
256 u64 id = le64_to_cpu(info->Gid);
257 if (id < ((gid_t)-1))
258 fattr->cf_gid = id;
259 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400260
261 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
262}
Steve Frenchb9a32602008-05-20 21:52:32 +0000263
264/*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400265 * Fill a cifs_fattr struct with fake inode info.
266 *
267 * Needed to setup cifs_fattr data for the directory which is the
268 * junction to the new submount (ie to setup the fake directory
269 * which represents a DFS referral).
Steve Frenchb9a32602008-05-20 21:52:32 +0000270 */
Steve Frenchf1230c92009-07-22 23:13:01 +0000271static void
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400272cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
Steve French0e4bbde2008-05-20 19:50:46 +0000273{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400274 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French0e4bbde2008-05-20 19:50:46 +0000275
Joe Perchesb6b38f72010-04-21 03:50:45 +0000276 cFYI(1, "creating fake fattr for DFS referral");
Steve French0e4bbde2008-05-20 19:50:46 +0000277
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400278 memset(fattr, 0, sizeof(*fattr));
279 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
280 fattr->cf_uid = cifs_sb->mnt_uid;
281 fattr->cf_gid = cifs_sb->mnt_gid;
282 fattr->cf_atime = CURRENT_TIME;
283 fattr->cf_ctime = CURRENT_TIME;
284 fattr->cf_mtime = CURRENT_TIME;
285 fattr->cf_nlink = 2;
286 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
Steve French0e4bbde2008-05-20 19:50:46 +0000287}
288
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700289static int
290cifs_get_file_info_unix(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500291{
292 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400293 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500294 FILE_UNIX_BASIC_INFO find_data;
295 struct cifs_fattr fattr;
296 struct inode *inode = filp->f_path.dentry->d_inode;
297 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700298 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000299 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500300
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400301 xid = get_xid();
Pavel Shilovsky4b4de762012-09-18 16:20:26 -0700302 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->fid.netfid, &find_data);
Jeff Laytonabab0952010-02-12 07:44:18 -0500303 if (!rc) {
304 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
305 } else if (rc == -EREMOTE) {
306 cifs_create_dfs_fattr(&fattr, inode->i_sb);
307 rc = 0;
308 }
309
310 cifs_fattr_to_inode(inode, &fattr);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400311 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500312 return rc;
313}
314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400316 const unsigned char *full_path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400317 struct super_block *sb, unsigned int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400319 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000320 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400321 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000322 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400323 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
Joe Perchesb6b38f72010-04-21 03:50:45 +0000326 cFYI(1, "Getting info on %s", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000327
Jeff Layton7ffec372010-09-29 19:51:11 -0400328 tlink = cifs_sb_tlink(cifs_sb);
329 if (IS_ERR(tlink))
330 return PTR_ERR(tlink);
331 tcon = tlink_tcon(tlink);
332
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400334 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Steve French737b7582005-04-28 22:41:06 -0700335 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
336 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400337 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400338
339 if (!rc) {
340 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
341 } else if (rc == -EREMOTE) {
342 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700343 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400344 } else {
345 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000346 }
347
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200348 /* check for Minshall+French symlinks */
349 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
350 int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
351 if (tmprc)
352 cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
353 }
354
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400355 if (*pinode == NULL) {
356 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400357 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400358 *pinode = cifs_iget(sb, &fattr);
359 if (!*pinode)
360 rc = -ENOMEM;
361 } else {
362 /* we already have inode, update it */
363 cifs_fattr_to_inode(*pinode, &fattr);
364 }
Steve French0e4bbde2008-05-20 19:50:46 +0000365
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 return rc;
367}
368
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400369static int
370cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400371 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800372{
373 int rc;
Steve French4b18f2a2008-04-29 00:06:05 +0000374 int oplock = 0;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800375 __u16 netfid;
Jeff Layton7ffec372010-09-29 19:51:11 -0400376 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000377 struct cifs_tcon *tcon;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000378 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800379 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800380 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000381 char *pbuf;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800382
383 pbuf = buf;
384
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400385 fattr->cf_mode &= ~S_IFMT;
386
387 if (fattr->cf_eof == 0) {
388 fattr->cf_mode |= S_IFIFO;
389 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800390 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400391 } else if (fattr->cf_eof < 8) {
392 fattr->cf_mode |= S_IFREG;
393 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800394 return -EINVAL; /* EOPNOTSUPP? */
395 }
Steve French50c2f752007-07-13 00:33:32 +0000396
Jeff Layton7ffec372010-09-29 19:51:11 -0400397 tlink = cifs_sb_tlink(cifs_sb);
398 if (IS_ERR(tlink))
399 return PTR_ERR(tlink);
400 tcon = tlink_tcon(tlink);
401
402 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800403 CREATE_NOT_DIR, &netfid, &oplock, NULL,
404 cifs_sb->local_nls,
405 cifs_sb->mnt_cifs_flags &
406 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000407 if (rc == 0) {
Steve Frenchec637e32005-12-12 20:53:18 -0800408 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800409 /* Read header */
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000410 io_parms.netfid = netfid;
411 io_parms.pid = current->tgid;
412 io_parms.tcon = tcon;
413 io_parms.offset = 0;
414 io_parms.length = 24;
415 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
416 &buf_type);
Steve French4523cc32007-04-30 20:13:06 +0000417 if ((rc == 0) && (bytes_read >= 8)) {
418 if (memcmp("IntxBLK", pbuf, 8) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000419 cFYI(1, "Block device");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400420 fattr->cf_mode |= S_IFBLK;
421 fattr->cf_dtype = DT_BLK;
Steve French4523cc32007-04-30 20:13:06 +0000422 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800423 /* we have enough to decode dev num */
424 __u64 mjr; /* major */
425 __u64 mnr; /* minor */
426 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
427 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400428 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve French86c96b42005-11-18 20:25:31 -0800429 }
Steve French4523cc32007-04-30 20:13:06 +0000430 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000431 cFYI(1, "Char device");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400432 fattr->cf_mode |= S_IFCHR;
433 fattr->cf_dtype = DT_CHR;
Steve French4523cc32007-04-30 20:13:06 +0000434 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800435 /* we have enough to decode dev num */
436 __u64 mjr; /* major */
437 __u64 mnr; /* minor */
438 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
439 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400440 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000441 }
Steve French4523cc32007-04-30 20:13:06 +0000442 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000443 cFYI(1, "Symlink");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400444 fattr->cf_mode |= S_IFLNK;
445 fattr->cf_dtype = DT_LNK;
Steve French86c96b42005-11-18 20:25:31 -0800446 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400447 fattr->cf_mode |= S_IFREG; /* file? */
448 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000449 rc = -EOPNOTSUPP;
Steve French86c96b42005-11-18 20:25:31 -0800450 }
Steve French3020a1f2005-11-18 11:31:10 -0800451 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400452 fattr->cf_mode |= S_IFREG; /* then it is a file */
453 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000454 rc = -EOPNOTSUPP; /* or some unknown SFU type */
455 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400456 CIFSSMBClose(xid, tcon, netfid);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800457 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400458 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800459 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800460}
461
Steve French9e294f12005-11-17 16:59:21 -0800462#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
463
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400464/*
465 * Fetch mode bits as provided by SFU.
466 *
467 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
468 */
469static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400470 struct cifs_sb_info *cifs_sb, unsigned int xid)
Steve French9e294f12005-11-17 16:59:21 -0800471{
Steve French3020a1f2005-11-18 11:31:10 -0800472#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800473 ssize_t rc;
474 char ea_value[4];
475 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400476 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000477 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800478
Jeff Layton7ffec372010-09-29 19:51:11 -0400479 tlink = cifs_sb_tlink(cifs_sb);
480 if (IS_ERR(tlink))
481 return PTR_ERR(tlink);
482 tcon = tlink_tcon(tlink);
483
484 rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400485 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
486 cifs_sb->mnt_cifs_flags &
487 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400488 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000489 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800490 return (int)rc;
491 else if (rc > 3) {
492 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400493 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000494 cFYI(1, "special bits 0%o org mode 0%o", mode,
495 fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400496 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000497 cFYI(1, "special mode bits 0%o", mode);
Steve French9e294f12005-11-17 16:59:21 -0800498 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400499
500 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800501#else
502 return -EOPNOTSUPP;
503#endif
Steve French9e294f12005-11-17 16:59:21 -0800504}
505
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400506/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000507static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400508cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
509 struct cifs_sb_info *cifs_sb, bool adjust_tz)
Steve Frenchb9a32602008-05-20 21:52:32 +0000510{
Steve French96daf2b2011-05-27 04:34:02 +0000511 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700512
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400513 memset(fattr, 0, sizeof(*fattr));
514 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
515 if (info->DeletePending)
516 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000517
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400518 if (info->LastAccessTime)
519 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
520 else
521 fattr->cf_atime = CURRENT_TIME;
522
523 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
524 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
525
526 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700527 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
528 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400529 }
530
531 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
532 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500533 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400534
535 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
536 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
537 fattr->cf_dtype = DT_DIR;
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300538 /*
539 * Server can return wrong NumberOfLinks value for directories
540 * when Unix extensions are disabled - fake it.
541 */
542 fattr->cf_nlink = 2;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400543 } else {
544 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
545 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400546
Jeff Laytond0c280d2009-07-09 01:46:44 -0400547 /* clear write bits if ATTR_READONLY is set */
548 if (fattr->cf_cifsattrs & ATTR_READONLY)
549 fattr->cf_mode &= ~(S_IWUGO);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400550
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +0300551 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
552 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400553
554 fattr->cf_uid = cifs_sb->mnt_uid;
555 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000556}
557
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700558static int
559cifs_get_file_info(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -0500560{
561 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400562 unsigned int xid;
Jeff Laytonabab0952010-02-12 07:44:18 -0500563 FILE_ALL_INFO find_data;
564 struct cifs_fattr fattr;
565 struct inode *inode = filp->f_path.dentry->d_inode;
566 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700567 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000568 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700569 struct TCP_Server_Info *server = tcon->ses->server;
570
571 if (!server->ops->query_file_info)
572 return -ENOSYS;
Jeff Laytonabab0952010-02-12 07:44:18 -0500573
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400574 xid = get_xid();
Pavel Shilovsky4ad65042012-09-18 16:20:26 -0700575 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400576 switch (rc) {
577 case 0:
578 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
579 break;
580 case -EREMOTE:
581 cifs_create_dfs_fattr(&fattr, inode->i_sb);
582 rc = 0;
583 break;
584 case -EOPNOTSUPP:
585 case -EINVAL:
Jeff Laytonabab0952010-02-12 07:44:18 -0500586 /*
587 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000588 * for now, just skip revalidating and mark inode for
589 * immediate reval.
590 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500591 rc = 0;
592 CIFS_I(inode)->time = 0;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400593 default:
Jeff Laytonabab0952010-02-12 07:44:18 -0500594 goto cgfi_exit;
Pavel Shilovsky42274bb2011-10-22 14:37:50 +0400595 }
Jeff Laytonabab0952010-02-12 07:44:18 -0500596
597 /*
598 * don't bother with SFU junk here -- just mark inode as needing
599 * revalidation.
600 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500601 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
602 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
603 cifs_fattr_to_inode(inode, &fattr);
604cgfi_exit:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400605 free_xid(xid);
Jeff Laytonabab0952010-02-12 07:44:18 -0500606 return rc;
607}
608
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400609int
610cifs_get_inode_info(struct inode **inode, const char *full_path,
611 FILE_ALL_INFO *data, struct super_block *sb, int xid,
612 const __u16 *fid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613{
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500614 bool validinum = false;
615 __u16 srchflgs;
616 int rc = 0, tmprc = ENOSYS;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400617 struct cifs_tcon *tcon;
618 struct TCP_Server_Info *server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400619 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 char *buf = NULL;
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400622 bool adjust_tz = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400623 struct cifs_fattr fattr;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500624 struct cifs_search_info *srchinf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
Jeff Layton7ffec372010-09-29 19:51:11 -0400626 tlink = cifs_sb_tlink(cifs_sb);
627 if (IS_ERR(tlink))
628 return PTR_ERR(tlink);
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400629 tcon = tlink_tcon(tlink);
630 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -0400631
Joe Perchesb6b38f72010-04-21 03:50:45 +0000632 cFYI(1, "Getting info on %s", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400634 if ((data == NULL) && (*inode != NULL)) {
635 if (CIFS_I(*inode)->clientCanCacheRead) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000636 cFYI(1, "No need to revalidate cached inode sizes");
Jeff Layton7ffec372010-09-29 19:51:11 -0400637 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 }
639 }
640
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400641 /* if inode info is not passed, get it from server */
642 if (data == NULL) {
643 if (!server->ops->query_path_info) {
644 rc = -ENOSYS;
645 goto cgii_exit;
646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400648 if (buf == NULL) {
649 rc = -ENOMEM;
650 goto cgii_exit;
651 }
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400652 data = (FILE_ALL_INFO *)buf;
653 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
654 data, &adjust_tz);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400656
657 if (!rc) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400658 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb,
659 adjust_tz);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400660 } else if (rc == -EREMOTE) {
661 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000662 rc = 0;
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500663 } else if (rc == -EACCES && backup_cred(cifs_sb)) {
664 srchinf = kzalloc(sizeof(struct cifs_search_info),
665 GFP_KERNEL);
666 if (srchinf == NULL) {
667 rc = -ENOMEM;
668 goto cgii_exit;
669 }
670
671 srchinf->endOfSearch = false;
672 srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
673
674 srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
675 CIFS_SEARCH_CLOSE_AT_END |
676 CIFS_SEARCH_BACKUP_SEARCH;
677
678 rc = CIFSFindFirst(xid, tcon, full_path,
679 cifs_sb, NULL, srchflgs, srchinf, false);
680 if (!rc) {
681 data =
682 (FILE_ALL_INFO *)srchinf->srch_entries_start;
683
684 cifs_dir_info_to_fattr(&fattr,
685 (FILE_DIRECTORY_INFO *)data, cifs_sb);
686 fattr.cf_uniqueid = le64_to_cpu(
687 ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
688 validinum = true;
689
690 cifs_buf_release(srchinf->ntwrk_buf_start);
691 }
692 kfree(srchinf);
693 } else
Igor Mammedov79626702008-03-09 03:44:18 +0000694 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400696 /*
697 * If an inode wasn't passed in, then get the inode number
698 *
699 * Is an i_ino of zero legal? Can we use that to check if the server
700 * supports returning inode numbers? Are there other sanity checks we
701 * can use to ensure that the server is really filling in that field?
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400702 */
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400703 if (*inode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000704 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500705 if (validinum == false) {
706 if (server->ops->get_srv_inum)
707 tmprc = server->ops->get_srv_inum(xid,
708 tcon, cifs_sb, full_path,
709 &fattr.cf_uniqueid, data);
710 if (tmprc) {
711 cFYI(1, "GetSrvInodeNum rc %d", tmprc);
712 fattr.cf_uniqueid = iunique(sb, ROOT_I);
713 cifs_autodisable_serverino(cifs_sb);
714 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500715 }
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500716 } else
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400717 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Shirish Pargaonkarc052e2b2012-09-28 12:21:14 -0500718 } else
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400719 fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000720
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400721 /* query for SFU type info if supported and needed */
722 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
723 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
724 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
725 if (tmprc)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000726 cFYI(1, "cifs_sfu_type failed: %d", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000727 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000728
Jeff Layton79df1ba2010-12-06 12:52:08 -0500729#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000730 /* fill in 0777 bits from ACL */
731 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400732 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, full_path, fid);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600733 if (rc) {
734 cFYI(1, "%s: Getting ACL failed with error: %d",
735 __func__, rc);
736 goto cgii_exit;
737 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000738 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500739#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400740
741 /* fill in remaining high mode bits e.g. SUID, VTX */
742 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
743 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
744
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200745 /* check for Minshall+French symlinks */
746 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
747 tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
748 if (tmprc)
749 cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
750 }
751
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400752 if (!*inode) {
753 *inode = cifs_iget(sb, &fattr);
754 if (!*inode)
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400755 rc = -ENOMEM;
756 } else {
Pavel Shilovsky1208ef12012-05-27 17:34:43 +0400757 cifs_fattr_to_inode(*inode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000758 }
759
Igor Mammedov79626702008-03-09 03:44:18 +0000760cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400762 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 return rc;
764}
765
Steve French7f8ed422007-09-28 22:28:55 +0000766static const struct inode_operations cifs_ipc_inode_ops = {
767 .lookup = cifs_lookup,
768};
769
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400770static int
771cifs_find_inode(struct inode *inode, void *opaque)
772{
773 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
774
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400775 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400776 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
777 return 0;
778
Jeff Layton20054bd2011-01-07 11:30:27 -0500779 /* use createtime like an i_generation field */
780 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
781 return 0;
782
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400783 /* don't match inode of different type */
784 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
785 return 0;
786
Jeff Layton5acfec22010-08-02 17:43:54 -0400787 /* if it's not a directory or has no dentries, then flag it */
Al Virob3d9b7a2012-06-09 13:51:19 -0400788 if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400789 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400790
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400791 return 1;
792}
793
794static int
795cifs_init_inode(struct inode *inode, void *opaque)
796{
797 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
798
799 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500800 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400801 return 0;
802}
803
Jeff Layton5acfec22010-08-02 17:43:54 -0400804/*
805 * walk dentry list for an inode and report whether it has aliases that
806 * are hashed. We use this to determine if a directory inode can actually
807 * be used.
808 */
809static bool
810inode_has_hashed_dentries(struct inode *inode)
811{
812 struct dentry *dentry;
Al Virob3d9b7a2012-06-09 13:51:19 -0400813 struct hlist_node *p;
Jeff Layton5acfec22010-08-02 17:43:54 -0400814
Nick Piggin873feea2011-01-07 17:50:06 +1100815 spin_lock(&inode->i_lock);
Al Virob3d9b7a2012-06-09 13:51:19 -0400816 hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400817 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100818 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400819 return true;
820 }
821 }
Nick Piggin873feea2011-01-07 17:50:06 +1100822 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400823 return false;
824}
825
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400826/* Given fattrs, get a corresponding inode */
827struct inode *
828cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
829{
830 unsigned long hash;
831 struct inode *inode;
832
Jeff Layton3d694382010-05-11 14:59:55 -0400833retry_iget5_locked:
Joe Perchesb6b38f72010-04-21 03:50:45 +0000834 cFYI(1, "looking for uniqueid=%llu", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400835
836 /* hash down to 32-bits on 32-bit arch */
837 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
838
839 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400840 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400841 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400842 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400843 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400844
845 if (inode_has_hashed_dentries(inode)) {
846 cifs_autodisable_serverino(CIFS_SB(sb));
847 iput(inode);
848 fattr->cf_uniqueid = iunique(sb, ROOT_I);
849 goto retry_iget5_locked;
850 }
Jeff Layton3d694382010-05-11 14:59:55 -0400851 }
852
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400853 cifs_fattr_to_inode(inode, fattr);
854 if (sb->s_flags & MS_NOATIME)
855 inode->i_flags |= S_NOATIME | S_NOCMTIME;
856 if (inode->i_state & I_NEW) {
857 inode->i_ino = hash;
Jeff Layton522440e2010-09-29 09:49:54 -0400858 if (S_ISREG(inode->i_mode))
859 inode->i_data.backing_dev_info = sb->s_bdi;
Steve French0ccd4802010-07-16 04:31:02 +0000860#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530861 /* initialize per-inode cache cookie pointer */
862 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000863#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400864 unlock_new_inode(inode);
865 }
866 }
867
868 return inode;
869}
870
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600872struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400874 unsigned int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700875 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400876 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800877 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000878 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800879
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400880 xid = get_xid();
Jeff Layton0d424ad2010-09-20 16:01:35 -0700881 if (tcon->unix_ext)
Steve Frenchf87d39d2011-05-27 03:50:55 +0000882 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400883 else
Steve Frenchf87d39d2011-05-27 03:50:55 +0000884 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400885
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000886 if (!inode) {
887 inode = ERR_PTR(rc);
888 goto out;
889 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400890
Steve French0ccd4802010-07-16 04:31:02 +0000891#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530892 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700893 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000894#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530895
Jeff Layton0d424ad2010-09-20 16:01:35 -0700896 if (rc && tcon->ipc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000897 cFYI(1, "ipc connection - fake read inode");
Steve Frenchb7ca6922012-08-03 08:43:01 -0500898 spin_lock(&inode->i_lock);
Steve French7f8ed422007-09-28 22:28:55 +0000899 inode->i_mode |= S_IFDIR;
Miklos Szeredibfe86842011-10-28 14:13:29 +0200900 set_nlink(inode, 2);
Steve French7f8ed422007-09-28 22:28:55 +0000901 inode->i_op = &cifs_ipc_inode_ops;
902 inode->i_fop = &simple_dir_operations;
903 inode->i_uid = cifs_sb->mnt_uid;
904 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchb7ca6922012-08-03 08:43:01 -0500905 spin_unlock(&inode->i_lock);
Steve Frenchad661332008-08-12 14:14:40 +0000906 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800907 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000908 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000909 }
910
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000911out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400912 /* can not call macro free_xid here since in a void func
David Howellsce634ab2008-02-07 00:15:33 -0800913 * TODO: This is no longer true
914 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400915 _free_xid(xid);
David Howellsce634ab2008-02-07 00:15:33 -0800916 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917}
918
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700919int
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +0400920cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700921 char *full_path, __u32 dosattr)
Steve French388e57b2008-09-16 23:50:58 +0000922{
Steve French388e57b2008-09-16 23:50:58 +0000923 bool set_time = false;
Steve French388e57b2008-09-16 23:50:58 +0000924 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700925 struct TCP_Server_Info *server;
Steve French388e57b2008-09-16 23:50:58 +0000926 FILE_BASIC_INFO info_buf;
927
Steve French1adcb712009-02-25 14:19:56 +0000928 if (attrs == NULL)
929 return -EINVAL;
930
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700931 server = cifs_sb_master_tcon(cifs_sb)->ses->server;
932 if (!server->ops->set_file_info)
933 return -ENOSYS;
934
Steve French388e57b2008-09-16 23:50:58 +0000935 if (attrs->ia_valid & ATTR_ATIME) {
936 set_time = true;
937 info_buf.LastAccessTime =
938 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
939 } else
940 info_buf.LastAccessTime = 0;
941
942 if (attrs->ia_valid & ATTR_MTIME) {
943 set_time = true;
944 info_buf.LastWriteTime =
945 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
946 } else
947 info_buf.LastWriteTime = 0;
948
949 /*
950 * Samba throws this field away, but windows may actually use it.
951 * Do not set ctime unless other time stamps are changed explicitly
952 * (i.e. by utimes()) since we would then have a mix of client and
953 * server times.
954 */
955 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000956 cFYI(1, "CIFS - CTIME changed");
Steve French388e57b2008-09-16 23:50:58 +0000957 info_buf.ChangeTime =
958 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
959 } else
960 info_buf.ChangeTime = 0;
961
962 info_buf.CreationTime = 0; /* don't change */
963 info_buf.Attributes = cpu_to_le32(dosattr);
964
Pavel Shilovsky6bdf6db2012-09-18 16:20:32 -0700965 return server->ops->set_file_info(inode, full_path, &info_buf, xid);
Steve French388e57b2008-09-16 23:50:58 +0000966}
967
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400968/*
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700969 * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400970 * and rename it to a random name that hopefully won't conflict with
971 * anything else.
972 */
Pavel Shilovskyed6875e2012-09-18 16:20:25 -0700973int
974cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
975 const unsigned int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400976{
977 int oplock = 0;
978 int rc;
979 __u16 netfid;
Steve French32709582008-10-20 00:44:19 +0000980 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400981 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
982 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400983 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000984 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +0000985 __u32 dosattr, origattr;
986 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400987
Jeff Layton7ffec372010-09-29 19:51:11 -0400988 tlink = cifs_sb_tlink(cifs_sb);
989 if (IS_ERR(tlink))
990 return PTR_ERR(tlink);
991 tcon = tlink_tcon(tlink);
992
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400993 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
Jeff Laytondd1db2d2008-10-16 19:27:12 -0400994 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
Jeff Laytona12a1ac2008-09-23 11:48:35 -0400995 &netfid, &oplock, NULL, cifs_sb->local_nls,
996 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
997 if (rc != 0)
998 goto out;
999
Steve French32709582008-10-20 00:44:19 +00001000 origattr = cifsInode->cifsAttrs;
1001 if (origattr == 0)
1002 origattr |= ATTR_NORMAL;
1003
1004 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001005 if (dosattr == 0)
1006 dosattr |= ATTR_NORMAL;
1007 dosattr |= ATTR_HIDDEN;
1008
Steve French32709582008-10-20 00:44:19 +00001009 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1010 if (dosattr != origattr) {
1011 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1012 if (info_buf == NULL) {
1013 rc = -ENOMEM;
1014 goto out_close;
1015 }
1016 info_buf->Attributes = cpu_to_le32(dosattr);
1017 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1018 current->tgid);
1019 /* although we would like to mark the file hidden
1020 if that fails we will still try to rename it */
Steve French41346092008-10-20 18:24:42 +00001021 if (rc != 0)
Steve French32709582008-10-20 00:44:19 +00001022 cifsInode->cifsAttrs = dosattr;
1023 else
1024 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001025 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001026
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001027 /* rename the file */
1028 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001029 cifs_sb->mnt_cifs_flags &
1030 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French32709582008-10-20 00:44:19 +00001031 if (rc != 0) {
1032 rc = -ETXTBSY;
1033 goto undo_setattr;
1034 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001035
Steve French32709582008-10-20 00:44:19 +00001036 /* try to set DELETE_ON_CLOSE */
1037 if (!cifsInode->delete_pending) {
1038 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
1039 current->tgid);
1040 /*
1041 * some samba versions return -ENOENT when we try to set the
1042 * file disposition here. Likely a samba bug, but work around
1043 * it for now. This means that some cifsXXX files may hang
1044 * around after they shouldn't.
1045 *
1046 * BB: remove this hack after more servers have the fix
1047 */
1048 if (rc == -ENOENT)
1049 rc = 0;
1050 else if (rc != 0) {
1051 rc = -ETXTBSY;
1052 goto undo_rename;
1053 }
1054 cifsInode->delete_pending = true;
1055 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001056
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001057out_close:
1058 CIFSSMBClose(xid, tcon, netfid);
1059out:
Steve French32709582008-10-20 00:44:19 +00001060 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001061 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001062 return rc;
Steve French32709582008-10-20 00:44:19 +00001063
1064 /*
1065 * reset everything back to the original state. Don't bother
1066 * dealing with errors here since we can't do anything about
1067 * them anyway.
1068 */
1069undo_rename:
1070 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
1071 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1072 CIFS_MOUNT_MAP_SPECIAL_CHR);
1073undo_setattr:
1074 if (dosattr != origattr) {
1075 info_buf->Attributes = cpu_to_le32(origattr);
1076 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1077 current->tgid))
1078 cifsInode->cifsAttrs = origattr;
1079 }
1080
1081 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001082}
1083
Steve Frenchb7ca6922012-08-03 08:43:01 -05001084/* copied from fs/nfs/dir.c with small changes */
1085static void
1086cifs_drop_nlink(struct inode *inode)
1087{
1088 spin_lock(&inode->i_lock);
1089 if (inode->i_nlink > 0)
1090 drop_nlink(inode);
1091 spin_unlock(&inode->i_lock);
1092}
Steve Frenchff694522009-04-20 19:45:13 +00001093
1094/*
1095 * If dentry->d_inode is null (usually meaning the cached dentry
1096 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001097 * if that fails we can not attempt the fall back mechanisms on EACCESS
1098 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001099 * unlink on negative dentries currently.
1100 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001101int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102{
1103 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001104 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001106 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001107 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001108 struct super_block *sb = dir->i_sb;
1109 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001110 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001111 struct cifs_tcon *tcon;
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001112 struct TCP_Server_Info *server;
Steve French60502472008-10-07 18:42:52 +00001113 struct iattr *attrs = NULL;
1114 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Joe Perchesb6b38f72010-04-21 03:50:45 +00001116 cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Jeff Layton7ffec372010-09-29 19:51:11 -04001118 tlink = cifs_sb_tlink(cifs_sb);
1119 if (IS_ERR(tlink))
1120 return PTR_ERR(tlink);
1121 tcon = tlink_tcon(tlink);
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001122 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001123
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001124 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
Jeff Layton5f0319a2008-09-16 14:05:16 -04001126 /* Unlink can be called from rename so we can not take the
1127 * sb->s_vfs_rename_mutex here */
1128 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301130 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001131 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 }
Steve French2d785a52007-07-15 01:48:57 +00001133
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001134 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1135 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001136 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001137 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1138 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001139 cFYI(1, "posix del rc %d", rc);
Steve French2d785a52007-07-15 01:48:57 +00001140 if ((rc == 0) || (rc == -ENOENT))
1141 goto psx_del_no_retry;
1142 }
1143
Steve French60502472008-10-07 18:42:52 +00001144retry_std_delete:
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001145 if (!server->ops->unlink) {
1146 rc = -ENOSYS;
1147 goto psx_del_no_retry;
1148 }
1149
1150 rc = server->ops->unlink(xid, tcon, full_path, cifs_sb);
Steve French60502472008-10-07 18:42:52 +00001151
Steve French2d785a52007-07-15 01:48:57 +00001152psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001154 if (inode)
Steve Frenchb7ca6922012-08-03 08:43:01 -05001155 cifs_drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001157 d_drop(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 } else if (rc == -ETXTBSY) {
Pavel Shilovskyed6875e2012-09-18 16:20:25 -07001159 if (server->ops->rename_pending_delete) {
1160 rc = server->ops->rename_pending_delete(full_path,
1161 dentry, xid);
1162 if (rc == 0)
1163 cifs_drop_nlink(inode);
1164 }
1165 if (rc == -ETXTBSY)
1166 rc = -EBUSY;
Steve Frenchff694522009-04-20 19:45:13 +00001167 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001168 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1169 if (attrs == NULL) {
1170 rc = -ENOMEM;
1171 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 }
Steve French388e57b2008-09-16 23:50:58 +00001173
1174 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001175 cifs_inode = CIFS_I(inode);
1176 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001177 if (origattr == 0)
1178 origattr |= ATTR_NORMAL;
1179 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001180 if (dosattr == 0)
1181 dosattr |= ATTR_NORMAL;
1182 dosattr |= ATTR_HIDDEN;
1183
1184 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001185 if (rc != 0)
1186 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001187
1188 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 }
Steve French60502472008-10-07 18:42:52 +00001190
1191 /* undo the setattr if we errored out and it's needed */
1192 if (rc != 0 && dosattr != 0)
1193 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1194
Steve French388e57b2008-09-16 23:50:58 +00001195out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001196 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001197 cifs_inode = CIFS_I(inode);
1198 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001199 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001200 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001201 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001202 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001203 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001204 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001205unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001207 kfree(attrs);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001208 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001209 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 return rc;
1211}
1212
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001213static int
Jeff Layton101b92d2012-09-19 06:22:45 -07001214cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001215 const char *full_path, struct cifs_sb_info *cifs_sb,
1216 struct cifs_tcon *tcon, const unsigned int xid)
1217{
1218 int rc = 0;
Jeff Layton101b92d2012-09-19 06:22:45 -07001219 struct inode *inode = NULL;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001220
1221 if (tcon->unix_ext)
Jeff Layton101b92d2012-09-19 06:22:45 -07001222 rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001223 xid);
1224 else
Jeff Layton101b92d2012-09-19 06:22:45 -07001225 rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb,
1226 xid, NULL);
1227
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001228 if (rc)
1229 return rc;
1230
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001231 /*
1232 * setting nlink not necessary except in cases where we failed to get it
Jeff Layton101b92d2012-09-19 06:22:45 -07001233 * from the server or was set bogus. Also, since this is a brand new
1234 * inode, no need to grab the i_lock before setting the i_nlink.
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001235 */
Jeff Layton101b92d2012-09-19 06:22:45 -07001236 if (inode->i_nlink < 2)
1237 set_nlink(inode, 2);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001238 mode &= ~current_umask();
1239 /* must turn on setgid bit if parent dir has it */
Jeff Layton101b92d2012-09-19 06:22:45 -07001240 if (parent->i_mode & S_ISGID)
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001241 mode |= S_ISGID;
1242
1243 if (tcon->unix_ext) {
1244 struct cifs_unix_set_info_args args = {
1245 .mode = mode,
1246 .ctime = NO_CHANGE_64,
1247 .atime = NO_CHANGE_64,
1248 .mtime = NO_CHANGE_64,
1249 .device = 0,
1250 };
1251 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1252 args.uid = (__u64)current_fsuid();
Jeff Layton101b92d2012-09-19 06:22:45 -07001253 if (parent->i_mode & S_ISGID)
1254 args.gid = (__u64)parent->i_gid;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001255 else
1256 args.gid = (__u64)current_fsgid();
1257 } else {
1258 args.uid = NO_CHANGE_64;
1259 args.gid = NO_CHANGE_64;
1260 }
1261 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
1262 cifs_sb->local_nls,
1263 cifs_sb->mnt_cifs_flags &
1264 CIFS_MOUNT_MAP_SPECIAL_CHR);
1265 } else {
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001266 struct TCP_Server_Info *server = tcon->ses->server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001267 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001268 (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
Jeff Layton101b92d2012-09-19 06:22:45 -07001269 server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001270 tcon, xid);
Jeff Layton101b92d2012-09-19 06:22:45 -07001271 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
1272 inode->i_mode = (mode | S_IFDIR);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001273
Jeff Layton101b92d2012-09-19 06:22:45 -07001274 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1275 inode->i_uid = current_fsuid();
1276 if (inode->i_mode & S_ISGID)
1277 inode->i_gid = parent->i_gid;
1278 else
1279 inode->i_gid = current_fsgid();
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001280 }
1281 }
Jeff Layton101b92d2012-09-19 06:22:45 -07001282 d_instantiate(dentry, inode);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001283 return rc;
1284}
1285
1286static int
1287cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode,
1288 const char *full_path, struct cifs_sb_info *cifs_sb,
1289 struct cifs_tcon *tcon, const unsigned int xid)
1290{
1291 int rc = 0;
1292 u32 oplock = 0;
1293 FILE_UNIX_BASIC_INFO *info = NULL;
1294 struct inode *newinode = NULL;
1295 struct cifs_fattr fattr;
1296
1297 info = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1298 if (info == NULL) {
1299 rc = -ENOMEM;
1300 goto posix_mkdir_out;
1301 }
1302
1303 mode &= ~current_umask();
1304 rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode,
1305 NULL /* netfid */, info, &oplock, full_path,
1306 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1307 CIFS_MOUNT_MAP_SPECIAL_CHR);
1308 if (rc == -EOPNOTSUPP)
1309 goto posix_mkdir_out;
1310 else if (rc) {
1311 cFYI(1, "posix mkdir returned 0x%x", rc);
1312 d_drop(dentry);
1313 goto posix_mkdir_out;
1314 }
1315
1316 if (info->Type == cpu_to_le32(-1))
1317 /* no return info, go query for it */
1318 goto posix_mkdir_get_info;
1319 /*
1320 * BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if
1321 * need to set uid/gid.
1322 */
1323
1324 cifs_unix_basic_to_fattr(&fattr, info, cifs_sb);
1325 cifs_fill_uniqueid(inode->i_sb, &fattr);
1326 newinode = cifs_iget(inode->i_sb, &fattr);
1327 if (!newinode)
1328 goto posix_mkdir_get_info;
1329
1330 d_instantiate(dentry, newinode);
1331
1332#ifdef CONFIG_CIFS_DEBUG2
1333 cFYI(1, "instantiated dentry %p %s to inode %p", dentry,
1334 dentry->d_name.name, newinode);
1335
1336 if (newinode->i_nlink != 2)
1337 cFYI(1, "unexpected number of links %d", newinode->i_nlink);
1338#endif
1339
1340posix_mkdir_out:
1341 kfree(info);
1342 return rc;
1343posix_mkdir_get_info:
1344 rc = cifs_mkdir_qinfo(inode, dentry, mode, full_path, cifs_sb, tcon,
1345 xid);
1346 goto posix_mkdir_out;
1347}
1348
Al Viro18bb1db2011-07-26 01:41:39 -04001349int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350{
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001351 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001352 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001354 struct tcon_link *tlink;
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001355 struct cifs_tcon *tcon;
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001356 struct TCP_Server_Info *server;
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001357 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Al Viro18bb1db2011-07-26 01:41:39 -04001359 cFYI(1, "In cifs_mkdir, mode = 0x%hx inode = 0x%p", mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001362 tlink = cifs_sb_tlink(cifs_sb);
1363 if (IS_ERR(tlink))
1364 return PTR_ERR(tlink);
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001365 tcon = tlink_tcon(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -04001366
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001367 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
Steve French7f573562005-08-30 11:32:14 -07001369 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301371 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001372 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 }
Steve French50c2f752007-07-13 00:33:32 +00001374
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04001375 if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1376 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001377 rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
1378 tcon, xid);
1379 if (rc != -EOPNOTSUPP)
Steve French2dd29d32007-04-23 22:07:35 +00001380 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001381 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001382
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001383 server = tcon->ses->server;
1384
1385 if (!server->ops->mkdir) {
1386 rc = -ENOSYS;
1387 goto mkdir_out;
1388 }
1389
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Pavel Shilovskyf4367202012-03-17 11:41:12 +03001391 rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001393 cFYI(1, "cifs_mkdir returned 0x%x", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 d_drop(direntry);
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001395 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 }
Pavel Shilovskyff691e92012-07-13 14:04:46 +04001397
1398 rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
1399 xid);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001400mkdir_out:
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001401 /*
1402 * Force revalidate to get parent dir info when needed since cached
1403 * attributes are invalid now.
1404 */
1405 CIFS_I(inode)->time = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001407 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001408 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 return rc;
1410}
1411
1412int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1413{
1414 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001415 unsigned int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001417 struct tcon_link *tlink;
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001418 struct cifs_tcon *tcon;
1419 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 char *full_path = NULL;
1421 struct cifsInodeInfo *cifsInode;
1422
Joe Perchesb6b38f72010-04-21 03:50:45 +00001423 cFYI(1, "cifs_rmdir, inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001425 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
Steve French7f573562005-08-30 11:32:14 -07001427 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301429 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001430 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 }
1432
Jeff Layton7ffec372010-09-29 19:51:11 -04001433 cifs_sb = CIFS_SB(inode->i_sb);
1434 tlink = cifs_sb_tlink(cifs_sb);
1435 if (IS_ERR(tlink)) {
1436 rc = PTR_ERR(tlink);
1437 goto rmdir_exit;
1438 }
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001439 tcon = tlink_tcon(tlink);
1440 server = tcon->ses->server;
Jeff Layton7ffec372010-09-29 19:51:11 -04001441
Pavel Shilovskyf958ca52012-07-10 16:14:18 +04001442 if (!server->ops->rmdir) {
1443 rc = -ENOSYS;
1444 cifs_put_tlink(tlink);
1445 goto rmdir_exit;
1446 }
1447
1448 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001449 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
1451 if (!rc) {
Steve French3677db12007-02-26 16:46:11 +00001452 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001453 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001454 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001455 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 }
1457
1458 cifsInode = CIFS_I(direntry->d_inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001459 /* force revalidate to go get info when needed */
1460 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001461
1462 cifsInode = CIFS_I(inode);
Pavel Shilovsky6de2ce42012-02-17 16:13:30 +03001463 /*
1464 * Force revalidate to get parent dir info when needed since cached
1465 * attributes are invalid now.
1466 */
1467 cifsInode->time = 0;
Steve French42c24542009-01-13 22:03:55 +00001468
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1470 current_fs_time(inode->i_sb);
1471
Jeff Layton7ffec372010-09-29 19:51:11 -04001472rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001474 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 return rc;
1476}
1477
Steve Frenchee2fd962008-09-23 18:23:33 +00001478static int
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001479cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1480 const char *from_path, struct dentry *to_dentry,
1481 const char *to_path)
Steve Frenchee2fd962008-09-23 18:23:33 +00001482{
1483 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001484 struct tcon_link *tlink;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001485 struct cifs_tcon *tcon;
1486 struct TCP_Server_Info *server;
Steve Frenchee2fd962008-09-23 18:23:33 +00001487 __u16 srcfid;
1488 int oplock, rc;
1489
Jeff Layton7ffec372010-09-29 19:51:11 -04001490 tlink = cifs_sb_tlink(cifs_sb);
1491 if (IS_ERR(tlink))
1492 return PTR_ERR(tlink);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001493 tcon = tlink_tcon(tlink);
1494 server = tcon->ses->server;
1495
1496 if (!server->ops->rename)
1497 return -ENOSYS;
Jeff Layton7ffec372010-09-29 19:51:11 -04001498
Steve Frenchee2fd962008-09-23 18:23:33 +00001499 /* try path-based rename first */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001500 rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
Steve Frenchee2fd962008-09-23 18:23:33 +00001501
1502 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001503 * Don't bother with rename by filehandle unless file is busy and
1504 * source. Note that cross directory moves do not work with
Steve Frenchee2fd962008-09-23 18:23:33 +00001505 * rename by filehandle to various Windows servers.
1506 */
1507 if (rc == 0 || rc != -ETXTBSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001508 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001509
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001510 /* open-file renames don't work across directories */
1511 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001512 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001513
Steve Frenchee2fd962008-09-23 18:23:33 +00001514 /* open the file to be renamed -- we need DELETE perms */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001515 rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE,
Steve Frenchee2fd962008-09-23 18:23:33 +00001516 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1517 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1518 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchee2fd962008-09-23 18:23:33 +00001519 if (rc == 0) {
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001520 rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
Steve Frenchee2fd962008-09-23 18:23:33 +00001521 (const char *) to_dentry->d_name.name,
1522 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1523 CIFS_MOUNT_MAP_SPECIAL_CHR);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001524 CIFSSMBClose(xid, tcon, srcfid);
Steve Frenchee2fd962008-09-23 18:23:33 +00001525 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001526do_rename_exit:
1527 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001528 return rc;
1529}
1530
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001531int
1532cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1533 struct inode *target_dir, struct dentry *target_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534{
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001535 char *from_name = NULL;
1536 char *to_name = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001537 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001538 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001539 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001540 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1541 FILE_UNIX_BASIC_INFO *info_buf_target;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001542 unsigned int xid;
1543 int rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544
Jeff Layton639e7a92010-09-03 11:50:09 -04001545 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001546 tlink = cifs_sb_tlink(cifs_sb);
1547 if (IS_ERR(tlink))
1548 return PTR_ERR(tlink);
1549 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001551 xid = get_xid();
Steve Frenchee2fd962008-09-23 18:23:33 +00001552
1553 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001554 * we already have the rename sem so we do not need to
1555 * grab it again here to protect the path integrity
1556 */
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001557 from_name = build_path_from_dentry(source_dentry);
1558 if (from_name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 rc = -ENOMEM;
1560 goto cifs_rename_exit;
1561 }
1562
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001563 to_name = build_path_from_dentry(target_dentry);
1564 if (to_name == NULL) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001565 rc = -ENOMEM;
1566 goto cifs_rename_exit;
1567 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001569 rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
1570 to_name);
Steve Frenchee2fd962008-09-23 18:23:33 +00001571
Jeff Layton14121bd2008-10-20 14:45:22 -04001572 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001573 /*
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001574 * Are src and dst hardlinks of same inode? We can only tell
1575 * with unix extensions enabled.
Steve Frenchee2fd962008-09-23 18:23:33 +00001576 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001577 info_buf_source =
1578 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1579 GFP_KERNEL);
1580 if (info_buf_source == NULL) {
1581 rc = -ENOMEM;
1582 goto cifs_rename_exit;
1583 }
1584
1585 info_buf_target = info_buf_source + 1;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001586 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
1587 info_buf_source,
1588 cifs_sb->local_nls,
1589 cifs_sb->mnt_cifs_flags &
1590 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton8d281ef2008-10-22 13:57:01 -04001591 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001592 goto unlink_target;
1593
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001594 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
1595 info_buf_target,
1596 cifs_sb->local_nls,
1597 cifs_sb->mnt_cifs_flags &
1598 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton14121bd2008-10-20 14:45:22 -04001599
Jeff Layton8d281ef2008-10-22 13:57:01 -04001600 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001601 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001602 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001603 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001604 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001605 }
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001606 }
1607 /*
1608 * else ... BB we could add the same check for Windows by
1609 * checking the UniqueId via FILE_INTERNAL_INFO
1610 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001611
Jeff Layton14121bd2008-10-20 14:45:22 -04001612unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001613 /* Try unlinking the target dentry if it's not negative */
1614 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Jeff Layton8d281ef2008-10-22 13:57:01 -04001615 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001616 if (tmprc)
1617 goto cifs_rename_exit;
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001618 rc = cifs_do_rename(xid, source_dentry, from_name,
1619 target_dentry, to_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 }
1621
1622cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001623 kfree(info_buf_source);
Pavel Shilovsky8ceb9842012-09-18 16:20:30 -07001624 kfree(from_name);
1625 kfree(to_name);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001626 free_xid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001627 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 return rc;
1629}
1630
Jeff Laytondf2cf172010-02-12 07:44:16 -05001631static bool
1632cifs_inode_needs_reval(struct inode *inode)
1633{
1634 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301635 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001636
1637 if (cifs_i->clientCanCacheRead)
1638 return false;
1639
1640 if (!lookupCacheEnabled)
1641 return true;
1642
1643 if (cifs_i->time == 0)
1644 return true;
1645
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301646 if (!time_in_range(jiffies, cifs_i->time,
1647 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001648 return true;
1649
Jeff Laytondb192722010-05-17 14:51:49 -04001650 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301651 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001652 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1653 return true;
1654
Jeff Laytondf2cf172010-02-12 07:44:16 -05001655 return false;
1656}
1657
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301658/*
1659 * Zap the cache. Called when invalid_mapping flag is set.
1660 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001661int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001662cifs_invalidate_mapping(struct inode *inode)
1663{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001664 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001665 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1666
1667 cifs_i->invalid_mapping = false;
1668
Jeff Laytondf2cf172010-02-12 07:44:16 -05001669 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001670 rc = invalidate_inode_pages2(inode->i_mapping);
1671 if (rc) {
1672 cERROR(1, "%s: could not invalidate inode %p", __func__,
1673 inode);
1674 cifs_i->invalid_mapping = true;
1675 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001676 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001677
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301678 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001679 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001680}
1681
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001682int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001683{
1684 int rc = 0;
1685 struct inode *inode = filp->f_path.dentry->d_inode;
Jeff Laytonba00ba62010-09-20 16:01:31 -07001686 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001687
1688 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001689 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001690
Jeff Layton13cfb732010-09-29 19:51:11 -04001691 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001692 rc = cifs_get_file_info_unix(filp);
1693 else
1694 rc = cifs_get_file_info(filp);
1695
Jeff Laytonabab0952010-02-12 07:44:18 -05001696 return rc;
1697}
1698
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001699int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001701 unsigned int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001702 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001703 struct inode *inode = dentry->d_inode;
1704 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001705 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
Jeff Laytondf2cf172010-02-12 07:44:16 -05001707 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 return -ENOENT;
1709
Jeff Laytondf2cf172010-02-12 07:44:16 -05001710 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001711 return rc;
1712
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001713 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
1715 /* can not safely grab the rename sem here if rename calls revalidate
1716 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001717 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301719 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001720 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001722
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001723 cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time "
1724 "%ld jiffies %ld", full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001725 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Jeff Layton0d424ad2010-09-20 16:01:35 -07001727 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001728 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1729 else
1730 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1731 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001733out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001735 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 return rc;
1737}
1738
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001739int cifs_revalidate_file(struct file *filp)
1740{
1741 int rc;
1742 struct inode *inode = filp->f_path.dentry->d_inode;
1743
1744 rc = cifs_revalidate_file_attr(filp);
1745 if (rc)
1746 return rc;
1747
1748 if (CIFS_I(inode)->invalid_mapping)
1749 rc = cifs_invalidate_mapping(inode);
1750 return rc;
1751}
1752
1753/* revalidate a dentry's inode attributes */
1754int cifs_revalidate_dentry(struct dentry *dentry)
1755{
1756 int rc;
1757 struct inode *inode = dentry->d_inode;
1758
1759 rc = cifs_revalidate_dentry_attr(dentry);
1760 if (rc)
1761 return rc;
1762
1763 if (CIFS_I(inode)->invalid_mapping)
1764 rc = cifs_invalidate_mapping(inode);
1765 return rc;
1766}
1767
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001769 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001771 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001772 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001773 struct inode *inode = dentry->d_inode;
1774 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001775
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001776 /*
1777 * We need to be sure that all dirty pages are written and the server
1778 * has actual ctime, mtime and file length.
1779 */
1780 if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
1781 inode->i_mapping->nrpages != 0) {
1782 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001783 if (rc) {
1784 mapping_set_error(inode->i_mapping, rc);
1785 return rc;
1786 }
Steve French5fe14c82006-11-07 19:26:33 +00001787 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001788
1789 rc = cifs_revalidate_dentry_attr(dentry);
1790 if (rc)
1791 return rc;
1792
1793 generic_fillattr(inode, stat);
1794 stat->blksize = CIFS_MAX_MSGSIZE;
1795 stat->ino = CIFS_I(inode)->uniqueid;
1796
1797 /*
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001798 * If on a multiuser mount without unix extensions or cifsacl being
1799 * enabled, and the admin hasn't overridden them, set the ownership
1800 * to the fsuid/fsgid of the current process.
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001801 */
1802 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
Jeff Laytond3d1fce2012-11-25 08:00:40 -05001803 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001804 !tcon->unix_ext) {
1805 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1806 stat->uid = current_fsuid();
1807 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1808 stat->gid = current_fsgid();
1809 }
1810 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811}
1812
1813static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1814{
1815 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1816 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1817 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 int rc = 0;
1819
1820 page = grab_cache_page(mapping, index);
1821 if (!page)
1822 return -ENOMEM;
1823
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001824 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 unlock_page(page);
1826 page_cache_release(page);
1827 return rc;
1828}
1829
Christoph Hellwig1b947462010-07-18 17:51:21 -04001830static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001831{
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001832 loff_t oldsize;
Steve French3677db12007-02-26 16:46:11 +00001833
Steve Frenchba6a46a2007-02-26 20:06:29 +00001834 spin_lock(&inode->i_lock);
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001835 oldsize = inode->i_size;
Steve French3677db12007-02-26 16:46:11 +00001836 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001837 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001838
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001839 truncate_pagecache(inode, oldsize, offset);
Steve French3677db12007-02-26 16:46:11 +00001840}
1841
Jeff Layton8efdbde2008-07-23 21:28:12 +00001842static int
1843cifs_set_file_size(struct inode *inode, struct iattr *attrs,
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001844 unsigned int xid, char *full_path)
Jeff Layton8efdbde2008-07-23 21:28:12 +00001845{
1846 int rc;
1847 struct cifsFileInfo *open_file;
1848 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1849 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001850 struct tcon_link *tlink = NULL;
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001851 struct cifs_tcon *tcon = NULL;
1852 struct TCP_Server_Info *server;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001853 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001854
1855 /*
1856 * To avoid spurious oplock breaks from server, in the case of
1857 * inodes that we already have open, avoid doing path based
1858 * setting of file size if we can do it by handle.
1859 * This keeps our caching token (oplock) and avoids timeouts
1860 * when the local oplock break takes longer to flush
1861 * writebehind data than the SMB timeout for the SetPathInfo
1862 * request would allow
1863 */
Jeff Layton6508d902010-09-29 19:51:11 -04001864 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001865 if (open_file) {
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001866 tcon = tlink_tcon(open_file->tlink);
1867 server = tcon->ses->server;
1868 if (server->ops->set_file_size)
1869 rc = server->ops->set_file_size(xid, tcon, open_file,
1870 attrs->ia_size, false);
1871 else
1872 rc = -ENOSYS;
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001873 cifsFileInfo_put(open_file);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001874 cFYI(1, "SetFSize for attrs rc = %d", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001875 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1876 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001877
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001878 io_parms.netfid = open_file->fid.netfid;
1879 io_parms.pid = open_file->pid;
1880 io_parms.tcon = tcon;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001881 io_parms.offset = 0;
1882 io_parms.length = attrs->ia_size;
1883 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1884 NULL, NULL, 1);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001885 cFYI(1, "Wrt seteof rc %d", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001886 }
1887 } else
1888 rc = -EINVAL;
1889
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001890 if (!rc)
1891 goto set_size_out;
Jeff Laytonba00ba62010-09-20 16:01:31 -07001892
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001893 if (tcon == NULL) {
1894 tlink = cifs_sb_tlink(cifs_sb);
1895 if (IS_ERR(tlink))
1896 return PTR_ERR(tlink);
1897 tcon = tlink_tcon(tlink);
1898 server = tcon->ses->server;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001899 }
1900
Pavel Shilovskyd1433412012-09-18 16:20:31 -07001901 /*
1902 * Set file size by pathname rather than by handle either because no
1903 * valid, writeable file handle for it was found or because there was
1904 * an error setting it by handle.
1905 */
1906 if (server->ops->set_path_size)
1907 rc = server->ops->set_path_size(xid, tcon, full_path,
1908 attrs->ia_size, cifs_sb, false);
1909 else
1910 rc = -ENOSYS;
1911 cFYI(1, "SetEOF by path (setattrs) rc = %d", rc);
1912 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1913 __u16 netfid;
1914 int oplock = 0;
1915
1916 rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
1917 GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
1918 &oplock, NULL, cifs_sb->local_nls,
1919 cifs_sb->mnt_cifs_flags &
1920 CIFS_MOUNT_MAP_SPECIAL_CHR);
1921 if (rc == 0) {
1922 unsigned int bytes_written;
1923
1924 io_parms.netfid = netfid;
1925 io_parms.pid = current->tgid;
1926 io_parms.tcon = tcon;
1927 io_parms.offset = 0;
1928 io_parms.length = attrs->ia_size;
1929 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
1930 NULL, 1);
1931 cFYI(1, "wrt seteof rc %d", rc);
1932 CIFSSMBClose(xid, tcon, netfid);
1933 }
1934 }
1935 if (tlink)
1936 cifs_put_tlink(tlink);
1937
1938set_size_out:
Jeff Layton8efdbde2008-07-23 21:28:12 +00001939 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001940 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04001941 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001942 cifs_truncate_page(inode->i_mapping, inode->i_size);
1943 }
1944
1945 return rc;
1946}
1947
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001948static int
1949cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1950{
1951 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001952 unsigned int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001953 char *full_path = NULL;
1954 struct inode *inode = direntry->d_inode;
1955 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1956 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001957 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001958 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001959 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04001960 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001961
Joe Perchesb6b38f72010-04-21 03:50:45 +00001962 cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x",
1963 direntry->d_name.name, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001964
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04001965 xid = get_xid();
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001966
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001967 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
1968 attrs->ia_valid |= ATTR_FORCE;
1969
1970 rc = inode_change_ok(inode, attrs);
1971 if (rc < 0)
1972 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001973
1974 full_path = build_path_from_dentry(direntry);
1975 if (full_path == NULL) {
1976 rc = -ENOMEM;
1977 goto out;
1978 }
1979
Jeff Layton0f4d6342009-03-26 13:35:37 -04001980 /*
1981 * Attempt to flush data before changing attributes. We need to do
1982 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1983 * ownership or mode then we may also need to do this. Here, we take
1984 * the safe way out and just do the flush on all setattr requests. If
1985 * the flush returns error, store it to report later and continue.
1986 *
1987 * BB: This should be smarter. Why bother flushing pages that
1988 * will be truncated anyway? Also, should we error out here if
1989 * the flush returns error?
1990 */
1991 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001992 mapping_set_error(inode->i_mapping, rc);
1993 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001994
1995 if (attrs->ia_valid & ATTR_SIZE) {
1996 rc = cifs_set_file_size(inode, attrs, xid, full_path);
1997 if (rc != 0)
1998 goto out;
1999 }
2000
2001 /* skip mode change if it's just for clearing setuid/setgid */
2002 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2003 attrs->ia_valid &= ~ATTR_MODE;
2004
2005 args = kmalloc(sizeof(*args), GFP_KERNEL);
2006 if (args == NULL) {
2007 rc = -ENOMEM;
2008 goto out;
2009 }
2010
2011 /* set up the struct */
2012 if (attrs->ia_valid & ATTR_MODE)
2013 args->mode = attrs->ia_mode;
2014 else
2015 args->mode = NO_CHANGE_64;
2016
2017 if (attrs->ia_valid & ATTR_UID)
2018 args->uid = attrs->ia_uid;
2019 else
2020 args->uid = NO_CHANGE_64;
2021
2022 if (attrs->ia_valid & ATTR_GID)
2023 args->gid = attrs->ia_gid;
2024 else
2025 args->gid = NO_CHANGE_64;
2026
2027 if (attrs->ia_valid & ATTR_ATIME)
2028 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2029 else
2030 args->atime = NO_CHANGE_64;
2031
2032 if (attrs->ia_valid & ATTR_MTIME)
2033 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2034 else
2035 args->mtime = NO_CHANGE_64;
2036
2037 if (attrs->ia_valid & ATTR_CTIME)
2038 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2039 else
2040 args->ctime = NO_CHANGE_64;
2041
2042 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002043 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002044 if (open_file) {
Pavel Shilovsky4b4de762012-09-18 16:20:26 -07002045 u16 nfid = open_file->fid.netfid;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002046 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002047 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002048 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002049 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002050 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002051 tlink = cifs_sb_tlink(cifs_sb);
2052 if (IS_ERR(tlink)) {
2053 rc = PTR_ERR(tlink);
2054 goto out;
2055 }
2056 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002057 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002058 cifs_sb->local_nls,
2059 cifs_sb->mnt_cifs_flags &
2060 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002061 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002062 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002063
Christoph Hellwig10257742010-06-04 11:30:02 +02002064 if (rc)
2065 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002066
Christoph Hellwig10257742010-06-04 11:30:02 +02002067 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002068 attrs->ia_size != i_size_read(inode))
2069 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002070
2071 setattr_copy(inode, attrs);
2072 mark_inode_dirty(inode);
2073
2074 /* force revalidate when any of these times are set since some
2075 of the fs types (eg ext3, fat) do not have fine enough
2076 time granularity to match protocol, and we do not have a
2077 a way (yet) to query the server fs's time granularity (and
2078 whether it rounds times down).
2079 */
2080 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2081 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002082out:
2083 kfree(args);
2084 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002085 free_xid(xid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002086 return rc;
2087}
2088
Jeff Layton0510eeb2008-08-02 07:26:12 -04002089static int
2090cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091{
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002092 unsigned int xid;
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002093 uid_t uid = NO_CHANGE_32;
2094 gid_t gid = NO_CHANGE_32;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002095 struct inode *inode = direntry->d_inode;
2096 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002097 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 char *full_path = NULL;
2099 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002100 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002101 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002102
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002103 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
Joe Perchesb6b38f72010-04-21 03:50:45 +00002105 cFYI(1, "setattr on file %s attrs->iavalid 0x%x",
2106 direntry->d_name.name, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002107
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002108 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2109 attrs->ia_valid |= ATTR_FORCE;
2110
2111 rc = inode_change_ok(inode, attrs);
2112 if (rc < 0) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002113 free_xid(xid);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002114 return rc;
Steve French6473a552005-11-29 20:20:10 -08002115 }
Steve French50c2f752007-07-13 00:33:32 +00002116
Steve French7f573562005-08-30 11:32:14 -07002117 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302119 rc = -ENOMEM;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002120 free_xid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302121 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
Jeff Layton0f4d6342009-03-26 13:35:37 -04002124 /*
2125 * Attempt to flush data before changing attributes. We need to do
2126 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2127 * ownership or mode then we may also need to do this. Here, we take
2128 * the safe way out and just do the flush on all setattr requests. If
2129 * the flush returns error, store it to report later and continue.
2130 *
2131 * BB: This should be smarter. Why bother flushing pages that
2132 * will be truncated anyway? Also, should we error out here if
2133 * the flush returns error?
2134 */
2135 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002136 mapping_set_error(inode->i_mapping, rc);
2137 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002138
Steve French50531442008-03-14 19:21:31 +00002139 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002140 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2141 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002142 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002144
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002145 if (attrs->ia_valid & ATTR_UID)
2146 uid = attrs->ia_uid;
2147
2148 if (attrs->ia_valid & ATTR_GID)
2149 gid = attrs->ia_gid;
2150
2151#ifdef CONFIG_CIFS_ACL
2152 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
2153 if (uid != NO_CHANGE_32 || gid != NO_CHANGE_32) {
2154 rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
2155 uid, gid);
2156 if (rc) {
2157 cFYI(1, "%s: Setting id failed with error: %d",
2158 __func__, rc);
2159 goto cifs_setattr_exit;
2160 }
2161 }
2162 } else
2163#endif /* CONFIG_CIFS_ACL */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002164 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002165 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
Jeff Laytond32c4f22007-10-18 03:05:22 -07002167 /* skip mode change if it's just for clearing setuid/setgid */
2168 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2169 attrs->ia_valid &= ~ATTR_MODE;
2170
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 if (attrs->ia_valid & ATTR_MODE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 mode = attrs->ia_mode;
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002173 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002174#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002175 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkara5ff3762011-10-13 10:26:03 -05002176 rc = id_mode_to_cifs_acl(inode, full_path, mode,
2177 NO_CHANGE_32, NO_CHANGE_32);
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002178 if (rc) {
2179 cFYI(1, "%s: Setting ACL failed with error: %d",
2180 __func__, rc);
2181 goto cifs_setattr_exit;
2182 }
2183 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002184#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002185 if (((mode & S_IWUGO) == 0) &&
2186 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002187
2188 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2189
Jeff Layton51328612008-05-22 09:33:34 -04002190 /* fix up mode if we're not using dynperm */
2191 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2192 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2193 } else if ((mode & S_IWUGO) &&
2194 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002195
2196 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2197 /* Attributes of 0 are ignored */
2198 if (dosattr == 0)
2199 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002200
2201 /* reset local inode permissions to normal */
2202 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2203 attrs->ia_mode &= ~(S_IALLUGO);
2204 if (S_ISDIR(inode->i_mode))
2205 attrs->ia_mode |=
2206 cifs_sb->mnt_dir_mode;
2207 else
2208 attrs->ia_mode |=
2209 cifs_sb->mnt_file_mode;
2210 }
2211 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2212 /* ignore mode change - ATTR_READONLY hasn't changed */
2213 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 }
2216
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002217 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2218 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2219 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2220 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
Steve Frenche30dcf32005-09-20 20:49:16 -07002222 /* Even if error on time set, no sense failing the call if
2223 the server would set the time to a reasonable value anyway,
2224 and this check ensures that we are not being called from
2225 sys_utimes in which case we ought to fail the call back to
2226 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002227 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002228 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002229 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 }
2231
2232 /* do not need local check to inode_check_ok since the server does
2233 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002234 if (rc)
2235 goto cifs_setattr_exit;
2236
2237 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002238 attrs->ia_size != i_size_read(inode))
2239 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002240
2241 setattr_copy(inode, attrs);
2242 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002243
Steve Frenche30dcf32005-09-20 20:49:16 -07002244cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 kfree(full_path);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002246 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 return rc;
2248}
2249
Jeff Layton0510eeb2008-08-02 07:26:12 -04002250int
2251cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2252{
2253 struct inode *inode = direntry->d_inode;
2254 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002255 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002256
2257 if (pTcon->unix_ext)
2258 return cifs_setattr_unix(direntry, attrs);
2259
2260 return cifs_setattr_nounix(direntry, attrs);
2261
2262 /* BB: add cifs_setattr_legacy for really old servers */
2263}
2264
Steve French99ee4db2007-02-27 05:35:17 +00002265#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266void cifs_delete_inode(struct inode *inode)
2267{
Joe Perchesb6b38f72010-04-21 03:50:45 +00002268 cFYI(1, "In cifs_delete_inode, inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 /* may have to add back in if and when safe distributed caching of
2270 directories added e.g. via FindNotify */
2271}
Steve French99ee4db2007-02-27 05:35:17 +00002272#endif