Merge branch 'dccp' of git://eden-feed.erg.abdn.ac.uk/net-next-2.6
[pandora-kernel.git] / fs / cifs / dir.c
1 /*
2  *   fs/cifs/dir.c
3  *
4  *   vfs operations that deal with dentries
5  *
6  *   Copyright (C) International Business Machines  Corp., 2002,2009
7  *   Author(s): Steve French (sfrench@us.ibm.com)
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23 #include <linux/fs.h>
24 #include <linux/stat.h>
25 #include <linux/slab.h>
26 #include <linux/namei.h>
27 #include <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 = CIFS_SB(direntry->d_sb);
58         struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
59
60         if (direntry == NULL)
61                 return NULL;  /* not much we can do if dentry is freed and
62                 we need to reopen the file after it was closed implicitly
63                 when the server crashed */
64
65         dirsep = CIFS_DIR_SEP(cifs_sb);
66         pplen = cifs_sb->prepathlen;
67         if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
68                 dfsplen = strnlen(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, 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 static void setup_cifs_dentry(struct cifsTconInfo *tcon,
134                               struct dentry *direntry,
135                               struct inode *newinode)
136 {
137         if (tcon->nocase)
138                 d_set_d_op(direntry, &cifs_ci_dentry_ops);
139         else
140                 d_set_d_op(direntry, &cifs_dentry_ops);
141         d_instantiate(direntry, newinode);
142 }
143
144 /* Inode operations in similar order to how they appear in Linux file fs.h */
145
146 int
147 cifs_create(struct inode *inode, struct dentry *direntry, int mode,
148                 struct nameidata *nd)
149 {
150         int rc = -ENOENT;
151         int xid;
152         int create_options = CREATE_NOT_DIR;
153         __u32 oplock = 0;
154         int oflags;
155         /*
156          * BB below access is probably too much for mknod to request
157          *    but we have to do query and setpathinfo so requesting
158          *    less could fail (unless we want to request getatr and setatr
159          *    permissions (only).  At least for POSIX we do not have to
160          *    request so much.
161          */
162         int desiredAccess = GENERIC_READ | GENERIC_WRITE;
163         __u16 fileHandle;
164         struct cifs_sb_info *cifs_sb;
165         struct tcon_link *tlink;
166         struct cifsTconInfo *tcon;
167         char *full_path = NULL;
168         FILE_ALL_INFO *buf = NULL;
169         struct inode *newinode = NULL;
170         int disposition = FILE_OVERWRITE_IF;
171
172         xid = GetXid();
173
174         cifs_sb = CIFS_SB(inode->i_sb);
175         tlink = cifs_sb_tlink(cifs_sb);
176         if (IS_ERR(tlink)) {
177                 FreeXid(xid);
178                 return PTR_ERR(tlink);
179         }
180         tcon = tlink_tcon(tlink);
181
182         if (oplockEnabled)
183                 oplock = REQ_OPLOCK;
184
185         if (nd && (nd->flags & LOOKUP_OPEN))
186                 oflags = nd->intent.open.file->f_flags;
187         else
188                 oflags = O_RDONLY | O_CREAT;
189
190         full_path = build_path_from_dentry(direntry);
191         if (full_path == NULL) {
192                 rc = -ENOMEM;
193                 goto cifs_create_out;
194         }
195
196         if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
197             (CIFS_UNIX_POSIX_PATH_OPS_CAP &
198                         le64_to_cpu(tcon->fsUnixInfo.Capability))) {
199                 rc = cifs_posix_open(full_path, &newinode,
200                         inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
201                 /* EIO could indicate that (posix open) operation is not
202                    supported, despite what server claimed in capability
203                    negotation.  EREMOTE indicates DFS junction, which is not
204                    handled in posix open */
205
206                 if (rc == 0) {
207                         if (newinode == NULL) /* query inode info */
208                                 goto cifs_create_get_file_info;
209                         else /* success, no need to query */
210                                 goto cifs_create_set_dentry;
211                 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
212                          (rc != -EOPNOTSUPP) && (rc != -EINVAL))
213                         goto cifs_create_out;
214                 /* else fallthrough to retry, using older open call, this is
215                    case where server does not support this SMB level, and
216                    falsely claims capability (also get here for DFS case
217                    which should be rare for path not covered on files) */
218         }
219
220         if (nd && (nd->flags & LOOKUP_OPEN)) {
221                 /* if the file is going to stay open, then we
222                    need to set the desired access properly */
223                 desiredAccess = 0;
224                 if (OPEN_FMODE(oflags) & FMODE_READ)
225                         desiredAccess |= GENERIC_READ; /* is this too little? */
226                 if (OPEN_FMODE(oflags) & FMODE_WRITE)
227                         desiredAccess |= GENERIC_WRITE;
228
229                 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
230                         disposition = FILE_CREATE;
231                 else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
232                         disposition = FILE_OVERWRITE_IF;
233                 else if ((oflags & O_CREAT) == O_CREAT)
234                         disposition = FILE_OPEN_IF;
235                 else
236                         cFYI(1, "Create flag not set in create function");
237         }
238
239         /* BB add processing to set equivalent of mode - e.g. via CreateX with
240            ACLs */
241
242         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
243         if (buf == NULL) {
244                 rc = -ENOMEM;
245                 goto cifs_create_out;
246         }
247
248         /*
249          * if we're not using unix extensions, see if we need to set
250          * ATTR_READONLY on the create call
251          */
252         if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
253                 create_options |= CREATE_OPTION_READONLY;
254
255         if (tcon->ses->capabilities & CAP_NT_SMBS)
256                 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
257                          desiredAccess, create_options,
258                          &fileHandle, &oplock, buf, cifs_sb->local_nls,
259                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
260         else
261                 rc = -EIO; /* no NT SMB support fall into legacy open below */
262
263         if (rc == -EIO) {
264                 /* old server, retry the open legacy style */
265                 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
266                         desiredAccess, create_options,
267                         &fileHandle, &oplock, buf, cifs_sb->local_nls,
268                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
269         }
270         if (rc) {
271                 cFYI(1, "cifs_create returned 0x%x", rc);
272                 goto cifs_create_out;
273         }
274
275         /* If Open reported that we actually created a file
276            then we now have to set the mode if possible */
277         if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
278                 struct cifs_unix_set_info_args args = {
279                                 .mode   = mode,
280                                 .ctime  = NO_CHANGE_64,
281                                 .atime  = NO_CHANGE_64,
282                                 .mtime  = NO_CHANGE_64,
283                                 .device = 0,
284                 };
285
286                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
287                         args.uid = (__u64) current_fsuid();
288                         if (inode->i_mode & S_ISGID)
289                                 args.gid = (__u64) inode->i_gid;
290                         else
291                                 args.gid = (__u64) current_fsgid();
292                 } else {
293                         args.uid = NO_CHANGE_64;
294                         args.gid = NO_CHANGE_64;
295                 }
296                 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
297                                         cifs_sb->local_nls,
298                                         cifs_sb->mnt_cifs_flags &
299                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
300         } else {
301                 /* BB implement mode setting via Windows security
302                    descriptors e.g. */
303                 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
304
305                 /* Could set r/o dos attribute if mode & 0222 == 0 */
306         }
307
308 cifs_create_get_file_info:
309         /* server might mask mode so we have to query for it */
310         if (tcon->unix_ext)
311                 rc = cifs_get_inode_info_unix(&newinode, full_path,
312                                               inode->i_sb, xid);
313         else {
314                 rc = cifs_get_inode_info(&newinode, full_path, buf,
315                                          inode->i_sb, xid, &fileHandle);
316                 if (newinode) {
317                         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
318                                 newinode->i_mode = mode;
319                         if ((oplock & CIFS_CREATE_ACTION) &&
320                             (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
321                                 newinode->i_uid = current_fsuid();
322                                 if (inode->i_mode & S_ISGID)
323                                         newinode->i_gid = inode->i_gid;
324                                 else
325                                         newinode->i_gid = current_fsgid();
326                         }
327                 }
328         }
329
330 cifs_create_set_dentry:
331         if (rc == 0)
332                 setup_cifs_dentry(tcon, direntry, newinode);
333         else
334                 cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
335
336         if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
337                 struct cifsFileInfo *pfile_info;
338                 struct file *filp;
339
340                 filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
341                 if (IS_ERR(filp)) {
342                         rc = PTR_ERR(filp);
343                         CIFSSMBClose(xid, tcon, fileHandle);
344                         goto cifs_create_out;
345                 }
346
347                 pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
348                 if (pfile_info == NULL) {
349                         fput(filp);
350                         CIFSSMBClose(xid, tcon, fileHandle);
351                         rc = -ENOMEM;
352                 }
353         } else {
354                 CIFSSMBClose(xid, tcon, fileHandle);
355         }
356
357 cifs_create_out:
358         kfree(buf);
359         kfree(full_path);
360         cifs_put_tlink(tlink);
361         FreeXid(xid);
362         return rc;
363 }
364
365 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
366                 dev_t device_number)
367 {
368         int rc = -EPERM;
369         int xid;
370         struct cifs_sb_info *cifs_sb;
371         struct tcon_link *tlink;
372         struct cifsTconInfo *pTcon;
373         char *full_path = NULL;
374         struct inode *newinode = NULL;
375         int oplock = 0;
376         u16 fileHandle;
377         FILE_ALL_INFO *buf = NULL;
378         unsigned int bytes_written;
379         struct win_dev *pdev;
380
381         if (!old_valid_dev(device_number))
382                 return -EINVAL;
383
384         cifs_sb = CIFS_SB(inode->i_sb);
385         tlink = cifs_sb_tlink(cifs_sb);
386         if (IS_ERR(tlink))
387                 return PTR_ERR(tlink);
388
389         pTcon = tlink_tcon(tlink);
390
391         xid = GetXid();
392
393         full_path = build_path_from_dentry(direntry);
394         if (full_path == NULL) {
395                 rc = -ENOMEM;
396                 goto mknod_out;
397         }
398
399         if (pTcon->unix_ext) {
400                 struct cifs_unix_set_info_args args = {
401                         .mode   = mode & ~current_umask(),
402                         .ctime  = NO_CHANGE_64,
403                         .atime  = NO_CHANGE_64,
404                         .mtime  = NO_CHANGE_64,
405                         .device = device_number,
406                 };
407                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
408                         args.uid = (__u64) current_fsuid();
409                         args.gid = (__u64) current_fsgid();
410                 } else {
411                         args.uid = NO_CHANGE_64;
412                         args.gid = NO_CHANGE_64;
413                 }
414                 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
415                                             cifs_sb->local_nls,
416                                             cifs_sb->mnt_cifs_flags &
417                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
418                 if (rc)
419                         goto mknod_out;
420
421                 rc = cifs_get_inode_info_unix(&newinode, full_path,
422                                                 inode->i_sb, xid);
423                 if (pTcon->nocase)
424                         d_set_d_op(direntry, &cifs_ci_dentry_ops);
425                 else
426                         d_set_d_op(direntry, &cifs_dentry_ops);
427
428                 if (rc == 0)
429                         d_instantiate(direntry, newinode);
430                 goto mknod_out;
431         }
432
433         if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
434                 goto mknod_out;
435
436
437         cFYI(1, "sfu compat create special file");
438
439         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
440         if (buf == NULL) {
441                 kfree(full_path);
442                 rc = -ENOMEM;
443                 FreeXid(xid);
444                 return rc;
445         }
446
447         /* FIXME: would WRITE_OWNER | WRITE_DAC be better? */
448         rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
449                          GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
450                          &fileHandle, &oplock, buf, cifs_sb->local_nls,
451                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
452         if (rc)
453                 goto mknod_out;
454
455         /* BB Do not bother to decode buf since no local inode yet to put
456          * timestamps in, but we can reuse it safely */
457
458         pdev = (struct win_dev *)buf;
459         if (S_ISCHR(mode)) {
460                 memcpy(pdev->type, "IntxCHR", 8);
461                 pdev->major =
462                       cpu_to_le64(MAJOR(device_number));
463                 pdev->minor =
464                       cpu_to_le64(MINOR(device_number));
465                 rc = CIFSSMBWrite(xid, pTcon,
466                         fileHandle,
467                         sizeof(struct win_dev),
468                         0, &bytes_written, (char *)pdev,
469                         NULL, 0);
470         } else if (S_ISBLK(mode)) {
471                 memcpy(pdev->type, "IntxBLK", 8);
472                 pdev->major =
473                       cpu_to_le64(MAJOR(device_number));
474                 pdev->minor =
475                       cpu_to_le64(MINOR(device_number));
476                 rc = CIFSSMBWrite(xid, pTcon,
477                         fileHandle,
478                         sizeof(struct win_dev),
479                         0, &bytes_written, (char *)pdev,
480                         NULL, 0);
481         } /* else if (S_ISFIFO) */
482         CIFSSMBClose(xid, pTcon, fileHandle);
483         d_drop(direntry);
484
485         /* FIXME: add code here to set EAs */
486
487 mknod_out:
488         kfree(full_path);
489         kfree(buf);
490         FreeXid(xid);
491         cifs_put_tlink(tlink);
492         return rc;
493 }
494
495 struct dentry *
496 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
497             struct nameidata *nd)
498 {
499         int xid;
500         int rc = 0; /* to get around spurious gcc warning, set to zero here */
501         __u32 oplock = 0;
502         __u16 fileHandle = 0;
503         bool posix_open = false;
504         struct cifs_sb_info *cifs_sb;
505         struct tcon_link *tlink;
506         struct cifsTconInfo *pTcon;
507         struct cifsFileInfo *cfile;
508         struct inode *newInode = NULL;
509         char *full_path = NULL;
510         struct file *filp;
511
512         xid = GetXid();
513
514         cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
515               parent_dir_inode, direntry->d_name.name, direntry);
516
517         /* check whether path exists */
518
519         cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
520         tlink = cifs_sb_tlink(cifs_sb);
521         if (IS_ERR(tlink)) {
522                 FreeXid(xid);
523                 return (struct dentry *)tlink;
524         }
525         pTcon = tlink_tcon(tlink);
526
527         /*
528          * Don't allow the separator character in a path component.
529          * The VFS will not allow "/", but "\" is allowed by posix.
530          */
531         if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
532                 int i;
533                 for (i = 0; i < direntry->d_name.len; i++)
534                         if (direntry->d_name.name[i] == '\\') {
535                                 cFYI(1, "Invalid file name");
536                                 rc = -EINVAL;
537                                 goto lookup_out;
538                         }
539         }
540
541         /*
542          * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
543          * the VFS handle the create.
544          */
545         if (nd && (nd->flags & LOOKUP_EXCL)) {
546                 d_instantiate(direntry, NULL);
547                 rc = 0;
548                 goto lookup_out;
549         }
550
551         /* can not grab the rename sem here since it would
552         deadlock in the cases (beginning of sys_rename itself)
553         in which we already have the sb rename sem */
554         full_path = build_path_from_dentry(direntry);
555         if (full_path == NULL) {
556                 rc = -ENOMEM;
557                 goto lookup_out;
558         }
559
560         if (direntry->d_inode != NULL) {
561                 cFYI(1, "non-NULL inode in lookup");
562         } else {
563                 cFYI(1, "NULL inode in lookup");
564         }
565         cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
566
567         /* Posix open is only called (at lookup time) for file create now.
568          * For opens (rather than creates), because we do not know if it
569          * is a file or directory yet, and current Samba no longer allows
570          * us to do posix open on dirs, we could end up wasting an open call
571          * on what turns out to be a dir. For file opens, we wait to call posix
572          * open till cifs_open.  It could be added here (lookup) in the future
573          * but the performance tradeoff of the extra network request when EISDIR
574          * or EACCES is returned would have to be weighed against the 50%
575          * reduction in network traffic in the other paths.
576          */
577         if (pTcon->unix_ext) {
578                 if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
579                      (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
580                      (nd->intent.open.file->f_flags & O_CREAT)) {
581                         rc = cifs_posix_open(full_path, &newInode,
582                                         parent_dir_inode->i_sb,
583                                         nd->intent.open.create_mode,
584                                         nd->intent.open.file->f_flags, &oplock,
585                                         &fileHandle, xid);
586                         /*
587                          * The check below works around a bug in POSIX
588                          * open in samba versions 3.3.1 and earlier where
589                          * open could incorrectly fail with invalid parameter.
590                          * If either that or op not supported returned, follow
591                          * the normal lookup.
592                          */
593                         if ((rc == 0) || (rc == -ENOENT))
594                                 posix_open = true;
595                         else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
596                                 pTcon->broken_posix_open = true;
597                 }
598                 if (!posix_open)
599                         rc = cifs_get_inode_info_unix(&newInode, full_path,
600                                                 parent_dir_inode->i_sb, xid);
601         } else
602                 rc = cifs_get_inode_info(&newInode, full_path, NULL,
603                                 parent_dir_inode->i_sb, xid, NULL);
604
605         if ((rc == 0) && (newInode != NULL)) {
606                 if (pTcon->nocase)
607                         d_set_d_op(direntry, &cifs_ci_dentry_ops);
608                 else
609                         d_set_d_op(direntry, &cifs_dentry_ops);
610                 d_add(direntry, newInode);
611                 if (posix_open) {
612                         filp = lookup_instantiate_filp(nd, direntry,
613                                                        generic_file_open);
614                         if (IS_ERR(filp)) {
615                                 rc = PTR_ERR(filp);
616                                 CIFSSMBClose(xid, pTcon, fileHandle);
617                                 goto lookup_out;
618                         }
619
620                         cfile = cifs_new_fileinfo(fileHandle, filp, tlink,
621                                                   oplock);
622                         if (cfile == NULL) {
623                                 fput(filp);
624                                 CIFSSMBClose(xid, pTcon, fileHandle);
625                                 rc = -ENOMEM;
626                                 goto lookup_out;
627                         }
628                 }
629                 /* since paths are not looked up by component - the parent
630                    directories are presumed to be good here */
631                 renew_parental_timestamps(direntry);
632
633         } else if (rc == -ENOENT) {
634                 rc = 0;
635                 direntry->d_time = jiffies;
636                 if (pTcon->nocase)
637                         d_set_d_op(direntry, &cifs_ci_dentry_ops);
638                 else
639                         d_set_d_op(direntry, &cifs_dentry_ops);
640                 d_add(direntry, NULL);
641         /*      if it was once a directory (but how can we tell?) we could do
642                 shrink_dcache_parent(direntry); */
643         } else if (rc != -EACCES) {
644                 cERROR(1, "Unexpected lookup error %d", rc);
645                 /* We special case check for Access Denied - since that
646                 is a common return code */
647         }
648
649 lookup_out:
650         kfree(full_path);
651         cifs_put_tlink(tlink);
652         FreeXid(xid);
653         return ERR_PTR(rc);
654 }
655
656 static int
657 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
658 {
659         if (nd->flags & LOOKUP_RCU)
660                 return -ECHILD;
661
662         if (direntry->d_inode) {
663                 if (cifs_revalidate_dentry(direntry))
664                         return 0;
665                 else
666                         return 1;
667         }
668
669         /*
670          * This may be nfsd (or something), anyway, we can't see the
671          * intent of this. So, since this can be for creation, drop it.
672          */
673         if (!nd)
674                 return 0;
675
676         /*
677          * Drop the negative dentry, in order to make sure to use the
678          * case sensitive name which is specified by user if this is
679          * for creation.
680          */
681         if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
682                 if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
683                         return 0;
684         }
685
686         if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
687                 return 0;
688
689         return 1;
690 }
691
692 /* static int cifs_d_delete(struct dentry *direntry)
693 {
694         int rc = 0;
695
696         cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
697
698         return rc;
699 }     */
700
701 const struct dentry_operations cifs_dentry_ops = {
702         .d_revalidate = cifs_d_revalidate,
703 /* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
704 };
705
706 static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
707                 struct qstr *q)
708 {
709         struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
710         unsigned long hash;
711         int i;
712
713         hash = init_name_hash();
714         for (i = 0; i < q->len; i++)
715                 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
716                                          hash);
717         q->hash = end_name_hash(hash);
718
719         return 0;
720 }
721
722 static int cifs_ci_compare(const struct dentry *parent,
723                 const struct inode *pinode,
724                 const struct dentry *dentry, const struct inode *inode,
725                 unsigned int len, const char *str, const struct qstr *name)
726 {
727         struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls;
728
729         if ((name->len == len) &&
730             (nls_strnicmp(codepage, name->name, str, len) == 0))
731                 return 0;
732         return 1;
733 }
734
735 const struct dentry_operations cifs_ci_dentry_ops = {
736         .d_revalidate = cifs_d_revalidate,
737         .d_hash = cifs_ci_hash,
738         .d_compare = cifs_ci_compare,
739 };