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