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