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