Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / fs / cifs / dir.c
CommitLineData
1da177e4
LT
1/*
2 * fs/cifs/dir.c
3 *
4 * vfs operations that deal with dentries
5fdae1f6 5 *
c3b2a0c6 6 * Copyright (C) International Business Machines Corp., 2002,2009
1da177e4
LT
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/fs.h>
24#include <linux/stat.h>
25#include <linux/slab.h>
26#include <linux/namei.h>
3bc303c2 27#include <linux/mount.h>
1da177e4
LT
28#include "cifsfs.h"
29#include "cifspdu.h"
30#include "cifsglob.h"
31#include "cifsproto.h"
32#include "cifs_debug.h"
33#include "cifs_fs_sb.h"
34
99ee4dbd 35static void
1da177e4
LT
36renew_parental_timestamps(struct dentry *direntry)
37{
5fdae1f6
SF
38 /* BB check if there is a way to get the kernel to do this or if we
39 really need this */
1da177e4
LT
40 do {
41 direntry->d_time = jiffies;
42 direntry = direntry->d_parent;
5fdae1f6 43 } while (!IS_ROOT(direntry));
1da177e4
LT
44}
45
46/* Note: caller must free return buffer */
47char *
48build_path_from_dentry(struct dentry *direntry)
49{
50 struct dentry *temp;
2fe87f02
SF
51 int namelen;
52 int pplen;
646dd539 53 int dfsplen;
1da177e4 54 char *full_path;
88274815 55 char dirsep;
646dd539 56 struct cifs_sb_info *cifs_sb;
1da177e4 57
5fdae1f6 58 if (direntry == NULL)
1da177e4
LT
59 return NULL; /* not much we can do if dentry is freed and
60 we need to reopen the file after it was closed implicitly
61 when the server crashed */
62
646dd539
SF
63 cifs_sb = CIFS_SB(direntry->d_sb);
64 dirsep = CIFS_DIR_SEP(cifs_sb);
65 pplen = cifs_sb->prepathlen;
66 if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
67 dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
68 else
69 dfsplen = 0;
1da177e4 70cifs_bp_rename_retry:
646dd539 71 namelen = pplen + dfsplen;
1da177e4
LT
72 for (temp = direntry; !IS_ROOT(temp);) {
73 namelen += (1 + temp->d_name.len);
74 temp = temp->d_parent;
5fdae1f6 75 if (temp == NULL) {
b6b38f70 76 cERROR(1, "corrupt dentry");
1da177e4
LT
77 return NULL;
78 }
79 }
80
81 full_path = kmalloc(namelen+1, GFP_KERNEL);
5fdae1f6 82 if (full_path == NULL)
1da177e4
LT
83 return full_path;
84 full_path[namelen] = 0; /* trailing null */
1da177e4
LT
85 for (temp = direntry; !IS_ROOT(temp);) {
86 namelen -= 1 + temp->d_name.len;
87 if (namelen < 0) {
88 break;
89 } else {
7f57356b 90 full_path[namelen] = dirsep;
1da177e4
LT
91 strncpy(full_path + namelen + 1, temp->d_name.name,
92 temp->d_name.len);
b6b38f70 93 cFYI(0, "name: %s", full_path + namelen);
1da177e4
LT
94 }
95 temp = temp->d_parent;
5fdae1f6 96 if (temp == NULL) {
b6b38f70 97 cERROR(1, "corrupt dentry");
1da177e4
LT
98 kfree(full_path);
99 return NULL;
100 }
101 }
646dd539 102 if (namelen != pplen + dfsplen) {
b6b38f70
JP
103 cERROR(1, "did not end path lookup where expected namelen is %d",
104 namelen);
5fdae1f6 105 /* presumably this is only possible if racing with a rename
1da177e4
LT
106 of one of the parent directories (we can not lock the dentries
107 above us to prevent this, but retrying should be harmless) */
108 kfree(full_path);
1da177e4
LT
109 goto cifs_bp_rename_retry;
110 }
2fe87f02
SF
111 /* DIR_SEP already set for byte 0 / vs \ but not for
112 subsequent slashes in prepath which currently must
113 be entered the right way - not sure if there is an alternative
114 since the '\' is a valid posix character so we can not switch
115 those safely to '/' if any are found in the middle of the prepath */
116 /* BB test paths to Windows with '/' in the midst of prepath */
646dd539
SF
117
118 if (dfsplen) {
119 strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
120 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
121 int i;
122 for (i = 0; i < dfsplen; i++) {
123 if (full_path[i] == '\\')
124 full_path[i] = '/';
125 }
126 }
127 }
128 strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
1da177e4
LT
129 return full_path;
130}
131
fae683f7
SJ
132/*
133 * When called with struct file pointer set to NULL, there is no way we could
134 * update file->private_data, but getting it stuck on openFileList provides a
135 * way to access it from cifs_fill_filedata and thereby set file->private_data
136 * from cifs_open.
137 */
086f68bd
JL
138struct cifsFileInfo *
139cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
140 struct file *file, struct vfsmount *mnt, unsigned int oflags)
a6ce4932
SF
141{
142 int oplock = 0;
143 struct cifsFileInfo *pCifsFile;
144 struct cifsInodeInfo *pCifsInode;
3bc303c2 145 struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
a6ce4932
SF
146
147 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
a6ce4932 148 if (pCifsFile == NULL)
086f68bd 149 return pCifsFile;
a6ce4932
SF
150
151 if (oplockEnabled)
152 oplock = REQ_OPLOCK;
153
154 pCifsFile->netfid = fileHandle;
155 pCifsFile->pid = current->tgid;
48541bd3 156 pCifsFile->pInode = igrab(newinode);
3bc303c2 157 pCifsFile->mnt = mnt;
086f68bd 158 pCifsFile->pfile = file;
a6ce4932 159 pCifsFile->invalidHandle = false;
bc8cd439 160 pCifsFile->closePend = false;
a6ce4932
SF
161 mutex_init(&pCifsFile->fh_mutex);
162 mutex_init(&pCifsFile->lock_mutex);
163 INIT_LIST_HEAD(&pCifsFile->llist);
6ab409b5 164 atomic_set(&pCifsFile->count, 1);
3bc303c2 165 slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops);
a6ce4932 166
a6ce4932 167 write_lock(&GlobalSMBSeslock);
3bc303c2 168 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
a6ce4932
SF
169 pCifsInode = CIFS_I(newinode);
170 if (pCifsInode) {
171 /* if readable file instance put first in list*/
086f68bd
JL
172 if (oflags & FMODE_READ)
173 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
174 else
a6ce4932
SF
175 list_add_tail(&pCifsFile->flist,
176 &pCifsInode->openFileList);
bc8cd439 177
a6ce4932
SF
178 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
179 pCifsInode->clientCanCacheAll = true;
180 pCifsInode->clientCanCacheRead = true;
b6b38f70 181 cFYI(1, "Exclusive Oplock inode %p", newinode);
a6ce4932 182 } else if ((oplock & 0xF) == OPLOCK_READ)
bc8cd439 183 pCifsInode->clientCanCacheRead = true;
a6ce4932
SF
184 }
185 write_unlock(&GlobalSMBSeslock);
086f68bd
JL
186
187 return pCifsFile;
a6ce4932
SF
188}
189
7fc8f4e9 190int cifs_posix_open(char *full_path, struct inode **pinode,
fa588e0c
SF
191 struct vfsmount *mnt, struct super_block *sb,
192 int mode, int oflags,
193 __u32 *poplock, __u16 *pnetfid, int xid)
c3b2a0c6
SF
194{
195 int rc;
c3b2a0c6
SF
196 FILE_UNIX_BASIC_INFO *presp_data;
197 __u32 posix_flags = 0;
fa588e0c 198 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
cc0bad75 199 struct cifs_fattr fattr;
c3b2a0c6 200
b6b38f70 201 cFYI(1, "posix open %s", full_path);
c3b2a0c6
SF
202
203 presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
204 if (presp_data == NULL)
205 return -ENOMEM;
206
207/* So far cifs posix extensions can only map the following flags.
208 There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
209 so far we do not seem to need them, and we can treat them as local only */
210 if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
211 (FMODE_READ | FMODE_WRITE))
212 posix_flags = SMB_O_RDWR;
213 else if (oflags & FMODE_READ)
214 posix_flags = SMB_O_RDONLY;
215 else if (oflags & FMODE_WRITE)
216 posix_flags = SMB_O_WRONLY;
217 if (oflags & O_CREAT)
218 posix_flags |= SMB_O_CREAT;
219 if (oflags & O_EXCL)
220 posix_flags |= SMB_O_EXCL;
221 if (oflags & O_TRUNC)
222 posix_flags |= SMB_O_TRUNC;
6b2f3d1f
CH
223 /* be safe and imply O_SYNC for O_DSYNC */
224 if (oflags & O_DSYNC)
c3b2a0c6
SF
225 posix_flags |= SMB_O_SYNC;
226 if (oflags & O_DIRECTORY)
227 posix_flags |= SMB_O_DIRECTORY;
228 if (oflags & O_NOFOLLOW)
229 posix_flags |= SMB_O_NOFOLLOW;
230 if (oflags & O_DIRECT)
231 posix_flags |= SMB_O_DIRECT;
232
703a3b8e 233 mode &= ~current_umask();
c3b2a0c6 234 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
590a3fe0 235 pnetfid, presp_data, poplock, full_path,
c3b2a0c6
SF
236 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
237 CIFS_MOUNT_MAP_SPECIAL_CHR);
238 if (rc)
239 goto posix_open_ret;
240
241 if (presp_data->Type == cpu_to_le32(-1))
242 goto posix_open_ret; /* open ok, caller does qpathinfo */
243
c3b2a0c6
SF
244 if (!pinode)
245 goto posix_open_ret; /* caller does not need info */
246
cc0bad75
JL
247 cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
248
249 /* get new inode and set it up */
85a6dac5 250 if (*pinode == NULL) {
4065c802 251 cifs_fill_uniqueid(sb, &fattr);
fa588e0c 252 *pinode = cifs_iget(sb, &fattr);
cc0bad75
JL
253 if (!*pinode) {
254 rc = -ENOMEM;
255 goto posix_open_ret;
256 }
257 } else {
258 cifs_fattr_to_inode(*pinode, &fattr);
85a6dac5 259 }
c3b2a0c6 260
fae683f7
SJ
261 /*
262 * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to
263 * file->private_data.
264 */
fdb36038
SJ
265 if (mnt) {
266 struct cifsFileInfo *pfile_info;
267
268 pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt,
269 oflags);
270 if (pfile_info == NULL)
271 rc = -ENOMEM;
272 }
a6ce4932 273
c3b2a0c6
SF
274posix_open_ret:
275 kfree(presp_data);
276 return rc;
277}
278
f818dd55
SF
279static void setup_cifs_dentry(struct cifsTconInfo *tcon,
280 struct dentry *direntry,
281 struct inode *newinode)
282{
283 if (tcon->nocase)
284 direntry->d_op = &cifs_ci_dentry_ops;
285 else
286 direntry->d_op = &cifs_dentry_ops;
287 d_instantiate(direntry, newinode);
288}
289
3979877e 290/* Inode operations in similar order to how they appear in Linux file fs.h */
1da177e4
LT
291
292int
293cifs_create(struct inode *inode, struct dentry *direntry, int mode,
294 struct nameidata *nd)
295{
296 int rc = -ENOENT;
297 int xid;
67750fb9 298 int create_options = CREATE_NOT_DIR;
590a3fe0 299 __u32 oplock = 0;
c3b2a0c6 300 int oflags;
90e4ee5d 301 bool posix_create = false;
c3b2a0c6
SF
302 /*
303 * BB below access is probably too much for mknod to request
304 * but we have to do query and setpathinfo so requesting
305 * less could fail (unless we want to request getatr and setatr
306 * permissions (only). At least for POSIX we do not have to
307 * request so much.
308 */
1da177e4
LT
309 int desiredAccess = GENERIC_READ | GENERIC_WRITE;
310 __u16 fileHandle;
311 struct cifs_sb_info *cifs_sb;
f818dd55 312 struct cifsTconInfo *tcon;
1da177e4 313 char *full_path = NULL;
fb8c4b14 314 FILE_ALL_INFO *buf = NULL;
1da177e4 315 struct inode *newinode = NULL;
1da177e4 316 int disposition = FILE_OVERWRITE_IF;
1da177e4
LT
317
318 xid = GetXid();
319
320 cifs_sb = CIFS_SB(inode->i_sb);
f818dd55 321 tcon = cifs_sb->tcon;
1da177e4 322
1da177e4 323 full_path = build_path_from_dentry(direntry);
5fdae1f6 324 if (full_path == NULL) {
0f3bc09e 325 rc = -ENOMEM;
1da177e4 326 FreeXid(xid);
0f3bc09e 327 return rc;
1da177e4
LT
328 }
329
c3b2a0c6
SF
330 if (oplockEnabled)
331 oplock = REQ_OPLOCK;
f818dd55 332
c3b2a0c6
SF
333 if (nd && (nd->flags & LOOKUP_OPEN))
334 oflags = nd->intent.open.flags;
335 else
fa588e0c 336 oflags = FMODE_READ | SMB_O_CREAT;
c3b2a0c6
SF
337
338 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
339 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
340 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
fa588e0c
SF
341 rc = cifs_posix_open(full_path, &newinode,
342 nd ? nd->path.mnt : NULL,
343 inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
c3b2a0c6
SF
344 /* EIO could indicate that (posix open) operation is not
345 supported, despite what server claimed in capability
346 negotation. EREMOTE indicates DFS junction, which is not
347 handled in posix open */
348
90e4ee5d
SF
349 if (rc == 0) {
350 posix_create = true;
351 if (newinode == NULL) /* query inode info */
352 goto cifs_create_get_file_info;
353 else /* success, no need to query */
354 goto cifs_create_set_dentry;
355 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
703a3b8e 356 (rc != -EOPNOTSUPP) && (rc != -EINVAL))
c3b2a0c6
SF
357 goto cifs_create_out;
358 /* else fallthrough to retry, using older open call, this is
359 case where server does not support this SMB level, and
360 falsely claims capability (also get here for DFS case
361 which should be rare for path not covered on files) */
362 }
e08fc045 363
c3b2a0c6
SF
364 if (nd && (nd->flags & LOOKUP_OPEN)) {
365 /* if the file is going to stay open, then we
366 need to set the desired access properly */
e08fc045
MS
367 desiredAccess = 0;
368 if (oflags & FMODE_READ)
c3b2a0c6 369 desiredAccess |= GENERIC_READ; /* is this too little? */
086f68bd 370 if (oflags & FMODE_WRITE)
e08fc045 371 desiredAccess |= GENERIC_WRITE;
1da177e4 372
5fdae1f6 373 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
1da177e4 374 disposition = FILE_CREATE;
5fdae1f6 375 else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
1da177e4 376 disposition = FILE_OVERWRITE_IF;
5fdae1f6 377 else if ((oflags & O_CREAT) == O_CREAT)
1da177e4 378 disposition = FILE_OPEN_IF;
ad7a2926 379 else
b6b38f70 380 cFYI(1, "Create flag not set in create function");
1da177e4
LT
381 }
382
5fdae1f6
SF
383 /* BB add processing to set equivalent of mode - e.g. via CreateX with
384 ACLs */
1da177e4 385
5fdae1f6
SF
386 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
387 if (buf == NULL) {
1da177e4
LT
388 kfree(full_path);
389 FreeXid(xid);
390 return -ENOMEM;
391 }
67750fb9 392
67750fb9
JL
393 /*
394 * if we're not using unix extensions, see if we need to set
395 * ATTR_READONLY on the create call
396 */
f818dd55 397 if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
67750fb9
JL
398 create_options |= CREATE_OPTION_READONLY;
399
5fdae1f6 400 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
f818dd55 401 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
67750fb9 402 desiredAccess, create_options,
737b758c
SF
403 &fileHandle, &oplock, buf, cifs_sb->local_nls,
404 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
5bafd765
SF
405 else
406 rc = -EIO; /* no NT SMB support fall into legacy open below */
407
5fdae1f6 408 if (rc == -EIO) {
a9d02ad4 409 /* old server, retry the open legacy style */
f818dd55 410 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
67750fb9 411 desiredAccess, create_options,
a9d02ad4
SF
412 &fileHandle, &oplock, buf, cifs_sb->local_nls,
413 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
5fdae1f6 414 }
1da177e4 415 if (rc) {
b6b38f70 416 cFYI(1, "cifs_create returned 0x%x", rc);
c3b2a0c6
SF
417 goto cifs_create_out;
418 }
419
420 /* If Open reported that we actually created a file
421 then we now have to set the mode if possible */
422 if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
423 struct cifs_unix_set_info_args args = {
4e1e7fb9
JL
424 .mode = mode,
425 .ctime = NO_CHANGE_64,
426 .atime = NO_CHANGE_64,
427 .mtime = NO_CHANGE_64,
428 .device = 0,
c3b2a0c6
SF
429 };
430
431 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
432 args.uid = (__u64) current_fsuid();
433 if (inode->i_mode & S_ISGID)
434 args.gid = (__u64) inode->i_gid;
435 else
436 args.gid = (__u64) current_fsgid();
3ce53fc4 437 } else {
c3b2a0c6
SF
438 args.uid = NO_CHANGE_64;
439 args.gid = NO_CHANGE_64;
1da177e4 440 }
01ea95e3
JL
441 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
442 cifs_sb->local_nls,
443 cifs_sb->mnt_cifs_flags &
444 CIFS_MOUNT_MAP_SPECIAL_CHR);
c3b2a0c6
SF
445 } else {
446 /* BB implement mode setting via Windows security
447 descriptors e.g. */
448 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
449
450 /* Could set r/o dos attribute if mode & 0222 == 0 */
451 }
1da177e4 452
c3b2a0c6
SF
453cifs_create_get_file_info:
454 /* server might mask mode so we have to query for it */
455 if (tcon->unix_ext)
456 rc = cifs_get_inode_info_unix(&newinode, full_path,
457 inode->i_sb, xid);
458 else {
459 rc = cifs_get_inode_info(&newinode, full_path, buf,
460 inode->i_sb, xid, &fileHandle);
461 if (newinode) {
462 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
463 newinode->i_mode = mode;
464 if ((oplock & CIFS_CREATE_ACTION) &&
465 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
466 newinode->i_uid = current_fsuid();
467 if (inode->i_mode & S_ISGID)
468 newinode->i_gid = inode->i_gid;
469 else
470 newinode->i_gid = current_fsgid();
6473a559 471 }
1da177e4 472 }
c3b2a0c6 473 }
1da177e4 474
c3b2a0c6
SF
475cifs_create_set_dentry:
476 if (rc == 0)
477 setup_cifs_dentry(tcon, direntry, newinode);
478 else
b6b38f70 479 cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
c3b2a0c6
SF
480
481 /* nfsd case - nfs srv does not set nd */
482 if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
483 /* mknod case - do not leave file open */
484 CIFSSMBClose(xid, tcon, fileHandle);
90e4ee5d 485 } else if (!(posix_create) && (newinode)) {
fdb36038 486 struct cifsFileInfo *pfile_info;
fae683f7
SJ
487 /*
488 * cifs_fill_filedata() takes care of setting cifsFileInfo
489 * pointer to file->private_data.
490 */
fdb36038
SJ
491 pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL,
492 nd->path.mnt, oflags);
493 if (pfile_info == NULL)
494 rc = -ENOMEM;
5fdae1f6 495 }
d14537f1
SF
496cifs_create_out:
497 kfree(buf);
498 kfree(full_path);
1da177e4 499 FreeXid(xid);
1da177e4
LT
500 return rc;
501}
502
5fdae1f6
SF
503int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
504 dev_t device_number)
1da177e4
LT
505{
506 int rc = -EPERM;
507 int xid;
508 struct cifs_sb_info *cifs_sb;
509 struct cifsTconInfo *pTcon;
510 char *full_path = NULL;
fb8c4b14 511 struct inode *newinode = NULL;
1da177e4
LT
512
513 if (!old_valid_dev(device_number))
514 return -EINVAL;
515
516 xid = GetXid();
517
518 cifs_sb = CIFS_SB(inode->i_sb);
519 pTcon = cifs_sb->tcon;
520
1da177e4 521 full_path = build_path_from_dentry(direntry);
5fdae1f6 522 if (full_path == NULL)
1da177e4 523 rc = -ENOMEM;
c18c842b 524 else if (pTcon->unix_ext) {
4e1e7fb9 525 struct cifs_unix_set_info_args args = {
ce3b0f8d 526 .mode = mode & ~current_umask(),
4e1e7fb9
JL
527 .ctime = NO_CHANGE_64,
528 .atime = NO_CHANGE_64,
529 .mtime = NO_CHANGE_64,
530 .device = device_number,
531 };
5fdae1f6 532 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
a001e5b5
DH
533 args.uid = (__u64) current_fsuid();
534 args.gid = (__u64) current_fsgid();
1da177e4 535 } else {
4e1e7fb9
JL
536 args.uid = NO_CHANGE_64;
537 args.gid = NO_CHANGE_64;
1da177e4 538 }
01ea95e3
JL
539 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
540 cifs_sb->local_nls,
541 cifs_sb->mnt_cifs_flags &
542 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4 543
5fdae1f6 544 if (!rc) {
1da177e4 545 rc = cifs_get_inode_info_unix(&newinode, full_path,
5fdae1f6 546 inode->i_sb, xid);
b92327fe
SF
547 if (pTcon->nocase)
548 direntry->d_op = &cifs_ci_dentry_ops;
549 else
550 direntry->d_op = &cifs_dentry_ops;
5fdae1f6 551 if (rc == 0)
1da177e4
LT
552 d_instantiate(direntry, newinode);
553 }
d7245c2c 554 } else {
5fdae1f6 555 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
eda3c029
SF
556 int oplock = 0;
557 u16 fileHandle;
ad7a2926 558 FILE_ALL_INFO *buf;
d7245c2c 559
b6b38f70 560 cFYI(1, "sfu compat create special file");
d7245c2c 561
5fdae1f6
SF
562 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
563 if (buf == NULL) {
eda3c029 564 kfree(full_path);
0f3bc09e 565 rc = -ENOMEM;
eda3c029 566 FreeXid(xid);
0f3bc09e 567 return rc;
eda3c029
SF
568 }
569
570 rc = CIFSSMBOpen(xid, pTcon, full_path,
571 FILE_CREATE, /* fail if exists */
5fdae1f6 572 GENERIC_WRITE /* BB would
eda3c029
SF
573 WRITE_OWNER | WRITE_DAC be better? */,
574 /* Create a file and set the
575 file attribute to SYSTEM */
576 CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
577 &fileHandle, &oplock, buf,
578 cifs_sb->local_nls,
5fdae1f6 579 cifs_sb->mnt_cifs_flags &
eda3c029
SF
580 CIFS_MOUNT_MAP_SPECIAL_CHR);
581
5bafd765
SF
582 /* BB FIXME - add handling for backlevel servers
583 which need legacy open and check for all
5fdae1f6
SF
584 calls to SMBOpen for fallback to SMBLeagcyOpen */
585 if (!rc) {
eda3c029 586 /* BB Do not bother to decode buf since no
86c96b4b
SF
587 local inode yet to put timestamps in,
588 but we can reuse it safely */
77159b4d 589 unsigned int bytes_written;
86c96b4b
SF
590 struct win_dev *pdev;
591 pdev = (struct win_dev *)buf;
5fdae1f6 592 if (S_ISCHR(mode)) {
86c96b4b
SF
593 memcpy(pdev->type, "IntxCHR", 8);
594 pdev->major =
595 cpu_to_le64(MAJOR(device_number));
5fdae1f6 596 pdev->minor =
86c96b4b
SF
597 cpu_to_le64(MINOR(device_number));
598 rc = CIFSSMBWrite(xid, pTcon,
599 fileHandle,
600 sizeof(struct win_dev),
601 0, &bytes_written, (char *)pdev,
602 NULL, 0);
5fdae1f6 603 } else if (S_ISBLK(mode)) {
86c96b4b
SF
604 memcpy(pdev->type, "IntxBLK", 8);
605 pdev->major =
606 cpu_to_le64(MAJOR(device_number));
607 pdev->minor =
608 cpu_to_le64(MINOR(device_number));
609 rc = CIFSSMBWrite(xid, pTcon,
610 fileHandle,
611 sizeof(struct win_dev),
612 0, &bytes_written, (char *)pdev,
613 NULL, 0);
614 } /* else if(S_ISFIFO */
eda3c029
SF
615 CIFSSMBClose(xid, pTcon, fileHandle);
616 d_drop(direntry);
617 }
618 kfree(buf);
d7245c2c
SF
619 /* add code here to set EAs */
620 }
1da177e4
LT
621 }
622
d14537f1 623 kfree(full_path);
1da177e4 624 FreeXid(xid);
1da177e4
LT
625 return rc;
626}
627
1da177e4 628struct dentry *
5fdae1f6
SF
629cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
630 struct nameidata *nd)
1da177e4
LT
631{
632 int xid;
633 int rc = 0; /* to get around spurious gcc warning, set to zero here */
590a3fe0 634 __u32 oplock = 0;
a6ce4932
SF
635 __u16 fileHandle = 0;
636 bool posix_open = false;
1da177e4
LT
637 struct cifs_sb_info *cifs_sb;
638 struct cifsTconInfo *pTcon;
639 struct inode *newInode = NULL;
640 char *full_path = NULL;
a6ce4932 641 struct file *filp;
1da177e4
LT
642
643 xid = GetXid();
644
b6b38f70
JP
645 cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
646 parent_dir_inode, direntry->d_name.name, direntry);
1da177e4 647
1da177e4
LT
648 /* check whether path exists */
649
650 cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
651 pTcon = cifs_sb->tcon;
652
296034f7
SF
653 /*
654 * Don't allow the separator character in a path component.
655 * The VFS will not allow "/", but "\" is allowed by posix.
656 */
657 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
658 int i;
659 for (i = 0; i < direntry->d_name.len; i++)
660 if (direntry->d_name.name[i] == '\\') {
b6b38f70 661 cFYI(1, "Invalid file name");
296034f7
SF
662 FreeXid(xid);
663 return ERR_PTR(-EINVAL);
664 }
665 }
666
5ddf1e0f
JL
667 /*
668 * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
669 * the VFS handle the create.
670 */
8e6c0332 671 if (nd && (nd->flags & LOOKUP_EXCL)) {
5ddf1e0f 672 d_instantiate(direntry, NULL);
2f81e752 673 return NULL;
5ddf1e0f
JL
674 }
675
1da177e4
LT
676 /* can not grab the rename sem here since it would
677 deadlock in the cases (beginning of sys_rename itself)
678 in which we already have the sb rename sem */
679 full_path = build_path_from_dentry(direntry);
5fdae1f6 680 if (full_path == NULL) {
1da177e4
LT
681 FreeXid(xid);
682 return ERR_PTR(-ENOMEM);
683 }
684
685 if (direntry->d_inode != NULL) {
b6b38f70 686 cFYI(1, "non-NULL inode in lookup");
1da177e4 687 } else {
b6b38f70 688 cFYI(1, "NULL inode in lookup");
1da177e4 689 }
b6b38f70 690 cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
1da177e4 691
8db14ca1
SF
692 /* Posix open is only called (at lookup time) for file create now.
693 * For opens (rather than creates), because we do not know if it
694 * is a file or directory yet, and current Samba no longer allows
695 * us to do posix open on dirs, we could end up wasting an open call
696 * on what turns out to be a dir. For file opens, we wait to call posix
697 * open till cifs_open. It could be added here (lookup) in the future
698 * but the performance tradeoff of the extra network request when EISDIR
699 * or EACCES is returned would have to be weighed against the 50%
700 * reduction in network traffic in the other paths.
701 */
a6ce4932 702 if (pTcon->unix_ext) {
8e6c0332 703 if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
8db14ca1
SF
704 (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
705 (nd->intent.open.flags & O_CREAT)) {
3bc303c2 706 rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
fa588e0c 707 parent_dir_inode->i_sb,
703a3b8e 708 nd->intent.open.create_mode,
a6ce4932
SF
709 nd->intent.open.flags, &oplock,
710 &fileHandle, xid);
8db14ca1
SF
711 /*
712 * The check below works around a bug in POSIX
713 * open in samba versions 3.3.1 and earlier where
714 * open could incorrectly fail with invalid parameter.
715 * If either that or op not supported returned, follow
716 * the normal lookup.
717 */
718 if ((rc == 0) || (rc == -ENOENT))
719 posix_open = true;
720 else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
721 pTcon->broken_posix_open = true;
a6ce4932
SF
722 }
723 if (!posix_open)
724 rc = cifs_get_inode_info_unix(&newInode, full_path,
725 parent_dir_inode->i_sb, xid);
726 } else
1da177e4 727 rc = cifs_get_inode_info(&newInode, full_path, NULL,
a6ce4932 728 parent_dir_inode->i_sb, xid, NULL);
1da177e4
LT
729
730 if ((rc == 0) && (newInode != NULL)) {
b92327fe
SF
731 if (pTcon->nocase)
732 direntry->d_op = &cifs_ci_dentry_ops;
733 else
734 direntry->d_op = &cifs_dentry_ops;
1da177e4 735 d_add(direntry, newInode);
a6ce4932
SF
736 if (posix_open)
737 filp = lookup_instantiate_filp(nd, direntry, NULL);
5fdae1f6 738 /* since paths are not looked up by component - the parent
3abb9272 739 directories are presumed to be good here */
1da177e4
LT
740 renew_parental_timestamps(direntry);
741
742 } else if (rc == -ENOENT) {
743 rc = 0;
3abb9272
SF
744 direntry->d_time = jiffies;
745 if (pTcon->nocase)
746 direntry->d_op = &cifs_ci_dentry_ops;
747 else
748 direntry->d_op = &cifs_dentry_ops;
1da177e4 749 d_add(direntry, NULL);
5fdae1f6
SF
750 /* if it was once a directory (but how can we tell?) we could do
751 shrink_dcache_parent(direntry); */
ed2b9170 752 } else if (rc != -EACCES) {
b6b38f70 753 cERROR(1, "Unexpected lookup error %d", rc);
ed2b9170
SF
754 /* We special case check for Access Denied - since that
755 is a common return code */
1da177e4
LT
756 }
757
d14537f1 758 kfree(full_path);
1da177e4
LT
759 FreeXid(xid);
760 return ERR_PTR(rc);
761}
762
1da177e4
LT
763static int
764cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
765{
766 int isValid = 1;
767
1da177e4 768 if (direntry->d_inode) {
df2cf170 769 if (cifs_revalidate_dentry(direntry))
1da177e4 770 return 0;
1da177e4 771 } else {
b6b38f70
JP
772 cFYI(1, "neg dentry 0x%p name = %s",
773 direntry, direntry->d_name.name);
5fdae1f6 774 if (time_after(jiffies, direntry->d_time + HZ) ||
3abb9272
SF
775 !lookupCacheEnabled) {
776 d_drop(direntry);
777 isValid = 0;
5fdae1f6 778 }
1da177e4
LT
779 }
780
1da177e4
LT
781 return isValid;
782}
783
784/* static int cifs_d_delete(struct dentry *direntry)
785{
786 int rc = 0;
787
b6b38f70 788 cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
1da177e4
LT
789
790 return rc;
791} */
792
4fd03e84 793const struct dentry_operations cifs_dentry_ops = {
1da177e4 794 .d_revalidate = cifs_d_revalidate,
5fdae1f6 795/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
1da177e4 796};
b92327fe
SF
797
798static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
799{
800 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
801 unsigned long hash;
802 int i;
803
804 hash = init_name_hash();
805 for (i = 0; i < q->len; i++)
806 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
807 hash);
808 q->hash = end_name_hash(hash);
809
810 return 0;
811}
812
813static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
814 struct qstr *b)
815{
816 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
817
818 if ((a->len == b->len) &&
819 (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
820 /*
821 * To preserve case, don't let an existing negative dentry's
822 * case take precedence. If a is not a negative dentry, this
823 * should have no side effects
824 */
c3291637 825 memcpy((void *)a->name, b->name, a->len);
b92327fe
SF
826 return 0;
827 }
828 return 1;
829}
830
4fd03e84 831const struct dentry_operations cifs_ci_dentry_ops = {
b92327fe
SF
832 .d_revalidate = cifs_d_revalidate,
833 .d_hash = cifs_ci_hash,
834 .d_compare = cifs_ci_compare,
835};