blob: a7b2dcd4a53ec1b5404729ea29e2e9ff79fabdeb [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);
127 unsigned long oldtime = cifs_i->time;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000128
Jeff Laytondf2cf172010-02-12 07:44:16 -0500129 cifs_revalidate_cache(inode, fattr);
130
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;
135 inode->i_nlink = fattr->cf_nlink;
136 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
Joe Perchesb6b38f72010-04-21 03:50:45 +0000151 cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode,
152 oldtime, cifs_i->time);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400153
154 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000155
Jeff Layton835a36c2010-02-10 16:21:33 -0500156 cifs_i->server_eof = fattr->cf_eof;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000157 /*
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400158 * Can't safely change the file size here if the client is writing to
159 * it due to potential races.
Christoph Hellwig75f12982008-02-25 20:25:21 +0000160 */
Christoph Hellwig75f12982008-02-25 20:25:21 +0000161 spin_lock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400162 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
163 i_size_write(inode, fattr->cf_eof);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000164
165 /*
166 * i_blocks is not related to (i_size / i_blksize),
167 * but instead 512 byte (2**9) size is required for
168 * calculating num blocks.
169 */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400170 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
Christoph Hellwig75f12982008-02-25 20:25:21 +0000171 }
172 spin_unlock(&inode->i_lock);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400173
David Howells01c64fe2011-01-14 18:45:47 +0000174 if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL)
175 inode->i_flags |= S_AUTOMOUNT;
176 cifs_set_ops(inode);
Christoph Hellwig75f12982008-02-25 20:25:21 +0000177}
178
Jeff Layton4065c802010-05-17 07:18:58 -0400179void
180cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
181{
182 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
183
184 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
185 return;
186
187 fattr->cf_uniqueid = iunique(sb, ROOT_I);
188}
189
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400190/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
191void
192cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
193 struct cifs_sb_info *cifs_sb)
194{
195 memset(fattr, 0, sizeof(*fattr));
196 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
197 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
198 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
199
200 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
201 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
202 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
203 fattr->cf_mode = le64_to_cpu(info->Permissions);
204
205 /*
206 * Since we set the inode type below we need to mask off
207 * to avoid strange results if bits set above.
208 */
209 fattr->cf_mode &= ~S_IFMT;
210 switch (le32_to_cpu(info->Type)) {
211 case UNIX_FILE:
212 fattr->cf_mode |= S_IFREG;
213 fattr->cf_dtype = DT_REG;
214 break;
215 case UNIX_SYMLINK:
216 fattr->cf_mode |= S_IFLNK;
217 fattr->cf_dtype = DT_LNK;
218 break;
219 case UNIX_DIR:
220 fattr->cf_mode |= S_IFDIR;
221 fattr->cf_dtype = DT_DIR;
222 break;
223 case UNIX_CHARDEV:
224 fattr->cf_mode |= S_IFCHR;
225 fattr->cf_dtype = DT_CHR;
226 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
227 le64_to_cpu(info->DevMinor) & MINORMASK);
228 break;
229 case UNIX_BLOCKDEV:
230 fattr->cf_mode |= S_IFBLK;
231 fattr->cf_dtype = DT_BLK;
232 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
233 le64_to_cpu(info->DevMinor) & MINORMASK);
234 break;
235 case UNIX_FIFO:
236 fattr->cf_mode |= S_IFIFO;
237 fattr->cf_dtype = DT_FIFO;
238 break;
239 case UNIX_SOCKET:
240 fattr->cf_mode |= S_IFSOCK;
241 fattr->cf_dtype = DT_SOCK;
242 break;
243 default:
244 /* safest to call it a file if we do not know */
245 fattr->cf_mode |= S_IFREG;
246 fattr->cf_dtype = DT_REG;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000247 cFYI(1, "unknown type %d", le32_to_cpu(info->Type));
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400248 break;
249 }
250
251 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
252 fattr->cf_uid = cifs_sb->mnt_uid;
253 else
254 fattr->cf_uid = le64_to_cpu(info->Uid);
255
256 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
257 fattr->cf_gid = cifs_sb->mnt_gid;
258 else
259 fattr->cf_gid = le64_to_cpu(info->Gid);
260
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
Jeff Laytonabab0952010-02-12 07:44:18 -0500289int cifs_get_file_info_unix(struct file *filp)
290{
291 int rc;
292 int xid;
293 FILE_UNIX_BASIC_INFO find_data;
294 struct cifs_fattr fattr;
295 struct inode *inode = filp->f_path.dentry->d_inode;
296 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700297 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000298 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500299
300 xid = GetXid();
301 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
302 if (!rc) {
303 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
304 } else if (rc == -EREMOTE) {
305 cifs_create_dfs_fattr(&fattr, inode->i_sb);
306 rc = 0;
307 }
308
309 cifs_fattr_to_inode(inode, &fattr);
310 FreeXid(xid);
311 return rc;
312}
313
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314int cifs_get_inode_info_unix(struct inode **pinode,
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400315 const unsigned char *full_path,
316 struct super_block *sb, int xid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317{
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400318 int rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000319 FILE_UNIX_BASIC_INFO find_data;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400320 struct cifs_fattr fattr;
Steve French96daf2b2011-05-27 04:34:02 +0000321 struct cifs_tcon *tcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400322 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
Joe Perchesb6b38f72010-04-21 03:50:45 +0000325 cFYI(1, "Getting info on %s", full_path);
Igor Mammedov79626702008-03-09 03:44:18 +0000326
Jeff Layton7ffec372010-09-29 19:51:11 -0400327 tlink = cifs_sb_tlink(cifs_sb);
328 if (IS_ERR(tlink))
329 return PTR_ERR(tlink);
330 tcon = tlink_tcon(tlink);
331
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 /* could have done a find first instead but this returns more info */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400333 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
Steve French737b7582005-04-28 22:41:06 -0700334 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
335 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400336 cifs_put_tlink(tlink);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400337
338 if (!rc) {
339 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
340 } else if (rc == -EREMOTE) {
341 cifs_create_dfs_fattr(&fattr, sb);
Jeff Laytone911d0c2008-07-12 13:47:59 -0700342 rc = 0;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400343 } else {
344 return rc;
Steve French0e4bbde2008-05-20 19:50:46 +0000345 }
346
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200347 /* check for Minshall+French symlinks */
348 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
349 int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
350 if (tmprc)
351 cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
352 }
353
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400354 if (*pinode == NULL) {
355 /* get new inode */
Jeff Layton4065c802010-05-17 07:18:58 -0400356 cifs_fill_uniqueid(sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400357 *pinode = cifs_iget(sb, &fattr);
358 if (!*pinode)
359 rc = -ENOMEM;
360 } else {
361 /* we already have inode, update it */
362 cifs_fattr_to_inode(*pinode, &fattr);
363 }
Steve French0e4bbde2008-05-20 19:50:46 +0000364
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 return rc;
366}
367
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400368static int
369cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
370 struct cifs_sb_info *cifs_sb, int xid)
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800371{
372 int rc;
Steve French4b18f2a2008-04-29 00:06:05 +0000373 int oplock = 0;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800374 __u16 netfid;
Jeff Layton7ffec372010-09-29 19:51:11 -0400375 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000376 struct cifs_tcon *tcon;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000377 struct cifs_io_parms io_parms;
Steve French86c96b42005-11-18 20:25:31 -0800378 char buf[24];
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800379 unsigned int bytes_read;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000380 char *pbuf;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800381
382 pbuf = buf;
383
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400384 fattr->cf_mode &= ~S_IFMT;
385
386 if (fattr->cf_eof == 0) {
387 fattr->cf_mode |= S_IFIFO;
388 fattr->cf_dtype = DT_FIFO;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800389 return 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400390 } else if (fattr->cf_eof < 8) {
391 fattr->cf_mode |= S_IFREG;
392 fattr->cf_dtype = DT_REG;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800393 return -EINVAL; /* EOPNOTSUPP? */
394 }
Steve French50c2f752007-07-13 00:33:32 +0000395
Jeff Layton7ffec372010-09-29 19:51:11 -0400396 tlink = cifs_sb_tlink(cifs_sb);
397 if (IS_ERR(tlink))
398 return PTR_ERR(tlink);
399 tcon = tlink_tcon(tlink);
400
401 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800402 CREATE_NOT_DIR, &netfid, &oplock, NULL,
403 cifs_sb->local_nls,
404 cifs_sb->mnt_cifs_flags &
405 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000406 if (rc == 0) {
Steve Frenchec637e32005-12-12 20:53:18 -0800407 int buf_type = CIFS_NO_BUFFER;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800408 /* Read header */
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000409 io_parms.netfid = netfid;
410 io_parms.pid = current->tgid;
411 io_parms.tcon = tcon;
412 io_parms.offset = 0;
413 io_parms.length = 24;
414 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf,
415 &buf_type);
Steve French4523cc32007-04-30 20:13:06 +0000416 if ((rc == 0) && (bytes_read >= 8)) {
417 if (memcmp("IntxBLK", pbuf, 8) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000418 cFYI(1, "Block device");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400419 fattr->cf_mode |= S_IFBLK;
420 fattr->cf_dtype = DT_BLK;
Steve French4523cc32007-04-30 20:13:06 +0000421 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800422 /* we have enough to decode dev num */
423 __u64 mjr; /* major */
424 __u64 mnr; /* minor */
425 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
426 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400427 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve French86c96b42005-11-18 20:25:31 -0800428 }
Steve French4523cc32007-04-30 20:13:06 +0000429 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000430 cFYI(1, "Char device");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400431 fattr->cf_mode |= S_IFCHR;
432 fattr->cf_dtype = DT_CHR;
Steve French4523cc32007-04-30 20:13:06 +0000433 if (bytes_read == 24) {
Steve French86c96b42005-11-18 20:25:31 -0800434 /* we have enough to decode dev num */
435 __u64 mjr; /* major */
436 __u64 mnr; /* minor */
437 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
438 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400439 fattr->cf_rdev = MKDEV(mjr, mnr);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000440 }
Steve French4523cc32007-04-30 20:13:06 +0000441 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000442 cFYI(1, "Symlink");
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400443 fattr->cf_mode |= S_IFLNK;
444 fattr->cf_dtype = DT_LNK;
Steve French86c96b42005-11-18 20:25:31 -0800445 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400446 fattr->cf_mode |= S_IFREG; /* file? */
447 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000448 rc = -EOPNOTSUPP;
Steve French86c96b42005-11-18 20:25:31 -0800449 }
Steve French3020a1f2005-11-18 11:31:10 -0800450 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400451 fattr->cf_mode |= S_IFREG; /* then it is a file */
452 fattr->cf_dtype = DT_REG;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000453 rc = -EOPNOTSUPP; /* or some unknown SFU type */
454 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400455 CIFSSMBClose(xid, tcon, netfid);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800456 }
Jeff Layton7ffec372010-09-29 19:51:11 -0400457 cifs_put_tlink(tlink);
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800458 return rc;
Steve Frenchd6e2f2a42005-11-15 16:43:39 -0800459}
460
Steve French9e294f12005-11-17 16:59:21 -0800461#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
462
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400463/*
464 * Fetch mode bits as provided by SFU.
465 *
466 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
467 */
468static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
469 struct cifs_sb_info *cifs_sb, int xid)
Steve French9e294f12005-11-17 16:59:21 -0800470{
Steve French3020a1f2005-11-18 11:31:10 -0800471#ifdef CONFIG_CIFS_XATTR
Steve French9e294f12005-11-17 16:59:21 -0800472 ssize_t rc;
473 char ea_value[4];
474 __u32 mode;
Jeff Layton7ffec372010-09-29 19:51:11 -0400475 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +0000476 struct cifs_tcon *tcon;
Steve French9e294f12005-11-17 16:59:21 -0800477
Jeff Layton7ffec372010-09-29 19:51:11 -0400478 tlink = cifs_sb_tlink(cifs_sb);
479 if (IS_ERR(tlink))
480 return PTR_ERR(tlink);
481 tcon = tlink_tcon(tlink);
482
483 rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400484 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
485 cifs_sb->mnt_cifs_flags &
486 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -0400487 cifs_put_tlink(tlink);
Steve French4523cc32007-04-30 20:13:06 +0000488 if (rc < 0)
Steve French9e294f12005-11-17 16:59:21 -0800489 return (int)rc;
490 else if (rc > 3) {
491 mode = le32_to_cpu(*((__le32 *)ea_value));
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400492 fattr->cf_mode &= ~SFBITS_MASK;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000493 cFYI(1, "special bits 0%o org mode 0%o", mode,
494 fattr->cf_mode);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400495 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000496 cFYI(1, "special mode bits 0%o", mode);
Steve French9e294f12005-11-17 16:59:21 -0800497 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400498
499 return 0;
Steve French3020a1f2005-11-18 11:31:10 -0800500#else
501 return -EOPNOTSUPP;
502#endif
Steve French9e294f12005-11-17 16:59:21 -0800503}
504
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400505/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
Steve Frenchf1230c92009-07-22 23:13:01 +0000506static void
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400507cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
508 struct cifs_sb_info *cifs_sb, bool adjust_tz)
Steve Frenchb9a32602008-05-20 21:52:32 +0000509{
Steve French96daf2b2011-05-27 04:34:02 +0000510 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700511
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400512 memset(fattr, 0, sizeof(*fattr));
513 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
514 if (info->DeletePending)
515 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
Steve Frenchb9a32602008-05-20 21:52:32 +0000516
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400517 if (info->LastAccessTime)
518 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
519 else
520 fattr->cf_atime = CURRENT_TIME;
521
522 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
523 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
524
525 if (adjust_tz) {
Jeff Layton0d424ad2010-09-20 16:01:35 -0700526 fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
527 fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400528 }
529
530 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
531 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
Jeff Layton20054bd2011-01-07 11:30:27 -0500532 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400533
534 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
535 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
536 fattr->cf_dtype = DT_DIR;
537 } else {
538 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
539 fattr->cf_dtype = DT_REG;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400540
Jeff Laytond0c280d2009-07-09 01:46:44 -0400541 /* clear write bits if ATTR_READONLY is set */
542 if (fattr->cf_cifsattrs & ATTR_READONLY)
543 fattr->cf_mode &= ~(S_IWUGO);
544 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400545
546 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
547
548 fattr->cf_uid = cifs_sb->mnt_uid;
549 fattr->cf_gid = cifs_sb->mnt_gid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000550}
551
Jeff Laytonabab0952010-02-12 07:44:18 -0500552int cifs_get_file_info(struct file *filp)
553{
554 int rc;
555 int xid;
556 FILE_ALL_INFO find_data;
557 struct cifs_fattr fattr;
558 struct inode *inode = filp->f_path.dentry->d_inode;
559 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Joe Perchesc21dfb62010-07-12 13:50:14 -0700560 struct cifsFileInfo *cfile = filp->private_data;
Steve French96daf2b2011-05-27 04:34:02 +0000561 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
Jeff Laytonabab0952010-02-12 07:44:18 -0500562
563 xid = GetXid();
564 rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
565 if (rc == -EOPNOTSUPP || rc == -EINVAL) {
566 /*
567 * FIXME: legacy server -- fall back to path-based call?
Steve Frenchff2157132010-03-09 20:30:42 +0000568 * for now, just skip revalidating and mark inode for
569 * immediate reval.
570 */
Jeff Laytonabab0952010-02-12 07:44:18 -0500571 rc = 0;
572 CIFS_I(inode)->time = 0;
573 goto cgfi_exit;
574 } else if (rc == -EREMOTE) {
575 cifs_create_dfs_fattr(&fattr, inode->i_sb);
576 rc = 0;
577 } else if (rc)
578 goto cgfi_exit;
579
580 /*
581 * don't bother with SFU junk here -- just mark inode as needing
582 * revalidation.
583 */
584 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
585 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
586 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
587 cifs_fattr_to_inode(inode, &fattr);
588cgfi_exit:
589 FreeXid(xid);
590 return rc;
591}
592
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593int cifs_get_inode_info(struct inode **pinode,
Steve French646dd532008-05-15 01:50:56 +0000594 const unsigned char *full_path, FILE_ALL_INFO *pfindData,
Steve French8b1327f2008-03-14 22:37:16 +0000595 struct super_block *sb, int xid, const __u16 *pfid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596{
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400597 int rc = 0, tmprc;
Steve French96daf2b2011-05-27 04:34:02 +0000598 struct cifs_tcon *pTcon;
Jeff Layton7ffec372010-09-29 19:51:11 -0400599 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 char *buf = NULL;
Steve French5ade9de2008-05-02 20:56:23 +0000602 bool adjustTZ = false;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400603 struct cifs_fattr fattr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604
Jeff Layton7ffec372010-09-29 19:51:11 -0400605 tlink = cifs_sb_tlink(cifs_sb);
606 if (IS_ERR(tlink))
607 return PTR_ERR(tlink);
608 pTcon = tlink_tcon(tlink);
609
Joe Perchesb6b38f72010-04-21 03:50:45 +0000610 cFYI(1, "Getting info on %s", full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Steve Frenchd0d2f2d2005-06-02 15:12:36 -0700612 if ((pfindData == NULL) && (*pinode != NULL)) {
613 if (CIFS_I(*pinode)->clientCanCacheRead) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000614 cFYI(1, "No need to revalidate cached inode sizes");
Jeff Layton7ffec372010-09-29 19:51:11 -0400615 goto cgii_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 }
617 }
618
619 /* if file info not passed in then get it from server */
Steve Frenchd0d2f2d2005-06-02 15:12:36 -0700620 if (pfindData == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Jeff Layton7ffec372010-09-29 19:51:11 -0400622 if (buf == NULL) {
623 rc = -ENOMEM;
624 goto cgii_exit;
625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 pfindData = (FILE_ALL_INFO *)buf;
Igor Mammedov79626702008-03-09 03:44:18 +0000627
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 /* could do find first instead but this returns more info */
Igor Mammedov79626702008-03-09 03:44:18 +0000629 rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
Steve Frenchacf1a1b2006-10-12 03:28:28 +0000630 0 /* not legacy */,
Steve French6b8edfe2005-08-23 20:26:03 -0700631 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700632 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French6b8edfe2005-08-23 20:26:03 -0700633 /* BB optimize code so we do not make the above call
634 when server claims no NT SMB support and the above call
635 failed at least once - set flag in tcon or mount */
Steve French4523cc32007-04-30 20:13:06 +0000636 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
Igor Mammedov79626702008-03-09 03:44:18 +0000637 rc = SMBQueryInformation(xid, pTcon, full_path,
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000638 pfindData, cifs_sb->local_nls,
Steve French6b8edfe2005-08-23 20:26:03 -0700639 cifs_sb->mnt_cifs_flags &
640 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French4b18f2a2008-04-29 00:06:05 +0000641 adjustTZ = true;
Steve French6b8edfe2005-08-23 20:26:03 -0700642 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 }
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400644
645 if (!rc) {
646 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData,
647 cifs_sb, adjustTZ);
648 } else if (rc == -EREMOTE) {
649 cifs_create_dfs_fattr(&fattr, sb);
Steve Frenchb9a32602008-05-20 21:52:32 +0000650 rc = 0;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400651 } else {
Igor Mammedov79626702008-03-09 03:44:18 +0000652 goto cgii_exit;
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400653 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400655 /*
656 * If an inode wasn't passed in, then get the inode number
657 *
658 * Is an i_ino of zero legal? Can we use that to check if the server
659 * supports returning inode numbers? Are there other sanity checks we
660 * can use to ensure that the server is really filling in that field?
661 *
662 * We can not use the IndexNumber field by default from Windows or
663 * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
664 * CIFS spec claims that this value is unique within the scope of a
665 * share, and the windows docs hint that it's actually unique
666 * per-machine.
667 *
668 * There may be higher info levels that work but are there Windows
669 * server or network appliances for which IndexNumber field is not
670 * guaranteed unique?
671 */
Steve Frenchb9a32602008-05-20 21:52:32 +0000672 if (*pinode == NULL) {
Steve Frenchb9a32602008-05-20 21:52:32 +0000673 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
674 int rc1 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
Steve Frenchb9a32602008-05-20 21:52:32 +0000676 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400677 full_path, &fattr.cf_uniqueid,
Steve French737b7582005-04-28 22:41:06 -0700678 cifs_sb->local_nls,
679 cifs_sb->mnt_cifs_flags &
680 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Laytonec06aed2009-11-06 14:18:29 -0500681 if (rc1 || !fattr.cf_uniqueid) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000682 cFYI(1, "GetSrvInodeNum rc %d", rc1);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400683 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Jeff Laytonec06aed2009-11-06 14:18:29 -0500684 cifs_autodisable_serverino(cifs_sb);
Jeff Layton132ac7b2009-02-10 07:33:57 -0500685 }
Jeff Layton132ac7b2009-02-10 07:33:57 -0500686 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400687 fattr.cf_uniqueid = iunique(sb, ROOT_I);
Jeff Layton132ac7b2009-02-10 07:33:57 -0500688 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000689 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400690 fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid;
Steve Frenchb9a32602008-05-20 21:52:32 +0000691 }
692
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400693 /* query for SFU type info if supported and needed */
694 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
695 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
696 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
697 if (tmprc)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000698 cFYI(1, "cifs_sfu_type failed: %d", tmprc);
Steve Frenchb9a32602008-05-20 21:52:32 +0000699 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000700
Jeff Layton79df1ba2010-12-06 12:52:08 -0500701#ifdef CONFIG_CIFS_ACL
Steve Frenchb9a32602008-05-20 21:52:32 +0000702 /* fill in 0777 bits from ACL */
703 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600704 rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path,
705 pfid);
706 if (rc) {
707 cFYI(1, "%s: Getting ACL failed with error: %d",
708 __func__, rc);
709 goto cgii_exit;
710 }
Steve Frenchb9a32602008-05-20 21:52:32 +0000711 }
Jeff Layton79df1ba2010-12-06 12:52:08 -0500712#endif /* CONFIG_CIFS_ACL */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400713
714 /* fill in remaining high mode bits e.g. SUID, VTX */
715 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
716 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
717
Stefan Metzmacher1b12b9c2010-08-05 21:19:56 +0200718 /* check for Minshall+French symlinks */
719 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
720 tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
721 if (tmprc)
722 cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
723 }
724
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400725 if (!*pinode) {
726 *pinode = cifs_iget(sb, &fattr);
727 if (!*pinode)
728 rc = -ENOMEM;
729 } else {
730 cifs_fattr_to_inode(*pinode, &fattr);
Steve Frenchb9a32602008-05-20 21:52:32 +0000731 }
732
Igor Mammedov79626702008-03-09 03:44:18 +0000733cgii_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 kfree(buf);
Jeff Layton7ffec372010-09-29 19:51:11 -0400735 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 return rc;
737}
738
Steve French7f8ed422007-09-28 22:28:55 +0000739static const struct inode_operations cifs_ipc_inode_ops = {
740 .lookup = cifs_lookup,
741};
742
Steve Frenchf87d39d2011-05-27 03:50:55 +0000743char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
Steve French96daf2b2011-05-27 04:34:02 +0000744 struct cifs_tcon *tcon)
Steve French8be0ed42008-12-05 19:14:12 +0000745{
Steve Frenchf87d39d2011-05-27 03:50:55 +0000746 int pplen = vol->prepath ? strlen(vol->prepath) : 0;
Steve French8be0ed42008-12-05 19:14:12 +0000747 int dfsplen;
748 char *full_path = NULL;
749
750 /* if no prefix path, simply set path to the root of share to "" */
751 if (pplen == 0) {
752 full_path = kmalloc(1, GFP_KERNEL);
753 if (full_path)
754 full_path[0] = 0;
755 return full_path;
756 }
757
Jeff Layton0d424ad2010-09-20 16:01:35 -0700758 if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
759 dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
Steve French8be0ed42008-12-05 19:14:12 +0000760 else
761 dfsplen = 0;
762
763 full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
764 if (full_path == NULL)
765 return full_path;
766
Jeff Laytonf9e8c452011-08-05 10:28:01 -0400767 if (dfsplen)
Jeff Layton0d424ad2010-09-20 16:01:35 -0700768 strncpy(full_path, tcon->treeName, dfsplen);
Steve Frenchf87d39d2011-05-27 03:50:55 +0000769 strncpy(full_path + dfsplen, vol->prepath, pplen);
Jeff Laytonf9e8c452011-08-05 10:28:01 -0400770 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Steve French8be0ed42008-12-05 19:14:12 +0000771 full_path[dfsplen + pplen] = 0; /* add trailing null */
772 return full_path;
773}
774
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400775static int
776cifs_find_inode(struct inode *inode, void *opaque)
777{
778 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
779
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400780 /* don't match inode with different uniqueid */
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400781 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
782 return 0;
783
Jeff Layton20054bd2011-01-07 11:30:27 -0500784 /* use createtime like an i_generation field */
785 if (CIFS_I(inode)->createtime != fattr->cf_createtime)
786 return 0;
787
Jeff Laytonf30b9c12010-07-19 18:00:17 -0400788 /* don't match inode of different type */
789 if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
790 return 0;
791
Jeff Layton5acfec22010-08-02 17:43:54 -0400792 /* if it's not a directory or has no dentries, then flag it */
793 if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry))
Jeff Layton3d694382010-05-11 14:59:55 -0400794 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
Jeff Layton3d694382010-05-11 14:59:55 -0400795
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400796 return 1;
797}
798
799static int
800cifs_init_inode(struct inode *inode, void *opaque)
801{
802 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
803
804 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
Jeff Layton20054bd2011-01-07 11:30:27 -0500805 CIFS_I(inode)->createtime = fattr->cf_createtime;
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400806 return 0;
807}
808
Jeff Layton5acfec22010-08-02 17:43:54 -0400809/*
810 * walk dentry list for an inode and report whether it has aliases that
811 * are hashed. We use this to determine if a directory inode can actually
812 * be used.
813 */
814static bool
815inode_has_hashed_dentries(struct inode *inode)
816{
817 struct dentry *dentry;
818
Nick Piggin873feea2011-01-07 17:50:06 +1100819 spin_lock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400820 list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
821 if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
Nick Piggin873feea2011-01-07 17:50:06 +1100822 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400823 return true;
824 }
825 }
Nick Piggin873feea2011-01-07 17:50:06 +1100826 spin_unlock(&inode->i_lock);
Jeff Layton5acfec22010-08-02 17:43:54 -0400827 return false;
828}
829
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400830/* Given fattrs, get a corresponding inode */
831struct inode *
832cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
833{
834 unsigned long hash;
835 struct inode *inode;
836
Jeff Layton3d694382010-05-11 14:59:55 -0400837retry_iget5_locked:
Joe Perchesb6b38f72010-04-21 03:50:45 +0000838 cFYI(1, "looking for uniqueid=%llu", fattr->cf_uniqueid);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400839
840 /* hash down to 32-bits on 32-bit arch */
841 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
842
843 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400844 if (inode) {
Jeff Layton5acfec22010-08-02 17:43:54 -0400845 /* was there a potentially problematic inode collision? */
Jeff Layton3d694382010-05-11 14:59:55 -0400846 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
Jeff Layton3d694382010-05-11 14:59:55 -0400847 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
Jeff Layton5acfec22010-08-02 17:43:54 -0400848
849 if (inode_has_hashed_dentries(inode)) {
850 cifs_autodisable_serverino(CIFS_SB(sb));
851 iput(inode);
852 fattr->cf_uniqueid = iunique(sb, ROOT_I);
853 goto retry_iget5_locked;
854 }
Jeff Layton3d694382010-05-11 14:59:55 -0400855 }
856
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400857 cifs_fattr_to_inode(inode, fattr);
858 if (sb->s_flags & MS_NOATIME)
859 inode->i_flags |= S_NOATIME | S_NOCMTIME;
860 if (inode->i_state & I_NEW) {
861 inode->i_ino = hash;
Jeff Layton522440e2010-09-29 09:49:54 -0400862 if (S_ISREG(inode->i_mode))
863 inode->i_data.backing_dev_info = sb->s_bdi;
Steve French0ccd4802010-07-16 04:31:02 +0000864#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530865 /* initialize per-inode cache cookie pointer */
866 CIFS_I(inode)->fscache = NULL;
Steve French0ccd4802010-07-16 04:31:02 +0000867#endif
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400868 unlock_new_inode(inode);
869 }
870 }
871
872 return inode;
873}
874
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875/* gets root inode */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600876struct inode *cifs_root_iget(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877{
David Howellsce634ab2008-02-07 00:15:33 -0800878 int xid;
Jeff Layton0d424ad2010-09-20 16:01:35 -0700879 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400880 struct inode *inode = NULL;
David Howellsce634ab2008-02-07 00:15:33 -0800881 long rc;
Steve French96daf2b2011-05-27 04:34:02 +0000882 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
David Howellsce634ab2008-02-07 00:15:33 -0800883
Steve French8be0ed42008-12-05 19:14:12 +0000884 xid = GetXid();
Jeff Layton0d424ad2010-09-20 16:01:35 -0700885 if (tcon->unix_ext)
Steve Frenchf87d39d2011-05-27 03:50:55 +0000886 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400887 else
Steve Frenchf87d39d2011-05-27 03:50:55 +0000888 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400889
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000890 if (!inode) {
891 inode = ERR_PTR(rc);
892 goto out;
893 }
Jeff Laytoncc0bad72009-06-25 00:56:52 -0400894
Steve French0ccd4802010-07-16 04:31:02 +0000895#ifdef CONFIG_CIFS_FSCACHE
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530896 /* populate tcon->resource_id */
Jeff Layton0d424ad2010-09-20 16:01:35 -0700897 tcon->resource_id = CIFS_I(inode)->uniqueid;
Steve French0ccd4802010-07-16 04:31:02 +0000898#endif
Suresh Jayaramand03382c2010-07-05 18:12:27 +0530899
Jeff Layton0d424ad2010-09-20 16:01:35 -0700900 if (rc && tcon->ipc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000901 cFYI(1, "ipc connection - fake read inode");
Steve French7f8ed422007-09-28 22:28:55 +0000902 inode->i_mode |= S_IFDIR;
903 inode->i_nlink = 2;
904 inode->i_op = &cifs_ipc_inode_ops;
905 inode->i_fop = &simple_dir_operations;
906 inode->i_uid = cifs_sb->mnt_uid;
907 inode->i_gid = cifs_sb->mnt_gid;
Steve Frenchad661332008-08-12 14:14:40 +0000908 } else if (rc) {
David Howellsce634ab2008-02-07 00:15:33 -0800909 iget_failed(inode);
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000910 inode = ERR_PTR(rc);
Steve French7f8ed422007-09-28 22:28:55 +0000911 }
912
Oskar Schirmera7851ce2010-11-10 21:06:13 +0000913out:
David Howellsce634ab2008-02-07 00:15:33 -0800914 /* can not call macro FreeXid here since in a void func
915 * TODO: This is no longer true
916 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 _FreeXid(xid);
David Howellsce634ab2008-02-07 00:15:33 -0800918 return inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919}
920
Steve French388e57b2008-09-16 23:50:58 +0000921static int
922cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
923 char *full_path, __u32 dosattr)
924{
925 int rc;
926 int oplock = 0;
927 __u16 netfid;
928 __u32 netpid;
929 bool set_time = false;
930 struct cifsFileInfo *open_file;
931 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
932 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400933 struct tcon_link *tlink = NULL;
Steve French96daf2b2011-05-27 04:34:02 +0000934 struct cifs_tcon *pTcon;
Steve French388e57b2008-09-16 23:50:58 +0000935 FILE_BASIC_INFO info_buf;
936
Steve French1adcb712009-02-25 14:19:56 +0000937 if (attrs == NULL)
938 return -EINVAL;
939
Steve French388e57b2008-09-16 23:50:58 +0000940 if (attrs->ia_valid & ATTR_ATIME) {
941 set_time = true;
942 info_buf.LastAccessTime =
943 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
944 } else
945 info_buf.LastAccessTime = 0;
946
947 if (attrs->ia_valid & ATTR_MTIME) {
948 set_time = true;
949 info_buf.LastWriteTime =
950 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
951 } else
952 info_buf.LastWriteTime = 0;
953
954 /*
955 * Samba throws this field away, but windows may actually use it.
956 * Do not set ctime unless other time stamps are changed explicitly
957 * (i.e. by utimes()) since we would then have a mix of client and
958 * server times.
959 */
960 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000961 cFYI(1, "CIFS - CTIME changed");
Steve French388e57b2008-09-16 23:50:58 +0000962 info_buf.ChangeTime =
963 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
964 } else
965 info_buf.ChangeTime = 0;
966
967 info_buf.CreationTime = 0; /* don't change */
968 info_buf.Attributes = cpu_to_le32(dosattr);
969
970 /*
971 * If the file is already open for write, just use that fileid
972 */
Jeff Layton6508d902010-09-29 19:51:11 -0400973 open_file = find_writable_file(cifsInode, true);
Steve French388e57b2008-09-16 23:50:58 +0000974 if (open_file) {
975 netfid = open_file->netfid;
976 netpid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -0400977 pTcon = tlink_tcon(open_file->tlink);
Steve French388e57b2008-09-16 23:50:58 +0000978 goto set_via_filehandle;
979 }
980
Jeff Layton7ffec372010-09-29 19:51:11 -0400981 tlink = cifs_sb_tlink(cifs_sb);
982 if (IS_ERR(tlink)) {
983 rc = PTR_ERR(tlink);
984 tlink = NULL;
985 goto out;
986 }
987 pTcon = tlink_tcon(tlink);
Jeff Laytonba00ba62010-09-20 16:01:31 -0700988
Steve French388e57b2008-09-16 23:50:58 +0000989 /*
990 * NT4 apparently returns success on this call, but it doesn't
991 * really work.
992 */
993 if (!(pTcon->ses->flags & CIFS_SES_NT4)) {
994 rc = CIFSSMBSetPathInfo(xid, pTcon, full_path,
995 &info_buf, cifs_sb->local_nls,
996 cifs_sb->mnt_cifs_flags &
997 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton6b37faa2008-10-06 21:54:41 +0000998 if (rc == 0) {
999 cifsInode->cifsAttrs = dosattr;
1000 goto out;
1001 } else if (rc != -EOPNOTSUPP && rc != -EINVAL)
Steve French388e57b2008-09-16 23:50:58 +00001002 goto out;
1003 }
1004
Joe Perchesb6b38f72010-04-21 03:50:45 +00001005 cFYI(1, "calling SetFileInfo since SetPathInfo for "
1006 "times not supported by this server");
Steve French388e57b2008-09-16 23:50:58 +00001007 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1008 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1009 CREATE_NOT_DIR, &netfid, &oplock,
1010 NULL, cifs_sb->local_nls,
1011 cifs_sb->mnt_cifs_flags &
1012 CIFS_MOUNT_MAP_SPECIAL_CHR);
1013
1014 if (rc != 0) {
1015 if (rc == -EIO)
1016 rc = -EINVAL;
1017 goto out;
1018 }
1019
1020 netpid = current->tgid;
1021
1022set_via_filehandle:
1023 rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid);
Steve Frenchd3889082008-09-24 19:22:52 +00001024 if (!rc)
1025 cifsInode->cifsAttrs = dosattr;
1026
Steve French388e57b2008-09-16 23:50:58 +00001027 if (open_file == NULL)
1028 CIFSSMBClose(xid, pTcon, netfid);
1029 else
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001030 cifsFileInfo_put(open_file);
Steve French388e57b2008-09-16 23:50:58 +00001031out:
Jeff Layton7ffec372010-09-29 19:51:11 -04001032 if (tlink != NULL)
1033 cifs_put_tlink(tlink);
Steve French388e57b2008-09-16 23:50:58 +00001034 return rc;
1035}
1036
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001037/*
1038 * open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
1039 * and rename it to a random name that hopefully won't conflict with
1040 * anything else.
1041 */
1042static int
Steve French32709582008-10-20 00:44:19 +00001043cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001044{
1045 int oplock = 0;
1046 int rc;
1047 __u16 netfid;
Steve French32709582008-10-20 00:44:19 +00001048 struct inode *inode = dentry->d_inode;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001049 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1050 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001051 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001052 struct cifs_tcon *tcon;
Steve French32709582008-10-20 00:44:19 +00001053 __u32 dosattr, origattr;
1054 FILE_BASIC_INFO *info_buf = NULL;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001055
Jeff Layton7ffec372010-09-29 19:51:11 -04001056 tlink = cifs_sb_tlink(cifs_sb);
1057 if (IS_ERR(tlink))
1058 return PTR_ERR(tlink);
1059 tcon = tlink_tcon(tlink);
1060
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001061 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001062 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001063 &netfid, &oplock, NULL, cifs_sb->local_nls,
1064 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1065 if (rc != 0)
1066 goto out;
1067
Steve French32709582008-10-20 00:44:19 +00001068 origattr = cifsInode->cifsAttrs;
1069 if (origattr == 0)
1070 origattr |= ATTR_NORMAL;
1071
1072 dosattr = origattr & ~ATTR_READONLY;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001073 if (dosattr == 0)
1074 dosattr |= ATTR_NORMAL;
1075 dosattr |= ATTR_HIDDEN;
1076
Steve French32709582008-10-20 00:44:19 +00001077 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
1078 if (dosattr != origattr) {
1079 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
1080 if (info_buf == NULL) {
1081 rc = -ENOMEM;
1082 goto out_close;
1083 }
1084 info_buf->Attributes = cpu_to_le32(dosattr);
1085 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1086 current->tgid);
1087 /* although we would like to mark the file hidden
1088 if that fails we will still try to rename it */
Steve French41346092008-10-20 18:24:42 +00001089 if (rc != 0)
Steve French32709582008-10-20 00:44:19 +00001090 cifsInode->cifsAttrs = dosattr;
1091 else
1092 dosattr = origattr; /* since not able to change them */
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001093 }
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001094
Jeff Laytondd1db2d2008-10-16 19:27:12 -04001095 /* rename the file */
1096 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001097 cifs_sb->mnt_cifs_flags &
1098 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French32709582008-10-20 00:44:19 +00001099 if (rc != 0) {
1100 rc = -ETXTBSY;
1101 goto undo_setattr;
1102 }
Jeff Layton6d22f092008-09-23 11:48:35 -04001103
Steve French32709582008-10-20 00:44:19 +00001104 /* try to set DELETE_ON_CLOSE */
1105 if (!cifsInode->delete_pending) {
1106 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
1107 current->tgid);
1108 /*
1109 * some samba versions return -ENOENT when we try to set the
1110 * file disposition here. Likely a samba bug, but work around
1111 * it for now. This means that some cifsXXX files may hang
1112 * around after they shouldn't.
1113 *
1114 * BB: remove this hack after more servers have the fix
1115 */
1116 if (rc == -ENOENT)
1117 rc = 0;
1118 else if (rc != 0) {
1119 rc = -ETXTBSY;
1120 goto undo_rename;
1121 }
1122 cifsInode->delete_pending = true;
1123 }
Jeff Layton7ce86d52008-09-24 11:32:59 -04001124
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001125out_close:
1126 CIFSSMBClose(xid, tcon, netfid);
1127out:
Steve French32709582008-10-20 00:44:19 +00001128 kfree(info_buf);
Jeff Layton7ffec372010-09-29 19:51:11 -04001129 cifs_put_tlink(tlink);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001130 return rc;
Steve French32709582008-10-20 00:44:19 +00001131
1132 /*
1133 * reset everything back to the original state. Don't bother
1134 * dealing with errors here since we can't do anything about
1135 * them anyway.
1136 */
1137undo_rename:
1138 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
1139 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1140 CIFS_MOUNT_MAP_SPECIAL_CHR);
1141undo_setattr:
1142 if (dosattr != origattr) {
1143 info_buf->Attributes = cpu_to_le32(origattr);
1144 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1145 current->tgid))
1146 cifsInode->cifsAttrs = origattr;
1147 }
1148
1149 goto out_close;
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001150}
1151
Steve Frenchff694522009-04-20 19:45:13 +00001152
1153/*
1154 * If dentry->d_inode is null (usually meaning the cached dentry
1155 * is a negative dentry) then we would attempt a standard SMB delete, but
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001156 * if that fails we can not attempt the fall back mechanisms on EACCESS
1157 * but will return the EACCESS to the caller. Note that the VFS does not call
Steve Frenchff694522009-04-20 19:45:13 +00001158 * unlink on negative dentries currently.
1159 */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001160int cifs_unlink(struct inode *dir, struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161{
1162 int rc = 0;
1163 int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 char *full_path = NULL;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001165 struct inode *inode = dentry->d_inode;
Steve Frenchff694522009-04-20 19:45:13 +00001166 struct cifsInodeInfo *cifs_inode;
Jeff Layton5f0319a2008-09-16 14:05:16 -04001167 struct super_block *sb = dir->i_sb;
1168 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001169 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001170 struct cifs_tcon *tcon;
Steve French60502472008-10-07 18:42:52 +00001171 struct iattr *attrs = NULL;
1172 __u32 dosattr = 0, origattr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
Joe Perchesb6b38f72010-04-21 03:50:45 +00001174 cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
Jeff Layton7ffec372010-09-29 19:51:11 -04001176 tlink = cifs_sb_tlink(cifs_sb);
1177 if (IS_ERR(tlink))
1178 return PTR_ERR(tlink);
1179 tcon = tlink_tcon(tlink);
1180
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 xid = GetXid();
1182
Jeff Layton5f0319a2008-09-16 14:05:16 -04001183 /* Unlink can be called from rename so we can not take the
1184 * sb->s_vfs_rename_mutex here */
1185 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301187 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001188 goto unlink_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 }
Steve French2d785a52007-07-15 01:48:57 +00001190
Jeff Layton5f0319a2008-09-16 14:05:16 -04001191 if ((tcon->ses->capabilities & CAP_UNIX) &&
Steve French2d785a52007-07-15 01:48:57 +00001192 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
Jeff Layton5f0319a2008-09-16 14:05:16 -04001193 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1194 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
Steve French2d785a52007-07-15 01:48:57 +00001195 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1196 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001197 cFYI(1, "posix del rc %d", rc);
Steve French2d785a52007-07-15 01:48:57 +00001198 if ((rc == 0) || (rc == -ENOENT))
1199 goto psx_del_no_retry;
1200 }
1201
Steve French60502472008-10-07 18:42:52 +00001202retry_std_delete:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001203 rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls,
Steve French737b7582005-04-28 22:41:06 -07001204 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French60502472008-10-07 18:42:52 +00001205
Steve French2d785a52007-07-15 01:48:57 +00001206psx_del_no_retry:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 if (!rc) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001208 if (inode)
1209 drop_nlink(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 } else if (rc == -ENOENT) {
Jeff Layton5f0319a2008-09-16 14:05:16 -04001211 d_drop(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 } else if (rc == -ETXTBSY) {
Steve French32709582008-10-20 00:44:19 +00001213 rc = cifs_rename_pending_delete(full_path, dentry, xid);
Jeff Laytona12a1ac2008-09-23 11:48:35 -04001214 if (rc == 0)
1215 drop_nlink(inode);
Steve Frenchff694522009-04-20 19:45:13 +00001216 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
Steve French388e57b2008-09-16 23:50:58 +00001217 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1218 if (attrs == NULL) {
1219 rc = -ENOMEM;
1220 goto out_reval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 }
Steve French388e57b2008-09-16 23:50:58 +00001222
1223 /* try to reset dos attributes */
Steve Frenchff694522009-04-20 19:45:13 +00001224 cifs_inode = CIFS_I(inode);
1225 origattr = cifs_inode->cifsAttrs;
Steve French60502472008-10-07 18:42:52 +00001226 if (origattr == 0)
1227 origattr |= ATTR_NORMAL;
1228 dosattr = origattr & ~ATTR_READONLY;
Steve French388e57b2008-09-16 23:50:58 +00001229 if (dosattr == 0)
1230 dosattr |= ATTR_NORMAL;
1231 dosattr |= ATTR_HIDDEN;
1232
1233 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
Steve French388e57b2008-09-16 23:50:58 +00001234 if (rc != 0)
1235 goto out_reval;
Steve French60502472008-10-07 18:42:52 +00001236
1237 goto retry_std_delete;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 }
Steve French60502472008-10-07 18:42:52 +00001239
1240 /* undo the setattr if we errored out and it's needed */
1241 if (rc != 0 && dosattr != 0)
1242 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1243
Steve French388e57b2008-09-16 23:50:58 +00001244out_reval:
Jeff Layton5f0319a2008-09-16 14:05:16 -04001245 if (inode) {
Steve Frenchff694522009-04-20 19:45:13 +00001246 cifs_inode = CIFS_I(inode);
1247 cifs_inode->time = 0; /* will force revalidate to get info
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001248 when needed */
Jeff Layton5f0319a2008-09-16 14:05:16 -04001249 inode->i_ctime = current_fs_time(sb);
Steve Frenchb2aeb9d2005-05-17 13:16:18 -05001250 }
Jeff Layton5f0319a2008-09-16 14:05:16 -04001251 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
Steve Frenchff694522009-04-20 19:45:13 +00001252 cifs_inode = CIFS_I(dir);
Steve French60502472008-10-07 18:42:52 +00001253 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
Jeff Layton7ffec372010-09-29 19:51:11 -04001254unlink_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 kfree(full_path);
Steve French60502472008-10-07 18:42:52 +00001256 kfree(attrs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001258 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 return rc;
1260}
1261
1262int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
1263{
Jeff Layton6b37faa2008-10-06 21:54:41 +00001264 int rc = 0, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 int xid;
1266 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001267 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001268 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 char *full_path = NULL;
1270 struct inode *newinode = NULL;
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001271 struct cifs_fattr fattr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
Joe Perchesb6b38f72010-04-21 03:50:45 +00001273 cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001276 tlink = cifs_sb_tlink(cifs_sb);
1277 if (IS_ERR(tlink))
1278 return PTR_ERR(tlink);
1279 pTcon = tlink_tcon(tlink);
1280
1281 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
Steve French7f573562005-08-30 11:32:14 -07001283 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301285 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001286 goto mkdir_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 }
Steve French50c2f752007-07-13 00:33:32 +00001288
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001289 if ((pTcon->ses->capabilities & CAP_UNIX) &&
1290 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
Steve French2dd29d32007-04-23 22:07:35 +00001291 le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
1292 u32 oplock = 0;
Steve Frenchf6d09982008-01-08 23:18:22 +00001293 FILE_UNIX_BASIC_INFO *pInfo =
Steve French2dd29d32007-04-23 22:07:35 +00001294 kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001295 if (pInfo == NULL) {
Steve French2dd29d32007-04-23 22:07:35 +00001296 rc = -ENOMEM;
1297 goto mkdir_out;
1298 }
Steve French50c2f752007-07-13 00:33:32 +00001299
Al Viroce3b0f82009-03-29 19:08:22 -04001300 mode &= ~current_umask();
Steve French2dd29d32007-04-23 22:07:35 +00001301 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
1302 mode, NULL /* netfid */, pInfo, &oplock,
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001303 full_path, cifs_sb->local_nls,
1304 cifs_sb->mnt_cifs_flags &
Steve French2dd29d32007-04-23 22:07:35 +00001305 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchc45d7072007-09-17 02:04:21 +00001306 if (rc == -EOPNOTSUPP) {
1307 kfree(pInfo);
1308 goto mkdir_retry_old;
1309 } else if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001310 cFYI(1, "posix mkdir returned 0x%x", rc);
Steve French2dd29d32007-04-23 22:07:35 +00001311 d_drop(direntry);
1312 } else {
Cyril Gorcunov8f2376a2007-10-14 17:58:43 +00001313 if (pInfo->Type == cpu_to_le32(-1)) {
1314 /* no return info, go query for it */
Steve French5a07cdf2007-09-16 23:12:47 +00001315 kfree(pInfo);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001316 goto mkdir_get_info;
Steve French5a07cdf2007-09-16 23:12:47 +00001317 }
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001318/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
1319 to set uid/gid */
Steve French2dd29d32007-04-23 22:07:35 +00001320 inc_nlink(inode);
Steve Frenchcbac3cb2007-04-25 11:46:06 +00001321
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001322 cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
Jeff Layton4065c802010-05-17 07:18:58 -04001323 cifs_fill_uniqueid(inode->i_sb, &fattr);
Jeff Laytoncc0bad72009-06-25 00:56:52 -04001324 newinode = cifs_iget(inode->i_sb, &fattr);
1325 if (!newinode) {
Steve French5a07cdf2007-09-16 23:12:47 +00001326 kfree(pInfo);
Steve Frenchcbac3cb2007-04-25 11:46:06 +00001327 goto mkdir_get_info;
Steve French5a07cdf2007-09-16 23:12:47 +00001328 }
Jeff Layton6b37faa2008-10-06 21:54:41 +00001329
Steve French2dd29d32007-04-23 22:07:35 +00001330 d_instantiate(direntry, newinode);
Steve Frenchcbac3cb2007-04-25 11:46:06 +00001331
Steve Frenchcbac3cb2007-04-25 11:46:06 +00001332#ifdef CONFIG_CIFS_DEBUG2
Joe Perchesb6b38f72010-04-21 03:50:45 +00001333 cFYI(1, "instantiated dentry %p %s to inode %p",
1334 direntry, direntry->d_name.name, newinode);
Steve Frenchcbac3cb2007-04-25 11:46:06 +00001335
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001336 if (newinode->i_nlink != 2)
Joe Perchesb6b38f72010-04-21 03:50:45 +00001337 cFYI(1, "unexpected number of links %d",
1338 newinode->i_nlink);
Steve Frenchcbac3cb2007-04-25 11:46:06 +00001339#endif
Steve French2dd29d32007-04-23 22:07:35 +00001340 }
1341 kfree(pInfo);
1342 goto mkdir_out;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001343 }
Steve Frenchc45d7072007-09-17 02:04:21 +00001344mkdir_retry_old:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 /* BB add setting the equivalent of mode via CreateX w/ACLs */
Steve French737b7582005-04-28 22:41:06 -07001346 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
1347 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001349 cFYI(1, "cifs_mkdir returned 0x%x", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 d_drop(direntry);
1351 } else {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001352mkdir_get_info:
Dave Hansend8c76e62006-09-30 23:29:04 -07001353 inc_nlink(inode);
Steve Frenchc18c8422007-07-18 23:21:09 +00001354 if (pTcon->unix_ext)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 rc = cifs_get_inode_info_unix(&newinode, full_path,
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001356 inode->i_sb, xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 else
1358 rc = cifs_get_inode_info(&newinode, full_path, NULL,
Steve French8b1327f2008-03-14 22:37:16 +00001359 inode->i_sb, xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 d_instantiate(direntry, newinode);
Steve French2dd29d32007-04-23 22:07:35 +00001362 /* setting nlink not necessary except in cases where we
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001363 * failed to get it from the server or was set bogus */
Steve French2dd29d32007-04-23 22:07:35 +00001364 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001365 direntry->d_inode->i_nlink = 2;
Jeff Layton95089912008-08-06 04:39:02 +00001366
Al Viroce3b0f82009-03-29 19:08:22 -04001367 mode &= ~current_umask();
Jeff Layton95089912008-08-06 04:39:02 +00001368 /* must turn on setgid bit if parent dir has it */
1369 if (inode->i_mode & S_ISGID)
1370 mode |= S_ISGID;
1371
Steve Frenchc18c8422007-07-18 23:21:09 +00001372 if (pTcon->unix_ext) {
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04001373 struct cifs_unix_set_info_args args = {
1374 .mode = mode,
1375 .ctime = NO_CHANGE_64,
1376 .atime = NO_CHANGE_64,
1377 .mtime = NO_CHANGE_64,
1378 .device = 0,
1379 };
Steve Frenchd0d2f2d2005-06-02 15:12:36 -07001380 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
David Howellsa001e5b2008-11-14 10:38:47 +11001381 args.uid = (__u64)current_fsuid();
Jeff Layton95089912008-08-06 04:39:02 +00001382 if (inode->i_mode & S_ISGID)
1383 args.gid = (__u64)inode->i_gid;
1384 else
David Howellsa001e5b2008-11-14 10:38:47 +11001385 args.gid = (__u64)current_fsgid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 } else {
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04001387 args.uid = NO_CHANGE_64;
1388 args.gid = NO_CHANGE_64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 }
Jeff Layton01ea95e2009-07-09 20:02:49 -04001390 CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
1391 cifs_sb->local_nls,
1392 cifs_sb->mnt_cifs_flags &
1393 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French3ce53fc2007-06-08 14:55:14 +00001394 } else {
Jeff Layton67750fb2008-05-09 22:28:02 +00001395 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
1396 (mode & S_IWUGO) == 0) {
1397 FILE_BASIC_INFO pInfo;
Jeff Layton6b37faa2008-10-06 21:54:41 +00001398 struct cifsInodeInfo *cifsInode;
1399 u32 dosattrs;
1400
Jeff Layton67750fb2008-05-09 22:28:02 +00001401 memset(&pInfo, 0, sizeof(pInfo));
Jeff Layton6b37faa2008-10-06 21:54:41 +00001402 cifsInode = CIFS_I(newinode);
1403 dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
1404 pInfo.Attributes = cpu_to_le32(dosattrs);
1405 tmprc = CIFSSMBSetPathInfo(xid, pTcon,
1406 full_path, &pInfo,
1407 cifs_sb->local_nls,
Jeff Layton67750fb2008-05-09 22:28:02 +00001408 cifs_sb->mnt_cifs_flags &
1409 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton6b37faa2008-10-06 21:54:41 +00001410 if (tmprc == 0)
1411 cifsInode->cifsAttrs = dosattrs;
Jeff Layton67750fb2008-05-09 22:28:02 +00001412 }
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001413 if (direntry->d_inode) {
Jeff Laytonb0fd30d2008-05-22 09:33:34 -04001414 if (cifs_sb->mnt_cifs_flags &
1415 CIFS_MOUNT_DYNPERM)
1416 direntry->d_inode->i_mode =
1417 (mode | S_IFDIR);
Steve French4e94a102008-05-23 18:22:46 +00001418
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001419 if (cifs_sb->mnt_cifs_flags &
Steve French6473a552005-11-29 20:20:10 -08001420 CIFS_MOUNT_SET_UID) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001421 direntry->d_inode->i_uid =
David Howellsa001e5b2008-11-14 10:38:47 +11001422 current_fsuid();
Jeff Layton95089912008-08-06 04:39:02 +00001423 if (inode->i_mode & S_ISGID)
1424 direntry->d_inode->i_gid =
1425 inode->i_gid;
1426 else
1427 direntry->d_inode->i_gid =
David Howellsa001e5b2008-11-14 10:38:47 +11001428 current_fsgid();
Steve French6473a552005-11-29 20:20:10 -08001429 }
1430 }
Steve French2a138ebb2005-11-29 21:22:19 -08001431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 }
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001433mkdir_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 kfree(full_path);
1435 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001436 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 return rc;
1438}
1439
1440int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1441{
1442 int rc = 0;
1443 int xid;
1444 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001445 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001446 struct cifs_tcon *pTcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 char *full_path = NULL;
1448 struct cifsInodeInfo *cifsInode;
1449
Joe Perchesb6b38f72010-04-21 03:50:45 +00001450 cFYI(1, "cifs_rmdir, inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
1452 xid = GetXid();
1453
Steve French7f573562005-08-30 11:32:14 -07001454 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301456 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -04001457 goto rmdir_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 }
1459
Jeff Layton7ffec372010-09-29 19:51:11 -04001460 cifs_sb = CIFS_SB(inode->i_sb);
1461 tlink = cifs_sb_tlink(cifs_sb);
1462 if (IS_ERR(tlink)) {
1463 rc = PTR_ERR(tlink);
1464 goto rmdir_exit;
1465 }
1466 pTcon = tlink_tcon(tlink);
1467
Steve French737b7582005-04-28 22:41:06 -07001468 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
1469 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04001470 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472 if (!rc) {
Dave Hansen9a53c3a2006-09-30 23:29:03 -07001473 drop_nlink(inode);
Steve French3677db12007-02-26 16:46:11 +00001474 spin_lock(&direntry->d_inode->i_lock);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001475 i_size_write(direntry->d_inode, 0);
Dave Hansence71ec32006-09-30 23:29:06 -07001476 clear_nlink(direntry->d_inode);
Steve French3677db12007-02-26 16:46:11 +00001477 spin_unlock(&direntry->d_inode->i_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 }
1479
1480 cifsInode = CIFS_I(direntry->d_inode);
1481 cifsInode->time = 0; /* force revalidate to go get info when
1482 needed */
Steve French42c24542009-01-13 22:03:55 +00001483
1484 cifsInode = CIFS_I(inode);
1485 cifsInode->time = 0; /* force revalidate to get parent dir info
1486 since cached search results now invalid */
1487
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1489 current_fs_time(inode->i_sb);
1490
Jeff Layton7ffec372010-09-29 19:51:11 -04001491rmdir_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 kfree(full_path);
1493 FreeXid(xid);
1494 return rc;
1495}
1496
Steve Frenchee2fd962008-09-23 18:23:33 +00001497static int
1498cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
1499 struct dentry *to_dentry, const char *toPath)
1500{
1501 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001502 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001503 struct cifs_tcon *pTcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001504 __u16 srcfid;
1505 int oplock, rc;
1506
Jeff Layton7ffec372010-09-29 19:51:11 -04001507 tlink = cifs_sb_tlink(cifs_sb);
1508 if (IS_ERR(tlink))
1509 return PTR_ERR(tlink);
1510 pTcon = tlink_tcon(tlink);
1511
Steve Frenchee2fd962008-09-23 18:23:33 +00001512 /* try path-based rename first */
1513 rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
1514 cifs_sb->mnt_cifs_flags &
1515 CIFS_MOUNT_MAP_SPECIAL_CHR);
1516
1517 /*
1518 * don't bother with rename by filehandle unless file is busy and
1519 * source Note that cross directory moves do not work with
1520 * rename by filehandle to various Windows servers.
1521 */
1522 if (rc == 0 || rc != -ETXTBSY)
Jeff Layton7ffec372010-09-29 19:51:11 -04001523 goto do_rename_exit;
Steve Frenchee2fd962008-09-23 18:23:33 +00001524
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001525 /* open-file renames don't work across directories */
1526 if (to_dentry->d_parent != from_dentry->d_parent)
Jeff Layton7ffec372010-09-29 19:51:11 -04001527 goto do_rename_exit;
Jeff Laytoned0e3ac2010-06-01 16:21:01 -04001528
Steve Frenchee2fd962008-09-23 18:23:33 +00001529 /* open the file to be renamed -- we need DELETE perms */
1530 rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
1531 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1532 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1533 CIFS_MOUNT_MAP_SPECIAL_CHR);
1534
1535 if (rc == 0) {
1536 rc = CIFSSMBRenameOpenFile(xid, pTcon, srcfid,
1537 (const char *) to_dentry->d_name.name,
1538 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1539 CIFS_MOUNT_MAP_SPECIAL_CHR);
1540
1541 CIFSSMBClose(xid, pTcon, srcfid);
1542 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001543do_rename_exit:
1544 cifs_put_tlink(tlink);
Steve Frenchee2fd962008-09-23 18:23:33 +00001545 return rc;
1546}
1547
Jeff Layton14121bd2008-10-20 14:45:22 -04001548int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1549 struct inode *target_dir, struct dentry *target_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550{
Steve Frenchee2fd962008-09-23 18:23:33 +00001551 char *fromName = NULL;
1552 char *toName = NULL;
Jeff Layton639e7a92010-09-03 11:50:09 -04001553 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -04001554 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001555 struct cifs_tcon *tcon;
Steve Frenchee2fd962008-09-23 18:23:33 +00001556 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1557 FILE_UNIX_BASIC_INFO *info_buf_target;
Jeff Layton8d281ef2008-10-22 13:57:01 -04001558 int xid, rc, tmprc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559
Jeff Layton639e7a92010-09-03 11:50:09 -04001560 cifs_sb = CIFS_SB(source_dir->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001561 tlink = cifs_sb_tlink(cifs_sb);
1562 if (IS_ERR(tlink))
1563 return PTR_ERR(tlink);
1564 tcon = tlink_tcon(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
Steve Frenchee2fd962008-09-23 18:23:33 +00001566 xid = GetXid();
1567
1568 /*
Steve Frenchee2fd962008-09-23 18:23:33 +00001569 * we already have the rename sem so we do not need to
1570 * grab it again here to protect the path integrity
1571 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001572 fromName = build_path_from_dentry(source_dentry);
Steve Frenchee2fd962008-09-23 18:23:33 +00001573 if (fromName == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 rc = -ENOMEM;
1575 goto cifs_rename_exit;
1576 }
1577
Jeff Layton14121bd2008-10-20 14:45:22 -04001578 toName = build_path_from_dentry(target_dentry);
Steve Frenchee2fd962008-09-23 18:23:33 +00001579 if (toName == NULL) {
1580 rc = -ENOMEM;
1581 goto cifs_rename_exit;
1582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Jeff Layton14121bd2008-10-20 14:45:22 -04001584 rc = cifs_do_rename(xid, source_dentry, fromName,
1585 target_dentry, toName);
Steve Frenchee2fd962008-09-23 18:23:33 +00001586
Jeff Layton14121bd2008-10-20 14:45:22 -04001587 if (rc == -EEXIST && tcon->unix_ext) {
Steve Frenchee2fd962008-09-23 18:23:33 +00001588 /*
Jeff Layton14121bd2008-10-20 14:45:22 -04001589 * Are src and dst hardlinks of same inode? We can
1590 * only tell with unix extensions enabled
Steve Frenchee2fd962008-09-23 18:23:33 +00001591 */
Jeff Layton14121bd2008-10-20 14:45:22 -04001592 info_buf_source =
1593 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1594 GFP_KERNEL);
1595 if (info_buf_source == NULL) {
1596 rc = -ENOMEM;
1597 goto cifs_rename_exit;
1598 }
1599
1600 info_buf_target = info_buf_source + 1;
Jeff Layton8d281ef2008-10-22 13:57:01 -04001601 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
Jeff Layton14121bd2008-10-20 14:45:22 -04001602 info_buf_source,
Jeff Layton639e7a92010-09-03 11:50:09 -04001603 cifs_sb->local_nls,
1604 cifs_sb->mnt_cifs_flags &
Jeff Layton14121bd2008-10-20 14:45:22 -04001605 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton8d281ef2008-10-22 13:57:01 -04001606 if (tmprc != 0)
Jeff Layton14121bd2008-10-20 14:45:22 -04001607 goto unlink_target;
1608
Jeff Layton639e7a92010-09-03 11:50:09 -04001609 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName,
1610 info_buf_target,
1611 cifs_sb->local_nls,
1612 cifs_sb->mnt_cifs_flags &
Jeff Layton14121bd2008-10-20 14:45:22 -04001613 CIFS_MOUNT_MAP_SPECIAL_CHR);
1614
Jeff Layton8d281ef2008-10-22 13:57:01 -04001615 if (tmprc == 0 && (info_buf_source->UniqueId ==
Jeff Laytonae6884a2008-11-03 14:05:08 -05001616 info_buf_target->UniqueId)) {
Jeff Layton14121bd2008-10-20 14:45:22 -04001617 /* same file, POSIX says that this is a noop */
Jeff Laytonae6884a2008-11-03 14:05:08 -05001618 rc = 0;
Jeff Layton14121bd2008-10-20 14:45:22 -04001619 goto cifs_rename_exit;
Jeff Laytonae6884a2008-11-03 14:05:08 -05001620 }
Jeff Layton14121bd2008-10-20 14:45:22 -04001621 } /* else ... BB we could add the same check for Windows by
1622 checking the UniqueId via FILE_INTERNAL_INFO */
1623
Jeff Layton14121bd2008-10-20 14:45:22 -04001624unlink_target:
Jeff Laytonfc6f3942009-04-17 11:45:30 -04001625 /* Try unlinking the target dentry if it's not negative */
1626 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
Jeff Layton8d281ef2008-10-22 13:57:01 -04001627 tmprc = cifs_unlink(target_dir, target_dentry);
Jeff Layton14121bd2008-10-20 14:45:22 -04001628 if (tmprc)
1629 goto cifs_rename_exit;
1630
Jeff Layton14121bd2008-10-20 14:45:22 -04001631 rc = cifs_do_rename(xid, source_dentry, fromName,
1632 target_dentry, toName);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 }
1634
1635cifs_rename_exit:
Steve Frenchee2fd962008-09-23 18:23:33 +00001636 kfree(info_buf_source);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 kfree(fromName);
1638 kfree(toName);
1639 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -04001640 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 return rc;
1642}
1643
Jeff Laytondf2cf172010-02-12 07:44:16 -05001644static bool
1645cifs_inode_needs_reval(struct inode *inode)
1646{
1647 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301648 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Laytondf2cf172010-02-12 07:44:16 -05001649
1650 if (cifs_i->clientCanCacheRead)
1651 return false;
1652
1653 if (!lookupCacheEnabled)
1654 return true;
1655
1656 if (cifs_i->time == 0)
1657 return true;
1658
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301659 if (!time_in_range(jiffies, cifs_i->time,
1660 cifs_i->time + cifs_sb->actimeo))
Jeff Laytondf2cf172010-02-12 07:44:16 -05001661 return true;
1662
Jeff Laytondb192722010-05-17 14:51:49 -04001663 /* hardlinked files w/ noserverino get "special" treatment */
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301664 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
Jeff Laytondb192722010-05-17 14:51:49 -04001665 S_ISREG(inode->i_mode) && inode->i_nlink != 1)
1666 return true;
1667
Jeff Laytondf2cf172010-02-12 07:44:16 -05001668 return false;
1669}
1670
Suresh Jayaraman523fb8c2010-11-29 22:39:47 +05301671/*
1672 * Zap the cache. Called when invalid_mapping flag is set.
1673 */
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001674int
Jeff Laytondf2cf172010-02-12 07:44:16 -05001675cifs_invalidate_mapping(struct inode *inode)
1676{
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001677 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001678 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1679
1680 cifs_i->invalid_mapping = false;
1681
Jeff Laytondf2cf172010-02-12 07:44:16 -05001682 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001683 rc = invalidate_inode_pages2(inode->i_mapping);
1684 if (rc) {
1685 cERROR(1, "%s: could not invalidate inode %p", __func__,
1686 inode);
1687 cifs_i->invalid_mapping = true;
1688 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001689 }
Pavel Shilovsky257fb1f2011-03-16 01:55:32 +03001690
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +05301691 cifs_fscache_reset_inode_cookie(inode);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001692 return rc;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001693}
1694
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001695int cifs_revalidate_file_attr(struct file *filp)
Jeff Laytonabab0952010-02-12 07:44:18 -05001696{
1697 int rc = 0;
1698 struct inode *inode = filp->f_path.dentry->d_inode;
Jeff Laytonba00ba62010-09-20 16:01:31 -07001699 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
Jeff Laytonabab0952010-02-12 07:44:18 -05001700
1701 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001702 return rc;
Jeff Laytonabab0952010-02-12 07:44:18 -05001703
Jeff Layton13cfb732010-09-29 19:51:11 -04001704 if (tlink_tcon(cfile->tlink)->unix_ext)
Jeff Laytonabab0952010-02-12 07:44:18 -05001705 rc = cifs_get_file_info_unix(filp);
1706 else
1707 rc = cifs_get_file_info(filp);
1708
Jeff Laytonabab0952010-02-12 07:44:18 -05001709 return rc;
1710}
1711
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001712int cifs_revalidate_dentry_attr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713{
1714 int xid;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001715 int rc = 0;
Jeff Laytondf2cf172010-02-12 07:44:16 -05001716 struct inode *inode = dentry->d_inode;
1717 struct super_block *sb = dentry->d_sb;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001718 char *full_path = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719
Jeff Laytondf2cf172010-02-12 07:44:16 -05001720 if (inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 return -ENOENT;
1722
Jeff Laytondf2cf172010-02-12 07:44:16 -05001723 if (!cifs_inode_needs_reval(inode))
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001724 return rc;
1725
1726 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
1728 /* can not safely grab the rename sem here if rename calls revalidate
1729 since that would deadlock */
Jeff Laytondf2cf172010-02-12 07:44:16 -05001730 full_path = build_path_from_dentry(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05301732 rc = -ENOMEM;
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001733 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 }
Jeff Laytondf2cf172010-02-12 07:44:16 -05001735
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001736 cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time "
1737 "%ld jiffies %ld", full_path, inode, inode->i_count.counter,
Steve Frenchf19159d2010-04-21 04:12:10 +00001738 dentry, dentry->d_time, jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
Jeff Layton0d424ad2010-09-20 16:01:35 -07001740 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
Jeff Laytondf2cf172010-02-12 07:44:16 -05001741 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1742 else
1743 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1744 xid, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001746out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 kfree(full_path);
1748 FreeXid(xid);
1749 return rc;
1750}
1751
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001752int cifs_revalidate_file(struct file *filp)
1753{
1754 int rc;
1755 struct inode *inode = filp->f_path.dentry->d_inode;
1756
1757 rc = cifs_revalidate_file_attr(filp);
1758 if (rc)
1759 return rc;
1760
1761 if (CIFS_I(inode)->invalid_mapping)
1762 rc = cifs_invalidate_mapping(inode);
1763 return rc;
1764}
1765
1766/* revalidate a dentry's inode attributes */
1767int cifs_revalidate_dentry(struct dentry *dentry)
1768{
1769 int rc;
1770 struct inode *inode = dentry->d_inode;
1771
1772 rc = cifs_revalidate_dentry_attr(dentry);
1773 if (rc)
1774 return rc;
1775
1776 if (CIFS_I(inode)->invalid_mapping)
1777 rc = cifs_invalidate_mapping(inode);
1778 return rc;
1779}
1780
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
Jeff Layton1c456012010-10-12 11:32:42 -04001782 struct kstat *stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783{
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001784 struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
Steve French96daf2b2011-05-27 04:34:02 +00001785 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001786 struct inode *inode = dentry->d_inode;
1787 int rc;
Jeff Layton3aa1c8c2010-10-07 14:46:28 -04001788
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001789 /*
1790 * We need to be sure that all dirty pages are written and the server
1791 * has actual ctime, mtime and file length.
1792 */
1793 if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
1794 inode->i_mapping->nrpages != 0) {
1795 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +00001796 if (rc) {
1797 mapping_set_error(inode->i_mapping, rc);
1798 return rc;
1799 }
Steve French5fe14c82006-11-07 19:26:33 +00001800 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +04001801
1802 rc = cifs_revalidate_dentry_attr(dentry);
1803 if (rc)
1804 return rc;
1805
1806 generic_fillattr(inode, stat);
1807 stat->blksize = CIFS_MAX_MSGSIZE;
1808 stat->ino = CIFS_I(inode)->uniqueid;
1809
1810 /*
1811 * If on a multiuser mount without unix extensions, and the admin hasn't
1812 * overridden them, set the ownership to the fsuid/fsgid of the current
1813 * process.
1814 */
1815 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
1816 !tcon->unix_ext) {
1817 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
1818 stat->uid = current_fsuid();
1819 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
1820 stat->gid = current_fsgid();
1821 }
1822 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823}
1824
1825static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1826{
1827 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1828 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1829 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 int rc = 0;
1831
1832 page = grab_cache_page(mapping, index);
1833 if (!page)
1834 return -ENOMEM;
1835
Christoph Lametereebd2aa2008-02-04 22:28:29 -08001836 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 unlock_page(page);
1838 page_cache_release(page);
1839 return rc;
1840}
1841
Christoph Hellwig1b947462010-07-18 17:51:21 -04001842static void cifs_setsize(struct inode *inode, loff_t offset)
Steve French3677db12007-02-26 16:46:11 +00001843{
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001844 loff_t oldsize;
Steve French3677db12007-02-26 16:46:11 +00001845
Steve Frenchba6a46a2007-02-26 20:06:29 +00001846 spin_lock(&inode->i_lock);
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001847 oldsize = inode->i_size;
Steve French3677db12007-02-26 16:46:11 +00001848 i_size_write(inode, offset);
Steve Frenchba6a46a2007-02-26 20:06:29 +00001849 spin_unlock(&inode->i_lock);
Christoph Hellwig1b947462010-07-18 17:51:21 -04001850
npiggin@suse.dec08d3b02009-08-21 02:35:06 +10001851 truncate_pagecache(inode, oldsize, offset);
Steve French3677db12007-02-26 16:46:11 +00001852}
1853
Jeff Layton8efdbde2008-07-23 21:28:12 +00001854static int
1855cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1856 int xid, char *full_path)
1857{
1858 int rc;
1859 struct cifsFileInfo *open_file;
1860 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1861 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001862 struct tcon_link *tlink = NULL;
Steve French96daf2b2011-05-27 04:34:02 +00001863 struct cifs_tcon *pTcon = NULL;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001864 struct cifs_io_parms io_parms;
Jeff Layton8efdbde2008-07-23 21:28:12 +00001865
1866 /*
1867 * To avoid spurious oplock breaks from server, in the case of
1868 * inodes that we already have open, avoid doing path based
1869 * setting of file size if we can do it by handle.
1870 * This keeps our caching token (oplock) and avoids timeouts
1871 * when the local oplock break takes longer to flush
1872 * writebehind data than the SMB timeout for the SetPathInfo
1873 * request would allow
1874 */
Jeff Layton6508d902010-09-29 19:51:11 -04001875 open_file = find_writable_file(cifsInode, true);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001876 if (open_file) {
1877 __u16 nfid = open_file->netfid;
1878 __u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04001879 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001880 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
1881 npid, false);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04001882 cifsFileInfo_put(open_file);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001883 cFYI(1, "SetFSize for attrs rc = %d", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001884 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1885 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001886
1887 io_parms.netfid = nfid;
1888 io_parms.pid = npid;
1889 io_parms.tcon = pTcon;
1890 io_parms.offset = 0;
1891 io_parms.length = attrs->ia_size;
1892 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1893 NULL, NULL, 1);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001894 cFYI(1, "Wrt seteof rc %d", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001895 }
1896 } else
1897 rc = -EINVAL;
1898
1899 if (rc != 0) {
Jeff Layton7ffec372010-09-29 19:51:11 -04001900 if (pTcon == NULL) {
1901 tlink = cifs_sb_tlink(cifs_sb);
1902 if (IS_ERR(tlink))
1903 return PTR_ERR(tlink);
1904 pTcon = tlink_tcon(tlink);
1905 }
Jeff Laytonba00ba62010-09-20 16:01:31 -07001906
Jeff Layton8efdbde2008-07-23 21:28:12 +00001907 /* Set file size by pathname rather than by handle
1908 either because no valid, writeable file handle for
1909 it was found or because there was an error setting
1910 it by handle */
1911 rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,
1912 false, cifs_sb->local_nls,
1913 cifs_sb->mnt_cifs_flags &
1914 CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001915 cFYI(1, "SetEOF by path (setattrs) rc = %d", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001916 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1917 __u16 netfid;
1918 int oplock = 0;
1919
1920 rc = SMBLegacyOpen(xid, pTcon, full_path,
1921 FILE_OPEN, GENERIC_WRITE,
1922 CREATE_NOT_DIR, &netfid, &oplock, NULL,
1923 cifs_sb->local_nls,
1924 cifs_sb->mnt_cifs_flags &
1925 CIFS_MOUNT_MAP_SPECIAL_CHR);
1926 if (rc == 0) {
1927 unsigned int bytes_written;
Pavel Shilovskyfa2989f2011-05-26 10:01:59 +04001928
1929 io_parms.netfid = netfid;
1930 io_parms.pid = current->tgid;
1931 io_parms.tcon = pTcon;
1932 io_parms.offset = 0;
1933 io_parms.length = attrs->ia_size;
1934 rc = CIFSSMBWrite(xid, &io_parms,
1935 &bytes_written,
1936 NULL, NULL, 1);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001937 cFYI(1, "wrt seteof rc %d", rc);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001938 CIFSSMBClose(xid, pTcon, netfid);
1939 }
1940 }
Jeff Layton7ffec372010-09-29 19:51:11 -04001941 if (tlink)
1942 cifs_put_tlink(tlink);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001943 }
1944
1945 if (rc == 0) {
Jeff Laytonfbec9ab2009-04-03 13:44:00 -04001946 cifsInode->server_eof = attrs->ia_size;
Christoph Hellwig1b947462010-07-18 17:51:21 -04001947 cifs_setsize(inode, attrs->ia_size);
Jeff Layton8efdbde2008-07-23 21:28:12 +00001948 cifs_truncate_page(inode->i_mapping, inode->i_size);
1949 }
1950
1951 return rc;
1952}
1953
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001954static int
1955cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1956{
1957 int rc;
1958 int xid;
1959 char *full_path = NULL;
1960 struct inode *inode = direntry->d_inode;
1961 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1962 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton7ffec372010-09-29 19:51:11 -04001963 struct tcon_link *tlink;
Steve French96daf2b2011-05-27 04:34:02 +00001964 struct cifs_tcon *pTcon;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001965 struct cifs_unix_set_info_args *args = NULL;
Jeff Layton3bbeeb32009-07-09 20:02:50 -04001966 struct cifsFileInfo *open_file;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001967
Joe Perchesb6b38f72010-04-21 03:50:45 +00001968 cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x",
1969 direntry->d_name.name, attrs->ia_valid);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001970
1971 xid = GetXid();
1972
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001973 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
1974 attrs->ia_valid |= ATTR_FORCE;
1975
1976 rc = inode_change_ok(inode, attrs);
1977 if (rc < 0)
1978 goto out;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04001979
1980 full_path = build_path_from_dentry(direntry);
1981 if (full_path == NULL) {
1982 rc = -ENOMEM;
1983 goto out;
1984 }
1985
Jeff Layton0f4d6342009-03-26 13:35:37 -04001986 /*
1987 * Attempt to flush data before changing attributes. We need to do
1988 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1989 * ownership or mode then we may also need to do this. Here, we take
1990 * the safe way out and just do the flush on all setattr requests. If
1991 * the flush returns error, store it to report later and continue.
1992 *
1993 * BB: This should be smarter. Why bother flushing pages that
1994 * will be truncated anyway? Also, should we error out here if
1995 * the flush returns error?
1996 */
1997 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04001998 mapping_set_error(inode->i_mapping, rc);
1999 rc = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002000
2001 if (attrs->ia_valid & ATTR_SIZE) {
2002 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2003 if (rc != 0)
2004 goto out;
2005 }
2006
2007 /* skip mode change if it's just for clearing setuid/setgid */
2008 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2009 attrs->ia_valid &= ~ATTR_MODE;
2010
2011 args = kmalloc(sizeof(*args), GFP_KERNEL);
2012 if (args == NULL) {
2013 rc = -ENOMEM;
2014 goto out;
2015 }
2016
2017 /* set up the struct */
2018 if (attrs->ia_valid & ATTR_MODE)
2019 args->mode = attrs->ia_mode;
2020 else
2021 args->mode = NO_CHANGE_64;
2022
2023 if (attrs->ia_valid & ATTR_UID)
2024 args->uid = attrs->ia_uid;
2025 else
2026 args->uid = NO_CHANGE_64;
2027
2028 if (attrs->ia_valid & ATTR_GID)
2029 args->gid = attrs->ia_gid;
2030 else
2031 args->gid = NO_CHANGE_64;
2032
2033 if (attrs->ia_valid & ATTR_ATIME)
2034 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
2035 else
2036 args->atime = NO_CHANGE_64;
2037
2038 if (attrs->ia_valid & ATTR_MTIME)
2039 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
2040 else
2041 args->mtime = NO_CHANGE_64;
2042
2043 if (attrs->ia_valid & ATTR_CTIME)
2044 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
2045 else
2046 args->ctime = NO_CHANGE_64;
2047
2048 args->device = 0;
Jeff Layton6508d902010-09-29 19:51:11 -04002049 open_file = find_writable_file(cifsInode, true);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002050 if (open_file) {
2051 u16 nfid = open_file->netfid;
2052 u32 npid = open_file->pid;
Jeff Layton13cfb732010-09-29 19:51:11 -04002053 pTcon = tlink_tcon(open_file->tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002054 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -04002055 cifsFileInfo_put(open_file);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002056 } else {
Jeff Layton7ffec372010-09-29 19:51:11 -04002057 tlink = cifs_sb_tlink(cifs_sb);
2058 if (IS_ERR(tlink)) {
2059 rc = PTR_ERR(tlink);
2060 goto out;
2061 }
2062 pTcon = tlink_tcon(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002063 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
Jeff Layton01ea95e2009-07-09 20:02:49 -04002064 cifs_sb->local_nls,
2065 cifs_sb->mnt_cifs_flags &
2066 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton7ffec372010-09-29 19:51:11 -04002067 cifs_put_tlink(tlink);
Jeff Layton3bbeeb32009-07-09 20:02:50 -04002068 }
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002069
Christoph Hellwig10257742010-06-04 11:30:02 +02002070 if (rc)
2071 goto out;
Steve Frenchccd4bb12010-02-08 17:39:58 +00002072
Christoph Hellwig10257742010-06-04 11:30:02 +02002073 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002074 attrs->ia_size != i_size_read(inode))
2075 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002076
2077 setattr_copy(inode, attrs);
2078 mark_inode_dirty(inode);
2079
2080 /* force revalidate when any of these times are set since some
2081 of the fs types (eg ext3, fat) do not have fine enough
2082 time granularity to match protocol, and we do not have a
2083 a way (yet) to query the server fs's time granularity (and
2084 whether it rounds times down).
2085 */
2086 if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
2087 cifsInode->time = 0;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002088out:
2089 kfree(args);
2090 kfree(full_path);
2091 FreeXid(xid);
2092 return rc;
2093}
2094
Jeff Layton0510eeb2008-08-02 07:26:12 -04002095static int
2096cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097{
2098 int xid;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002099 struct inode *inode = direntry->d_inode;
2100 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002101 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 char *full_path = NULL;
2103 int rc = -EACCES;
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002104 __u32 dosattr = 0;
Jeff Layton4e1e7fb2008-08-02 07:26:12 -04002105 __u64 mode = NO_CHANGE_64;
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002106
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 xid = GetXid();
2108
Joe Perchesb6b38f72010-04-21 03:50:45 +00002109 cFYI(1, "setattr on file %s attrs->iavalid 0x%x",
2110 direntry->d_name.name, attrs->ia_valid);
Steve French6473a552005-11-29 20:20:10 -08002111
Christoph Hellwigdb78b872010-06-04 11:30:03 +02002112 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
2113 attrs->ia_valid |= ATTR_FORCE;
2114
2115 rc = inode_change_ok(inode, attrs);
2116 if (rc < 0) {
2117 FreeXid(xid);
2118 return rc;
Steve French6473a552005-11-29 20:20:10 -08002119 }
Steve French50c2f752007-07-13 00:33:32 +00002120
Steve French7f573562005-08-30 11:32:14 -07002121 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302123 rc = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 FreeXid(xid);
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +05302125 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127
Jeff Layton0f4d6342009-03-26 13:35:37 -04002128 /*
2129 * Attempt to flush data before changing attributes. We need to do
2130 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
2131 * ownership or mode then we may also need to do this. Here, we take
2132 * the safe way out and just do the flush on all setattr requests. If
2133 * the flush returns error, store it to report later and continue.
2134 *
2135 * BB: This should be smarter. Why bother flushing pages that
2136 * will be truncated anyway? Also, should we error out here if
2137 * the flush returns error?
2138 */
2139 rc = filemap_write_and_wait(inode->i_mapping);
Jeff Laytoneb4b7562010-10-22 14:52:29 -04002140 mapping_set_error(inode->i_mapping, rc);
2141 rc = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +00002142
Steve French50531442008-03-14 19:21:31 +00002143 if (attrs->ia_valid & ATTR_SIZE) {
Jeff Layton8efdbde2008-07-23 21:28:12 +00002144 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2145 if (rc != 0)
Steve Frenche30dcf32005-09-20 20:49:16 -07002146 goto cifs_setattr_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 }
Jeff Layton4ca691a2008-05-22 09:33:34 -04002148
2149 /*
2150 * Without unix extensions we can't send ownership changes to the
2151 * server, so silently ignore them. This is consistent with how
2152 * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With
2153 * CIFSACL support + proper Windows to Unix idmapping, we may be
2154 * able to support this in the future.
2155 */
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002156 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
Jeff Layton4ca691a2008-05-22 09:33:34 -04002157 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158
Jeff Laytond32c4f22007-10-18 03:05:22 -07002159 /* skip mode change if it's just for clearing setuid/setgid */
2160 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
2161 attrs->ia_valid &= ~ATTR_MODE;
2162
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 if (attrs->ia_valid & ATTR_MODE) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002164 cFYI(1, "Mode changed to 0%o", attrs->ia_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 mode = attrs->ia_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 }
2167
Jeff Layton3fe5c1d2008-08-02 07:26:12 -04002168 if (attrs->ia_valid & ATTR_MODE) {
Steve Frenchcdbce9c2005-11-19 21:04:52 -08002169 rc = 0;
Jeff Layton79df1ba2010-12-06 12:52:08 -05002170#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar78415d22010-11-27 11:37:26 -06002171 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
2172 rc = mode_to_cifs_acl(inode, full_path, mode);
2173 if (rc) {
2174 cFYI(1, "%s: Setting ACL failed with error: %d",
2175 __func__, rc);
2176 goto cifs_setattr_exit;
2177 }
2178 } else
Jeff Layton79df1ba2010-12-06 12:52:08 -05002179#endif /* CONFIG_CIFS_ACL */
Jeff Layton51328612008-05-22 09:33:34 -04002180 if (((mode & S_IWUGO) == 0) &&
2181 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002182
2183 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
2184
Jeff Layton51328612008-05-22 09:33:34 -04002185 /* fix up mode if we're not using dynperm */
2186 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
2187 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
2188 } else if ((mode & S_IWUGO) &&
2189 (cifsInode->cifsAttrs & ATTR_READONLY)) {
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002190
2191 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
2192 /* Attributes of 0 are ignored */
2193 if (dosattr == 0)
2194 dosattr |= ATTR_NORMAL;
Jeff Layton51328612008-05-22 09:33:34 -04002195
2196 /* reset local inode permissions to normal */
2197 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2198 attrs->ia_mode &= ~(S_IALLUGO);
2199 if (S_ISDIR(inode->i_mode))
2200 attrs->ia_mode |=
2201 cifs_sb->mnt_dir_mode;
2202 else
2203 attrs->ia_mode |=
2204 cifs_sb->mnt_file_mode;
2205 }
2206 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
2207 /* ignore mode change - ATTR_READONLY hasn't changed */
2208 attrs->ia_valid &= ~ATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 }
2211
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002212 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
2213 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
2214 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
2215 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216
Steve Frenche30dcf32005-09-20 20:49:16 -07002217 /* Even if error on time set, no sense failing the call if
2218 the server would set the time to a reasonable value anyway,
2219 and this check ensures that we are not being called from
2220 sys_utimes in which case we ought to fail the call back to
2221 the user when the server rejects the call */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002222 if ((rc) && (attrs->ia_valid &
Jeff Laytonfeb3e202008-08-02 07:26:12 -04002223 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
Steve Frenche30dcf32005-09-20 20:49:16 -07002224 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 }
2226
2227 /* do not need local check to inode_check_ok since the server does
2228 that */
Christoph Hellwig10257742010-06-04 11:30:02 +02002229 if (rc)
2230 goto cifs_setattr_exit;
2231
2232 if ((attrs->ia_valid & ATTR_SIZE) &&
Christoph Hellwig1b947462010-07-18 17:51:21 -04002233 attrs->ia_size != i_size_read(inode))
2234 truncate_setsize(inode, attrs->ia_size);
Christoph Hellwig10257742010-06-04 11:30:02 +02002235
2236 setattr_copy(inode, attrs);
2237 mark_inode_dirty(inode);
Christoph Hellwig10257742010-06-04 11:30:02 +02002238
Steve Frenche30dcf32005-09-20 20:49:16 -07002239cifs_setattr_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 kfree(full_path);
2241 FreeXid(xid);
2242 return rc;
2243}
2244
Jeff Layton0510eeb2008-08-02 07:26:12 -04002245int
2246cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2247{
2248 struct inode *inode = direntry->d_inode;
2249 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Steve French96daf2b2011-05-27 04:34:02 +00002250 struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
Jeff Layton0510eeb2008-08-02 07:26:12 -04002251
2252 if (pTcon->unix_ext)
2253 return cifs_setattr_unix(direntry, attrs);
2254
2255 return cifs_setattr_nounix(direntry, attrs);
2256
2257 /* BB: add cifs_setattr_legacy for really old servers */
2258}
2259
Steve French99ee4db2007-02-27 05:35:17 +00002260#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261void cifs_delete_inode(struct inode *inode)
2262{
Joe Perchesb6b38f72010-04-21 03:50:45 +00002263 cFYI(1, "In cifs_delete_inode, inode = 0x%p", inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 /* may have to add back in if and when safe distributed caching of
2265 directories added e.g. via FindNotify */
2266}
Steve French99ee4db2007-02-27 05:35:17 +00002267#endif