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