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