Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide-2.6
[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
192         cFYI(1, ("posix open %s", full_path));
193
194         presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
195         if (presp_data == NULL)
196                 return -ENOMEM;
197
198 /* So far cifs posix extensions can only map the following flags.
199    There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
200    so far we do not seem to need them, and we can treat them as local only */
201         if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
202                 (FMODE_READ | FMODE_WRITE))
203                 posix_flags = SMB_O_RDWR;
204         else if (oflags & FMODE_READ)
205                 posix_flags = SMB_O_RDONLY;
206         else if (oflags & FMODE_WRITE)
207                 posix_flags = SMB_O_WRONLY;
208         if (oflags & O_CREAT)
209                 posix_flags |= SMB_O_CREAT;
210         if (oflags & O_EXCL)
211                 posix_flags |= SMB_O_EXCL;
212         if (oflags & O_TRUNC)
213                 posix_flags |= SMB_O_TRUNC;
214         if (oflags & O_APPEND)
215                 posix_flags |= SMB_O_APPEND;
216         if (oflags & O_SYNC)
217                 posix_flags |= SMB_O_SYNC;
218         if (oflags & O_DIRECTORY)
219                 posix_flags |= SMB_O_DIRECTORY;
220         if (oflags & O_NOFOLLOW)
221                 posix_flags |= SMB_O_NOFOLLOW;
222         if (oflags & O_DIRECT)
223                 posix_flags |= SMB_O_DIRECT;
224
225         if (!(oflags & FMODE_READ))
226                 write_only = true;
227
228         mode &= ~current_umask();
229         rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
230                         pnetfid, presp_data, &oplock, full_path,
231                         cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
232                                         CIFS_MOUNT_MAP_SPECIAL_CHR);
233         if (rc)
234                 goto posix_open_ret;
235
236         if (presp_data->Type == cpu_to_le32(-1))
237                 goto posix_open_ret; /* open ok, caller does qpathinfo */
238
239         /* get new inode and set it up */
240         if (!pinode)
241                 goto posix_open_ret; /* caller does not need info */
242
243         if (*pinode == NULL) {
244                 __u64 unique_id = le64_to_cpu(presp_data->UniqueId);
245                 *pinode = cifs_new_inode(sb, &unique_id);
246         }
247         /* else an inode was passed in. Update its info, don't create one */
248
249         /* We do not need to close the file if new_inode fails since
250            the caller will retry qpathinfo as long as inode is null */
251         if (*pinode == NULL)
252                 goto posix_open_ret;
253
254         posix_fill_in_inode(*pinode, presp_data, 1);
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                 CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
429                         cifs_sb->local_nls,
430                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
431         } else {
432                 /* BB implement mode setting via Windows security
433                    descriptors e.g. */
434                 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
435
436                 /* Could set r/o dos attribute if mode & 0222 == 0 */
437         }
438
439 cifs_create_get_file_info:
440         /* server might mask mode so we have to query for it */
441         if (tcon->unix_ext)
442                 rc = cifs_get_inode_info_unix(&newinode, full_path,
443                                               inode->i_sb, xid);
444         else {
445                 rc = cifs_get_inode_info(&newinode, full_path, buf,
446                                          inode->i_sb, xid, &fileHandle);
447                 if (newinode) {
448                         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
449                                 newinode->i_mode = mode;
450                         if ((oplock & CIFS_CREATE_ACTION) &&
451                             (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
452                                 newinode->i_uid = current_fsuid();
453                                 if (inode->i_mode & S_ISGID)
454                                         newinode->i_gid = inode->i_gid;
455                                 else
456                                         newinode->i_gid = current_fsgid();
457                         }
458                 }
459         }
460
461 cifs_create_set_dentry:
462         if (rc == 0)
463                 setup_cifs_dentry(tcon, direntry, newinode);
464         else
465                 cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc));
466
467         /* nfsd case - nfs srv does not set nd */
468         if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
469                 /* mknod case - do not leave file open */
470                 CIFSSMBClose(xid, tcon, fileHandle);
471         } else if (!(posix_create) && (newinode)) {
472                         cifs_fill_fileinfo(newinode, fileHandle,
473                                         cifs_sb->tcon, write_only);
474         }
475 cifs_create_out:
476         kfree(buf);
477         kfree(full_path);
478         FreeXid(xid);
479         return rc;
480 }
481
482 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
483                 dev_t device_number)
484 {
485         int rc = -EPERM;
486         int xid;
487         struct cifs_sb_info *cifs_sb;
488         struct cifsTconInfo *pTcon;
489         char *full_path = NULL;
490         struct inode *newinode = NULL;
491
492         if (!old_valid_dev(device_number))
493                 return -EINVAL;
494
495         xid = GetXid();
496
497         cifs_sb = CIFS_SB(inode->i_sb);
498         pTcon = cifs_sb->tcon;
499
500         full_path = build_path_from_dentry(direntry);
501         if (full_path == NULL)
502                 rc = -ENOMEM;
503         else if (pTcon->unix_ext) {
504                 struct cifs_unix_set_info_args args = {
505                         .mode   = mode & ~current_umask(),
506                         .ctime  = NO_CHANGE_64,
507                         .atime  = NO_CHANGE_64,
508                         .mtime  = NO_CHANGE_64,
509                         .device = device_number,
510                 };
511                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
512                         args.uid = (__u64) current_fsuid();
513                         args.gid = (__u64) current_fsgid();
514                 } else {
515                         args.uid = NO_CHANGE_64;
516                         args.gid = NO_CHANGE_64;
517                 }
518                 rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path,
519                         &args, cifs_sb->local_nls,
520                         cifs_sb->mnt_cifs_flags &
521                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
522
523                 if (!rc) {
524                         rc = cifs_get_inode_info_unix(&newinode, full_path,
525                                                 inode->i_sb, xid);
526                         if (pTcon->nocase)
527                                 direntry->d_op = &cifs_ci_dentry_ops;
528                         else
529                                 direntry->d_op = &cifs_dentry_ops;
530                         if (rc == 0)
531                                 d_instantiate(direntry, newinode);
532                 }
533         } else {
534                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
535                         int oplock = 0;
536                         u16 fileHandle;
537                         FILE_ALL_INFO *buf;
538
539                         cFYI(1, ("sfu compat create special file"));
540
541                         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
542                         if (buf == NULL) {
543                                 kfree(full_path);
544                                 rc = -ENOMEM;
545                                 FreeXid(xid);
546                                 return rc;
547                         }
548
549                         rc = CIFSSMBOpen(xid, pTcon, full_path,
550                                          FILE_CREATE, /* fail if exists */
551                                          GENERIC_WRITE /* BB would
552                                           WRITE_OWNER | WRITE_DAC be better? */,
553                                          /* Create a file and set the
554                                             file attribute to SYSTEM */
555                                          CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
556                                          &fileHandle, &oplock, buf,
557                                          cifs_sb->local_nls,
558                                          cifs_sb->mnt_cifs_flags &
559                                             CIFS_MOUNT_MAP_SPECIAL_CHR);
560
561                         /* BB FIXME - add handling for backlevel servers
562                            which need legacy open and check for all
563                            calls to SMBOpen for fallback to SMBLeagcyOpen */
564                         if (!rc) {
565                                 /* BB Do not bother to decode buf since no
566                                    local inode yet to put timestamps in,
567                                    but we can reuse it safely */
568                                 unsigned int bytes_written;
569                                 struct win_dev *pdev;
570                                 pdev = (struct win_dev *)buf;
571                                 if (S_ISCHR(mode)) {
572                                         memcpy(pdev->type, "IntxCHR", 8);
573                                         pdev->major =
574                                               cpu_to_le64(MAJOR(device_number));
575                                         pdev->minor =
576                                               cpu_to_le64(MINOR(device_number));
577                                         rc = CIFSSMBWrite(xid, pTcon,
578                                                 fileHandle,
579                                                 sizeof(struct win_dev),
580                                                 0, &bytes_written, (char *)pdev,
581                                                 NULL, 0);
582                                 } else if (S_ISBLK(mode)) {
583                                         memcpy(pdev->type, "IntxBLK", 8);
584                                         pdev->major =
585                                               cpu_to_le64(MAJOR(device_number));
586                                         pdev->minor =
587                                               cpu_to_le64(MINOR(device_number));
588                                         rc = CIFSSMBWrite(xid, pTcon,
589                                                 fileHandle,
590                                                 sizeof(struct win_dev),
591                                                 0, &bytes_written, (char *)pdev,
592                                                 NULL, 0);
593                                 } /* else if(S_ISFIFO */
594                                 CIFSSMBClose(xid, pTcon, fileHandle);
595                                 d_drop(direntry);
596                         }
597                         kfree(buf);
598                         /* add code here to set EAs */
599                 }
600         }
601
602         kfree(full_path);
603         FreeXid(xid);
604         return rc;
605 }
606
607 struct dentry *
608 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
609             struct nameidata *nd)
610 {
611         int xid;
612         int rc = 0; /* to get around spurious gcc warning, set to zero here */
613         int oplock = 0;
614         __u16 fileHandle = 0;
615         bool posix_open = false;
616         struct cifs_sb_info *cifs_sb;
617         struct cifsTconInfo *pTcon;
618         struct inode *newInode = NULL;
619         char *full_path = NULL;
620         struct file *filp;
621
622         xid = GetXid();
623
624         cFYI(1, ("parent inode = 0x%p name is: %s and dentry = 0x%p",
625               parent_dir_inode, direntry->d_name.name, direntry));
626
627         /* check whether path exists */
628
629         cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
630         pTcon = cifs_sb->tcon;
631
632         /*
633          * Don't allow the separator character in a path component.
634          * The VFS will not allow "/", but "\" is allowed by posix.
635          */
636         if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
637                 int i;
638                 for (i = 0; i < direntry->d_name.len; i++)
639                         if (direntry->d_name.name[i] == '\\') {
640                                 cFYI(1, ("Invalid file name"));
641                                 FreeXid(xid);
642                                 return ERR_PTR(-EINVAL);
643                         }
644         }
645
646         /* can not grab the rename sem here since it would
647         deadlock in the cases (beginning of sys_rename itself)
648         in which we already have the sb rename sem */
649         full_path = build_path_from_dentry(direntry);
650         if (full_path == NULL) {
651                 FreeXid(xid);
652                 return ERR_PTR(-ENOMEM);
653         }
654
655         if (direntry->d_inode != NULL) {
656                 cFYI(1, ("non-NULL inode in lookup"));
657         } else {
658                 cFYI(1, ("NULL inode in lookup"));
659         }
660         cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
661
662         /* Posix open is only called (at lookup time) for file create now.
663          * For opens (rather than creates), because we do not know if it
664          * is a file or directory yet, and current Samba no longer allows
665          * us to do posix open on dirs, we could end up wasting an open call
666          * on what turns out to be a dir. For file opens, we wait to call posix
667          * open till cifs_open.  It could be added here (lookup) in the future
668          * but the performance tradeoff of the extra network request when EISDIR
669          * or EACCES is returned would have to be weighed against the 50%
670          * reduction in network traffic in the other paths.
671          */
672         if (pTcon->unix_ext) {
673                 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
674                      (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
675                      (nd->intent.open.flags & O_CREAT)) {
676                         rc = cifs_posix_open(full_path, &newInode,
677                                         parent_dir_inode->i_sb,
678                                         nd->intent.open.create_mode,
679                                         nd->intent.open.flags, &oplock,
680                                         &fileHandle, xid);
681                         /*
682                          * The check below works around a bug in POSIX
683                          * open in samba versions 3.3.1 and earlier where
684                          * open could incorrectly fail with invalid parameter.
685                          * If either that or op not supported returned, follow
686                          * the normal lookup.
687                          */
688                         if ((rc == 0) || (rc == -ENOENT))
689                                 posix_open = true;
690                         else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
691                                 pTcon->broken_posix_open = true;
692                 }
693                 if (!posix_open)
694                         rc = cifs_get_inode_info_unix(&newInode, full_path,
695                                                 parent_dir_inode->i_sb, xid);
696         } else
697                 rc = cifs_get_inode_info(&newInode, full_path, NULL,
698                                 parent_dir_inode->i_sb, xid, NULL);
699
700         if ((rc == 0) && (newInode != NULL)) {
701                 if (pTcon->nocase)
702                         direntry->d_op = &cifs_ci_dentry_ops;
703                 else
704                         direntry->d_op = &cifs_dentry_ops;
705                 d_add(direntry, newInode);
706                 if (posix_open)
707                         filp = lookup_instantiate_filp(nd, direntry, NULL);
708                 /* since paths are not looked up by component - the parent
709                    directories are presumed to be good here */
710                 renew_parental_timestamps(direntry);
711
712         } else if (rc == -ENOENT) {
713                 rc = 0;
714                 direntry->d_time = jiffies;
715                 if (pTcon->nocase)
716                         direntry->d_op = &cifs_ci_dentry_ops;
717                 else
718                         direntry->d_op = &cifs_dentry_ops;
719                 d_add(direntry, NULL);
720         /*      if it was once a directory (but how can we tell?) we could do
721                 shrink_dcache_parent(direntry); */
722         } else if (rc != -EACCES) {
723                 cERROR(1, ("Unexpected lookup error %d", rc));
724                 /* We special case check for Access Denied - since that
725                 is a common return code */
726         }
727
728         kfree(full_path);
729         FreeXid(xid);
730         return ERR_PTR(rc);
731 }
732
733 static int
734 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
735 {
736         int isValid = 1;
737
738         if (direntry->d_inode) {
739                 if (cifs_revalidate(direntry))
740                         return 0;
741         } else {
742                 cFYI(1, ("neg dentry 0x%p name = %s",
743                          direntry, direntry->d_name.name));
744                 if (time_after(jiffies, direntry->d_time + HZ) ||
745                         !lookupCacheEnabled) {
746                         d_drop(direntry);
747                         isValid = 0;
748                 }
749         }
750
751         return isValid;
752 }
753
754 /* static int cifs_d_delete(struct dentry *direntry)
755 {
756         int rc = 0;
757
758         cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
759
760         return rc;
761 }     */
762
763 const struct dentry_operations cifs_dentry_ops = {
764         .d_revalidate = cifs_d_revalidate,
765 /* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
766 };
767
768 static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
769 {
770         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
771         unsigned long hash;
772         int i;
773
774         hash = init_name_hash();
775         for (i = 0; i < q->len; i++)
776                 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
777                                          hash);
778         q->hash = end_name_hash(hash);
779
780         return 0;
781 }
782
783 static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
784                            struct qstr *b)
785 {
786         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
787
788         if ((a->len == b->len) &&
789             (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
790                 /*
791                  * To preserve case, don't let an existing negative dentry's
792                  * case take precedence.  If a is not a negative dentry, this
793                  * should have no side effects
794                  */
795                 memcpy((void *)a->name, b->name, a->len);
796                 return 0;
797         }
798         return 1;
799 }
800
801 const struct dentry_operations cifs_ci_dentry_ops = {
802         .d_revalidate = cifs_d_revalidate,
803         .d_hash = cifs_ci_hash,
804         .d_compare = cifs_ci_compare,
805 };