[CIFS] Fix double list addition in cifs posix open code
[linux-2.6.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         rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
229                         pnetfid, presp_data, &oplock, 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         /* get new inode and set it up */
239         if (!pinode)
240                 goto posix_open_ret; /* caller does not need info */
241
242         if (*pinode == NULL) {
243                 __u64 unique_id = le64_to_cpu(presp_data->UniqueId);
244                 *pinode = cifs_new_inode(sb, &unique_id);
245         }
246         /* else an inode was passed in. Update its info, don't create one */
247
248         /* We do not need to close the file if new_inode fails since
249            the caller will retry qpathinfo as long as inode is null */
250         if (*pinode == NULL)
251                 goto posix_open_ret;
252
253         posix_fill_in_inode(*pinode, presp_data, 1);
254
255         cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only);
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         int 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         bool write_only = false;
301
302         xid = GetXid();
303
304         cifs_sb = CIFS_SB(inode->i_sb);
305         tcon = cifs_sb->tcon;
306
307         full_path = build_path_from_dentry(direntry);
308         if (full_path == NULL) {
309                 FreeXid(xid);
310                 return -ENOMEM;
311         }
312
313         mode &= ~current_umask();
314         if (oplockEnabled)
315                 oplock = REQ_OPLOCK;
316
317         if (nd && (nd->flags & LOOKUP_OPEN))
318                 oflags = nd->intent.open.flags;
319         else
320                 oflags = FMODE_READ;
321
322         if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
323             (CIFS_UNIX_POSIX_PATH_OPS_CAP &
324                         le64_to_cpu(tcon->fsUnixInfo.Capability))) {
325                 rc = cifs_posix_open(full_path, &newinode, inode->i_sb,
326                                      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)) /* path not found or net err */
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                         if (!(oflags & FMODE_READ))
356                                 write_only = true;
357                 }
358
359                 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
360                         disposition = FILE_CREATE;
361                 else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
362                         disposition = FILE_OVERWRITE_IF;
363                 else if ((oflags & O_CREAT) == O_CREAT)
364                         disposition = FILE_OPEN_IF;
365                 else
366                         cFYI(1, ("Create flag not set in create function"));
367         }
368
369         /* BB add processing to set equivalent of mode - e.g. via CreateX with
370            ACLs */
371
372         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
373         if (buf == NULL) {
374                 kfree(full_path);
375                 FreeXid(xid);
376                 return -ENOMEM;
377         }
378
379         /*
380          * if we're not using unix extensions, see if we need to set
381          * ATTR_READONLY on the create call
382          */
383         if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
384                 create_options |= CREATE_OPTION_READONLY;
385
386         if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
387                 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
388                          desiredAccess, create_options,
389                          &fileHandle, &oplock, buf, cifs_sb->local_nls,
390                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
391         else
392                 rc = -EIO; /* no NT SMB support fall into legacy open below */
393
394         if (rc == -EIO) {
395                 /* old server, retry the open legacy style */
396                 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
397                         desiredAccess, create_options,
398                         &fileHandle, &oplock, buf, cifs_sb->local_nls,
399                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
400         }
401         if (rc) {
402                 cFYI(1, ("cifs_create returned 0x%x", rc));
403                 goto cifs_create_out;
404         }
405
406         /* If Open reported that we actually created a file
407            then we now have to set the mode if possible */
408         if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
409                 struct cifs_unix_set_info_args args = {
410                                 .mode   = mode,
411                                 .ctime  = NO_CHANGE_64,
412                                 .atime  = NO_CHANGE_64,
413                                 .mtime  = NO_CHANGE_64,
414                                 .device = 0,
415                 };
416
417                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
418                         args.uid = (__u64) current_fsuid();
419                         if (inode->i_mode & S_ISGID)
420                                 args.gid = (__u64) inode->i_gid;
421                         else
422                                 args.gid = (__u64) current_fsgid();
423                 } else {
424                         args.uid = NO_CHANGE_64;
425                         args.gid = NO_CHANGE_64;
426                 }
427                 CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
428                         cifs_sb->local_nls,
429                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
430         } else {
431                 /* BB implement mode setting via Windows security
432                    descriptors e.g. */
433                 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
434
435                 /* Could set r/o dos attribute if mode & 0222 == 0 */
436         }
437
438 cifs_create_get_file_info:
439         /* server might mask mode so we have to query for it */
440         if (tcon->unix_ext)
441                 rc = cifs_get_inode_info_unix(&newinode, full_path,
442                                               inode->i_sb, xid);
443         else {
444                 rc = cifs_get_inode_info(&newinode, full_path, buf,
445                                          inode->i_sb, xid, &fileHandle);
446                 if (newinode) {
447                         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
448                                 newinode->i_mode = mode;
449                         if ((oplock & CIFS_CREATE_ACTION) &&
450                             (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
451                                 newinode->i_uid = current_fsuid();
452                                 if (inode->i_mode & S_ISGID)
453                                         newinode->i_gid = inode->i_gid;
454                                 else
455                                         newinode->i_gid = current_fsgid();
456                         }
457                 }
458         }
459
460 cifs_create_set_dentry:
461         if (rc == 0)
462                 setup_cifs_dentry(tcon, direntry, newinode);
463         else
464                 cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc));
465
466         /* nfsd case - nfs srv does not set nd */
467         if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
468                 /* mknod case - do not leave file open */
469                 CIFSSMBClose(xid, tcon, fileHandle);
470         } else if (!(posix_create) && (newinode)) {
471                         cifs_fill_fileinfo(newinode, fileHandle,
472                                         cifs_sb->tcon, write_only);
473         }
474 cifs_create_out:
475         kfree(buf);
476         kfree(full_path);
477         FreeXid(xid);
478         return rc;
479 }
480
481 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
482                 dev_t device_number)
483 {
484         int rc = -EPERM;
485         int xid;
486         struct cifs_sb_info *cifs_sb;
487         struct cifsTconInfo *pTcon;
488         char *full_path = NULL;
489         struct inode *newinode = NULL;
490
491         if (!old_valid_dev(device_number))
492                 return -EINVAL;
493
494         xid = GetXid();
495
496         cifs_sb = CIFS_SB(inode->i_sb);
497         pTcon = cifs_sb->tcon;
498
499         full_path = build_path_from_dentry(direntry);
500         if (full_path == NULL)
501                 rc = -ENOMEM;
502         else if (pTcon->unix_ext) {
503                 struct cifs_unix_set_info_args args = {
504                         .mode   = mode & ~current_umask(),
505                         .ctime  = NO_CHANGE_64,
506                         .atime  = NO_CHANGE_64,
507                         .mtime  = NO_CHANGE_64,
508                         .device = device_number,
509                 };
510                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
511                         args.uid = (__u64) current_fsuid();
512                         args.gid = (__u64) current_fsgid();
513                 } else {
514                         args.uid = NO_CHANGE_64;
515                         args.gid = NO_CHANGE_64;
516                 }
517                 rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path,
518                         &args, cifs_sb->local_nls,
519                         cifs_sb->mnt_cifs_flags &
520                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
521
522                 if (!rc) {
523                         rc = cifs_get_inode_info_unix(&newinode, full_path,
524                                                 inode->i_sb, xid);
525                         if (pTcon->nocase)
526                                 direntry->d_op = &cifs_ci_dentry_ops;
527                         else
528                                 direntry->d_op = &cifs_dentry_ops;
529                         if (rc == 0)
530                                 d_instantiate(direntry, newinode);
531                 }
532         } else {
533                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
534                         int oplock = 0;
535                         u16 fileHandle;
536                         FILE_ALL_INFO *buf;
537
538                         cFYI(1, ("sfu compat create special file"));
539
540                         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
541                         if (buf == NULL) {
542                                 kfree(full_path);
543                                 FreeXid(xid);
544                                 return -ENOMEM;
545                         }
546
547                         rc = CIFSSMBOpen(xid, pTcon, full_path,
548                                          FILE_CREATE, /* fail if exists */
549                                          GENERIC_WRITE /* BB would
550                                           WRITE_OWNER | WRITE_DAC be better? */,
551                                          /* Create a file and set the
552                                             file attribute to SYSTEM */
553                                          CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
554                                          &fileHandle, &oplock, buf,
555                                          cifs_sb->local_nls,
556                                          cifs_sb->mnt_cifs_flags &
557                                             CIFS_MOUNT_MAP_SPECIAL_CHR);
558
559                         /* BB FIXME - add handling for backlevel servers
560                            which need legacy open and check for all
561                            calls to SMBOpen for fallback to SMBLeagcyOpen */
562                         if (!rc) {
563                                 /* BB Do not bother to decode buf since no
564                                    local inode yet to put timestamps in,
565                                    but we can reuse it safely */
566                                 unsigned int bytes_written;
567                                 struct win_dev *pdev;
568                                 pdev = (struct win_dev *)buf;
569                                 if (S_ISCHR(mode)) {
570                                         memcpy(pdev->type, "IntxCHR", 8);
571                                         pdev->major =
572                                               cpu_to_le64(MAJOR(device_number));
573                                         pdev->minor =
574                                               cpu_to_le64(MINOR(device_number));
575                                         rc = CIFSSMBWrite(xid, pTcon,
576                                                 fileHandle,
577                                                 sizeof(struct win_dev),
578                                                 0, &bytes_written, (char *)pdev,
579                                                 NULL, 0);
580                                 } else if (S_ISBLK(mode)) {
581                                         memcpy(pdev->type, "IntxBLK", 8);
582                                         pdev->major =
583                                               cpu_to_le64(MAJOR(device_number));
584                                         pdev->minor =
585                                               cpu_to_le64(MINOR(device_number));
586                                         rc = CIFSSMBWrite(xid, pTcon,
587                                                 fileHandle,
588                                                 sizeof(struct win_dev),
589                                                 0, &bytes_written, (char *)pdev,
590                                                 NULL, 0);
591                                 } /* else if(S_ISFIFO */
592                                 CIFSSMBClose(xid, pTcon, fileHandle);
593                                 d_drop(direntry);
594                         }
595                         kfree(buf);
596                         /* add code here to set EAs */
597                 }
598         }
599
600         kfree(full_path);
601         FreeXid(xid);
602         return rc;
603 }
604
605 struct dentry *
606 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
607             struct nameidata *nd)
608 {
609         int xid;
610         int rc = 0; /* to get around spurious gcc warning, set to zero here */
611         int oplock = 0;
612         int mode;
613         __u16 fileHandle = 0;
614         bool posix_open = false;
615         struct cifs_sb_info *cifs_sb;
616         struct cifsTconInfo *pTcon;
617         struct inode *newInode = NULL;
618         char *full_path = NULL;
619         struct file *filp;
620
621         xid = GetXid();
622
623         cFYI(1, ("parent inode = 0x%p name is: %s and dentry = 0x%p",
624               parent_dir_inode, direntry->d_name.name, direntry));
625
626         /* check whether path exists */
627
628         cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
629         pTcon = cifs_sb->tcon;
630
631         /*
632          * Don't allow the separator character in a path component.
633          * The VFS will not allow "/", but "\" is allowed by posix.
634          */
635         if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
636                 int i;
637                 for (i = 0; i < direntry->d_name.len; i++)
638                         if (direntry->d_name.name[i] == '\\') {
639                                 cFYI(1, ("Invalid file name"));
640                                 FreeXid(xid);
641                                 return ERR_PTR(-EINVAL);
642                         }
643         }
644
645         /* can not grab the rename sem here since it would
646         deadlock in the cases (beginning of sys_rename itself)
647         in which we already have the sb rename sem */
648         full_path = build_path_from_dentry(direntry);
649         if (full_path == NULL) {
650                 FreeXid(xid);
651                 return ERR_PTR(-ENOMEM);
652         }
653
654         if (direntry->d_inode != NULL) {
655                 cFYI(1, ("non-NULL inode in lookup"));
656         } else {
657                 cFYI(1, ("NULL inode in lookup"));
658         }
659         cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
660
661         if (pTcon->unix_ext) {
662                 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
663                                 (nd->flags & LOOKUP_OPEN)) {
664                         if (!((nd->intent.open.flags & O_CREAT) &&
665                                         (nd->intent.open.flags & O_EXCL))) {
666                                 mode = nd->intent.open.create_mode &
667                                                 ~current_umask();
668                                 rc = cifs_posix_open(full_path, &newInode,
669                                         parent_dir_inode->i_sb, mode,
670                                         nd->intent.open.flags, &oplock,
671                                         &fileHandle, xid);
672                                 /*
673                                  * This code works around a bug in
674                                  * samba posix open in samba versions 3.3.1
675                                  * and earlier where create works
676                                  * but open fails with invalid parameter.
677                                  * If either of these error codes are
678                                  * returned, follow the normal lookup.
679                                  * Otherwise, the error during posix open
680                                  * is handled.
681                                  */
682                                 if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
683                                         posix_open = true;
684                         }
685                 }
686                 if (!posix_open)
687                         rc = cifs_get_inode_info_unix(&newInode, full_path,
688                                                 parent_dir_inode->i_sb, xid);
689         } else
690                 rc = cifs_get_inode_info(&newInode, full_path, NULL,
691                                 parent_dir_inode->i_sb, xid, NULL);
692
693         if ((rc == 0) && (newInode != NULL)) {
694                 if (pTcon->nocase)
695                         direntry->d_op = &cifs_ci_dentry_ops;
696                 else
697                         direntry->d_op = &cifs_dentry_ops;
698                 d_add(direntry, newInode);
699                 if (posix_open)
700                         filp = lookup_instantiate_filp(nd, direntry, NULL);
701                 /* since paths are not looked up by component - the parent
702                    directories are presumed to be good here */
703                 renew_parental_timestamps(direntry);
704
705         } else if (rc == -ENOENT) {
706                 rc = 0;
707                 direntry->d_time = jiffies;
708                 if (pTcon->nocase)
709                         direntry->d_op = &cifs_ci_dentry_ops;
710                 else
711                         direntry->d_op = &cifs_dentry_ops;
712                 d_add(direntry, NULL);
713         /*      if it was once a directory (but how can we tell?) we could do
714                 shrink_dcache_parent(direntry); */
715         } else if (rc != -EACCES) {
716                 cERROR(1, ("Unexpected lookup error %d", rc));
717                 /* We special case check for Access Denied - since that
718                 is a common return code */
719         }
720
721         kfree(full_path);
722         FreeXid(xid);
723         return ERR_PTR(rc);
724 }
725
726 static int
727 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
728 {
729         int isValid = 1;
730
731         if (direntry->d_inode) {
732                 if (cifs_revalidate(direntry))
733                         return 0;
734         } else {
735                 cFYI(1, ("neg dentry 0x%p name = %s",
736                          direntry, direntry->d_name.name));
737                 if (time_after(jiffies, direntry->d_time + HZ) ||
738                         !lookupCacheEnabled) {
739                         d_drop(direntry);
740                         isValid = 0;
741                 }
742         }
743
744         return isValid;
745 }
746
747 /* static int cifs_d_delete(struct dentry *direntry)
748 {
749         int rc = 0;
750
751         cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
752
753         return rc;
754 }     */
755
756 const struct dentry_operations cifs_dentry_ops = {
757         .d_revalidate = cifs_d_revalidate,
758 /* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
759 };
760
761 static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
762 {
763         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
764         unsigned long hash;
765         int i;
766
767         hash = init_name_hash();
768         for (i = 0; i < q->len; i++)
769                 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
770                                          hash);
771         q->hash = end_name_hash(hash);
772
773         return 0;
774 }
775
776 static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
777                            struct qstr *b)
778 {
779         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
780
781         if ((a->len == b->len) &&
782             (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
783                 /*
784                  * To preserve case, don't let an existing negative dentry's
785                  * case take precedence.  If a is not a negative dentry, this
786                  * should have no side effects
787                  */
788                 memcpy((void *)a->name, b->name, a->len);
789                 return 0;
790         }
791         return 1;
792 }
793
794 const struct dentry_operations cifs_ci_dentry_ops = {
795         .d_revalidate = cifs_d_revalidate,
796         .d_hash = cifs_ci_hash,
797         .d_compare = cifs_ci_compare,
798 };