461750e01364f9b38a3be599b8ee8cecf4b95d93
[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         /*
285          * BB below access is probably too much for mknod to request
286          *    but we have to do query and setpathinfo so requesting
287          *    less could fail (unless we want to request getatr and setatr
288          *    permissions (only).  At least for POSIX we do not have to
289          *    request so much.
290          */
291         int desiredAccess = GENERIC_READ | GENERIC_WRITE;
292         __u16 fileHandle;
293         struct cifs_sb_info *cifs_sb;
294         struct cifsTconInfo *tcon;
295         char *full_path = NULL;
296         FILE_ALL_INFO *buf = NULL;
297         struct inode *newinode = NULL;
298         int disposition = FILE_OVERWRITE_IF;
299         bool write_only = false;
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                 FreeXid(xid);
309                 return -ENOMEM;
310         }
311
312         mode &= ~current_umask();
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;
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, inode->i_sb,
325                                      mode, oflags, &oplock, &fileHandle, xid);
326                 /* EIO could indicate that (posix open) operation is not
327                    supported, despite what server claimed in capability
328                    negotation.  EREMOTE indicates DFS junction, which is not
329                    handled in posix open */
330
331                 if ((rc == 0) && (newinode == NULL))
332                         goto cifs_create_get_file_info; /* query inode info */
333                 else if (rc == 0) /* success, no need to query */
334                         goto cifs_create_set_dentry;
335                 else if ((rc != -EIO) && (rc != -EREMOTE) &&
336                          (rc != -EOPNOTSUPP)) /* path not found or net err */
337                         goto cifs_create_out;
338                 /* else fallthrough to retry, using older open call, this is
339                    case where server does not support this SMB level, and
340                    falsely claims capability (also get here for DFS case
341                    which should be rare for path not covered on files) */
342         }
343
344         if (nd && (nd->flags & LOOKUP_OPEN)) {
345                 /* if the file is going to stay open, then we
346                    need to set the desired access properly */
347                 desiredAccess = 0;
348                 if (oflags & FMODE_READ)
349                         desiredAccess |= GENERIC_READ; /* is this too little? */
350                 if (oflags & FMODE_WRITE) {
351                         desiredAccess |= GENERIC_WRITE;
352                         if (!(oflags & FMODE_READ))
353                                 write_only = true;
354                 }
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                 CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
425                         cifs_sb->local_nls,
426                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
427         } else {
428                 /* BB implement mode setting via Windows security
429                    descriptors e.g. */
430                 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
431
432                 /* Could set r/o dos attribute if mode & 0222 == 0 */
433         }
434
435 cifs_create_get_file_info:
436         /* server might mask mode so we have to query for it */
437         if (tcon->unix_ext)
438                 rc = cifs_get_inode_info_unix(&newinode, full_path,
439                                               inode->i_sb, xid);
440         else {
441                 rc = cifs_get_inode_info(&newinode, full_path, buf,
442                                          inode->i_sb, xid, &fileHandle);
443                 if (newinode) {
444                         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
445                                 newinode->i_mode = mode;
446                         if ((oplock & CIFS_CREATE_ACTION) &&
447                             (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
448                                 newinode->i_uid = current_fsuid();
449                                 if (inode->i_mode & S_ISGID)
450                                         newinode->i_gid = inode->i_gid;
451                                 else
452                                         newinode->i_gid = current_fsgid();
453                         }
454                 }
455         }
456
457 cifs_create_set_dentry:
458         if (rc == 0)
459                 setup_cifs_dentry(tcon, direntry, newinode);
460         else
461                 cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc));
462
463         /* nfsd case - nfs srv does not set nd */
464         if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
465                 /* mknod case - do not leave file open */
466                 CIFSSMBClose(xid, tcon, fileHandle);
467         } else if (newinode) {
468                         cifs_fill_fileinfo(newinode, fileHandle,
469                                         cifs_sb->tcon, write_only);
470         }
471 cifs_create_out:
472         kfree(buf);
473         kfree(full_path);
474         FreeXid(xid);
475         return rc;
476 }
477
478 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
479                 dev_t device_number)
480 {
481         int rc = -EPERM;
482         int xid;
483         struct cifs_sb_info *cifs_sb;
484         struct cifsTconInfo *pTcon;
485         char *full_path = NULL;
486         struct inode *newinode = NULL;
487
488         if (!old_valid_dev(device_number))
489                 return -EINVAL;
490
491         xid = GetXid();
492
493         cifs_sb = CIFS_SB(inode->i_sb);
494         pTcon = cifs_sb->tcon;
495
496         full_path = build_path_from_dentry(direntry);
497         if (full_path == NULL)
498                 rc = -ENOMEM;
499         else if (pTcon->unix_ext) {
500                 struct cifs_unix_set_info_args args = {
501                         .mode   = mode & ~current_umask(),
502                         .ctime  = NO_CHANGE_64,
503                         .atime  = NO_CHANGE_64,
504                         .mtime  = NO_CHANGE_64,
505                         .device = device_number,
506                 };
507                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
508                         args.uid = (__u64) current_fsuid();
509                         args.gid = (__u64) current_fsgid();
510                 } else {
511                         args.uid = NO_CHANGE_64;
512                         args.gid = NO_CHANGE_64;
513                 }
514                 rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path,
515                         &args, cifs_sb->local_nls,
516                         cifs_sb->mnt_cifs_flags &
517                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
518
519                 if (!rc) {
520                         rc = cifs_get_inode_info_unix(&newinode, full_path,
521                                                 inode->i_sb, xid);
522                         if (pTcon->nocase)
523                                 direntry->d_op = &cifs_ci_dentry_ops;
524                         else
525                                 direntry->d_op = &cifs_dentry_ops;
526                         if (rc == 0)
527                                 d_instantiate(direntry, newinode);
528                 }
529         } else {
530                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
531                         int oplock = 0;
532                         u16 fileHandle;
533                         FILE_ALL_INFO *buf;
534
535                         cFYI(1, ("sfu compat create special file"));
536
537                         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
538                         if (buf == NULL) {
539                                 kfree(full_path);
540                                 FreeXid(xid);
541                                 return -ENOMEM;
542                         }
543
544                         rc = CIFSSMBOpen(xid, pTcon, full_path,
545                                          FILE_CREATE, /* fail if exists */
546                                          GENERIC_WRITE /* BB would
547                                           WRITE_OWNER | WRITE_DAC be better? */,
548                                          /* Create a file and set the
549                                             file attribute to SYSTEM */
550                                          CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
551                                          &fileHandle, &oplock, buf,
552                                          cifs_sb->local_nls,
553                                          cifs_sb->mnt_cifs_flags &
554                                             CIFS_MOUNT_MAP_SPECIAL_CHR);
555
556                         /* BB FIXME - add handling for backlevel servers
557                            which need legacy open and check for all
558                            calls to SMBOpen for fallback to SMBLeagcyOpen */
559                         if (!rc) {
560                                 /* BB Do not bother to decode buf since no
561                                    local inode yet to put timestamps in,
562                                    but we can reuse it safely */
563                                 unsigned int bytes_written;
564                                 struct win_dev *pdev;
565                                 pdev = (struct win_dev *)buf;
566                                 if (S_ISCHR(mode)) {
567                                         memcpy(pdev->type, "IntxCHR", 8);
568                                         pdev->major =
569                                               cpu_to_le64(MAJOR(device_number));
570                                         pdev->minor =
571                                               cpu_to_le64(MINOR(device_number));
572                                         rc = CIFSSMBWrite(xid, pTcon,
573                                                 fileHandle,
574                                                 sizeof(struct win_dev),
575                                                 0, &bytes_written, (char *)pdev,
576                                                 NULL, 0);
577                                 } else if (S_ISBLK(mode)) {
578                                         memcpy(pdev->type, "IntxBLK", 8);
579                                         pdev->major =
580                                               cpu_to_le64(MAJOR(device_number));
581                                         pdev->minor =
582                                               cpu_to_le64(MINOR(device_number));
583                                         rc = CIFSSMBWrite(xid, pTcon,
584                                                 fileHandle,
585                                                 sizeof(struct win_dev),
586                                                 0, &bytes_written, (char *)pdev,
587                                                 NULL, 0);
588                                 } /* else if(S_ISFIFO */
589                                 CIFSSMBClose(xid, pTcon, fileHandle);
590                                 d_drop(direntry);
591                         }
592                         kfree(buf);
593                         /* add code here to set EAs */
594                 }
595         }
596
597         kfree(full_path);
598         FreeXid(xid);
599         return rc;
600 }
601
602 struct dentry *
603 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
604             struct nameidata *nd)
605 {
606         int xid;
607         int rc = 0; /* to get around spurious gcc warning, set to zero here */
608         int oplock = 0;
609         int mode;
610         __u16 fileHandle = 0;
611         bool posix_open = false;
612         struct cifs_sb_info *cifs_sb;
613         struct cifsTconInfo *pTcon;
614         struct inode *newInode = NULL;
615         char *full_path = NULL;
616         struct file *filp;
617
618         xid = GetXid();
619
620         cFYI(1, ("parent inode = 0x%p name is: %s and dentry = 0x%p",
621               parent_dir_inode, direntry->d_name.name, direntry));
622
623         /* check whether path exists */
624
625         cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
626         pTcon = cifs_sb->tcon;
627
628         /*
629          * Don't allow the separator character in a path component.
630          * The VFS will not allow "/", but "\" is allowed by posix.
631          */
632         if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
633                 int i;
634                 for (i = 0; i < direntry->d_name.len; i++)
635                         if (direntry->d_name.name[i] == '\\') {
636                                 cFYI(1, ("Invalid file name"));
637                                 FreeXid(xid);
638                                 return ERR_PTR(-EINVAL);
639                         }
640         }
641
642         /* can not grab the rename sem here since it would
643         deadlock in the cases (beginning of sys_rename itself)
644         in which we already have the sb rename sem */
645         full_path = build_path_from_dentry(direntry);
646         if (full_path == NULL) {
647                 FreeXid(xid);
648                 return ERR_PTR(-ENOMEM);
649         }
650
651         if (direntry->d_inode != NULL) {
652                 cFYI(1, ("non-NULL inode in lookup"));
653         } else {
654                 cFYI(1, ("NULL inode in lookup"));
655         }
656         cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
657
658         if (pTcon->unix_ext) {
659                 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
660                                 (nd->flags & LOOKUP_OPEN)) {
661                         if (!((nd->intent.open.flags & O_CREAT) &&
662                                         (nd->intent.open.flags & O_EXCL))) {
663                                 mode = nd->intent.open.create_mode &
664                                                 ~current_umask();
665                                 rc = cifs_posix_open(full_path, &newInode,
666                                         parent_dir_inode->i_sb, mode,
667                                         nd->intent.open.flags, &oplock,
668                                         &fileHandle, xid);
669                                 /*
670                                  * This code works around a bug in
671                                  * samba posix open in samba versions 3.3.1
672                                  * and earlier where create works
673                                  * but open fails with invalid parameter.
674                                  * If either of these error codes are
675                                  * returned, follow the normal lookup.
676                                  * Otherwise, the error during posix open
677                                  * is handled.
678                                  */
679                                 if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
680                                         posix_open = true;
681                         }
682                 }
683                 if (!posix_open)
684                         rc = cifs_get_inode_info_unix(&newInode, full_path,
685                                                 parent_dir_inode->i_sb, xid);
686         } else
687                 rc = cifs_get_inode_info(&newInode, full_path, NULL,
688                                 parent_dir_inode->i_sb, xid, NULL);
689
690         if ((rc == 0) && (newInode != NULL)) {
691                 if (pTcon->nocase)
692                         direntry->d_op = &cifs_ci_dentry_ops;
693                 else
694                         direntry->d_op = &cifs_dentry_ops;
695                 d_add(direntry, newInode);
696                 if (posix_open)
697                         filp = lookup_instantiate_filp(nd, direntry, NULL);
698                 /* since paths are not looked up by component - the parent
699                    directories are presumed to be good here */
700                 renew_parental_timestamps(direntry);
701
702         } else if (rc == -ENOENT) {
703                 rc = 0;
704                 direntry->d_time = jiffies;
705                 if (pTcon->nocase)
706                         direntry->d_op = &cifs_ci_dentry_ops;
707                 else
708                         direntry->d_op = &cifs_dentry_ops;
709                 d_add(direntry, NULL);
710         /*      if it was once a directory (but how can we tell?) we could do
711                 shrink_dcache_parent(direntry); */
712         } else if (rc != -EACCES) {
713                 cERROR(1, ("Unexpected lookup error %d", rc));
714                 /* We special case check for Access Denied - since that
715                 is a common return code */
716         }
717
718         kfree(full_path);
719         FreeXid(xid);
720         return ERR_PTR(rc);
721 }
722
723 static int
724 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
725 {
726         int isValid = 1;
727
728         if (direntry->d_inode) {
729                 if (cifs_revalidate(direntry))
730                         return 0;
731         } else {
732                 cFYI(1, ("neg dentry 0x%p name = %s",
733                          direntry, direntry->d_name.name));
734                 if (time_after(jiffies, direntry->d_time + HZ) ||
735                         !lookupCacheEnabled) {
736                         d_drop(direntry);
737                         isValid = 0;
738                 }
739         }
740
741         return isValid;
742 }
743
744 /* static int cifs_d_delete(struct dentry *direntry)
745 {
746         int rc = 0;
747
748         cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
749
750         return rc;
751 }     */
752
753 const struct dentry_operations cifs_dentry_ops = {
754         .d_revalidate = cifs_d_revalidate,
755 /* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
756 };
757
758 static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
759 {
760         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
761         unsigned long hash;
762         int i;
763
764         hash = init_name_hash();
765         for (i = 0; i < q->len; i++)
766                 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
767                                          hash);
768         q->hash = end_name_hash(hash);
769
770         return 0;
771 }
772
773 static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
774                            struct qstr *b)
775 {
776         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
777
778         if ((a->len == b->len) &&
779             (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
780                 /*
781                  * To preserve case, don't let an existing negative dentry's
782                  * case take precedence.  If a is not a negative dentry, this
783                  * should have no side effects
784                  */
785                 memcpy((void *)a->name, b->name, a->len);
786                 return 0;
787         }
788         return 1;
789 }
790
791 const struct dentry_operations cifs_ci_dentry_ops = {
792         .d_revalidate = cifs_d_revalidate,
793         .d_hash = cifs_ci_hash,
794         .d_compare = cifs_ci_compare,
795 };