lockd: push lock_flocks down
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / cifs / dir.c
blob3840eddbfb7afd504e01862bcfbb2e6a1d975e0b
1 /*
2 * fs/cifs/dir.c
4 * vfs operations that deal with dentries
6 * Copyright (C) International Business Machines Corp., 2002,2009
7 * Author(s): Steve French (sfrench@us.ibm.com)
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.
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.
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
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"
36 static void
37 renew_parental_timestamps(struct dentry *direntry)
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));
47 /* Note: caller must free return buffer */
48 char *
49 build_path_from_dentry(struct dentry *direntry)
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);
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 */
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;
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);
96 temp = temp->d_parent;
97 if (temp == NULL) {
98 cERROR(1, "corrupt dentry");
99 kfree(full_path);
100 return NULL;
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;
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 */
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] = '/';
129 strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
130 return full_path;
133 static void setup_cifs_dentry(struct cifsTconInfo *tcon,
134 struct dentry *direntry,
135 struct inode *newinode)
137 if (tcon->nocase)
138 direntry->d_op = &cifs_ci_dentry_ops;
139 else
140 direntry->d_op = &cifs_dentry_ops;
141 d_instantiate(direntry, newinode);
144 /* Inode operations in similar order to how they appear in Linux file fs.h */
147 cifs_create(struct inode *inode, struct dentry *direntry, int mode,
148 struct nameidata *nd)
150 int rc = -ENOENT;
151 int xid;
152 int create_options = CREATE_NOT_DIR;
153 __u32 oplock = 0;
154 int oflags;
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.
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;
172 xid = GetXid();
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);
180 tcon = tlink_tcon(tlink);
182 if (oplockEnabled)
183 oplock = REQ_OPLOCK;
185 if (nd && (nd->flags & LOOKUP_OPEN))
186 oflags = nd->intent.open.file->f_flags;
187 else
188 oflags = O_RDONLY | O_CREAT;
190 full_path = build_path_from_dentry(direntry);
191 if (full_path == NULL) {
192 rc = -ENOMEM;
193 goto cifs_create_out;
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 */
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) */
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;
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");
239 /* BB add processing to set equivalent of mode - e.g. via CreateX with
240 ACLs */
242 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
243 if (buf == NULL) {
244 rc = -ENOMEM;
245 goto cifs_create_out;
249 * if we're not using unix extensions, see if we need to set
250 * ATTR_READONLY on the create call
252 if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
253 create_options |= CREATE_OPTION_READONLY;
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 */
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);
270 if (rc) {
271 cFYI(1, "cifs_create returned 0x%x", rc);
272 goto cifs_create_out;
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,
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;
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);*/
305 /* Could set r/o dos attribute if mode & 0222 == 0 */
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();
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);
336 if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
337 struct cifsFileInfo *pfile_info;
338 struct file *filp;
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;
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;
353 } else {
354 CIFSSMBClose(xid, tcon, fileHandle);
357 cifs_create_out:
358 kfree(buf);
359 kfree(full_path);
360 cifs_put_tlink(tlink);
361 FreeXid(xid);
362 return rc;
365 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
366 dev_t device_number)
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;
381 if (!old_valid_dev(device_number))
382 return -EINVAL;
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);
389 pTcon = tlink_tcon(tlink);
391 xid = GetXid();
393 full_path = build_path_from_dentry(direntry);
394 if (full_path == NULL) {
395 rc = -ENOMEM;
396 goto mknod_out;
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,
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;
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;
421 rc = cifs_get_inode_info_unix(&newinode, full_path,
422 inode->i_sb, xid);
423 if (pTcon->nocase)
424 direntry->d_op = &cifs_ci_dentry_ops;
425 else
426 direntry->d_op = &cifs_dentry_ops;
428 if (rc == 0)
429 d_instantiate(direntry, newinode);
430 goto mknod_out;
433 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
434 goto mknod_out;
437 cFYI(1, "sfu compat create special file");
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;
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;
455 /* BB Do not bother to decode buf since no local inode yet to put
456 * timestamps in, but we can reuse it safely */
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);
485 /* FIXME: add code here to set EAs */
487 mknod_out:
488 kfree(full_path);
489 kfree(buf);
490 FreeXid(xid);
491 cifs_put_tlink(tlink);
492 return rc;
495 struct dentry *
496 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
497 struct nameidata *nd)
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;
512 xid = GetXid();
514 cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
515 parent_dir_inode, direntry->d_name.name, direntry);
517 /* check whether path exists */
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;
525 pTcon = tlink_tcon(tlink);
528 * Don't allow the separator character in a path component.
529 * The VFS will not allow "/", but "\" is allowed by posix.
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;
542 * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
543 * the VFS handle the create.
545 if (nd && (nd->flags & LOOKUP_EXCL)) {
546 d_instantiate(direntry, NULL);
547 rc = 0;
548 goto lookup_out;
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;
560 if (direntry->d_inode != NULL) {
561 cFYI(1, "non-NULL inode in lookup");
562 } else {
563 cFYI(1, "NULL inode in lookup");
565 cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
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.
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);
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.
593 if ((rc == 0) || (rc == -ENOENT))
594 posix_open = true;
595 else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
596 pTcon->broken_posix_open = true;
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);
605 if ((rc == 0) && (newInode != NULL)) {
606 if (pTcon->nocase)
607 direntry->d_op = &cifs_ci_dentry_ops;
608 else
609 direntry->d_op = &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;
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;
629 /* since paths are not looked up by component - the parent
630 directories are presumed to be good here */
631 renew_parental_timestamps(direntry);
633 } else if (rc == -ENOENT) {
634 rc = 0;
635 direntry->d_time = jiffies;
636 if (pTcon->nocase)
637 direntry->d_op = &cifs_ci_dentry_ops;
638 else
639 direntry->d_op = &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 */
649 lookup_out:
650 kfree(full_path);
651 cifs_put_tlink(tlink);
652 FreeXid(xid);
653 return ERR_PTR(rc);
656 static int
657 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
659 int isValid = 1;
661 if (direntry->d_inode) {
662 if (cifs_revalidate_dentry(direntry))
663 return 0;
664 } else {
665 cFYI(1, "neg dentry 0x%p name = %s",
666 direntry, direntry->d_name.name);
667 if (time_after(jiffies, direntry->d_time + HZ) ||
668 !lookupCacheEnabled) {
669 d_drop(direntry);
670 isValid = 0;
674 return isValid;
677 /* static int cifs_d_delete(struct dentry *direntry)
679 int rc = 0;
681 cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
683 return rc;
684 } */
686 const struct dentry_operations cifs_dentry_ops = {
687 .d_revalidate = cifs_d_revalidate,
688 /* d_delete: cifs_d_delete, */ /* not needed except for debugging */
691 static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
693 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
694 unsigned long hash;
695 int i;
697 hash = init_name_hash();
698 for (i = 0; i < q->len; i++)
699 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
700 hash);
701 q->hash = end_name_hash(hash);
703 return 0;
706 static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
707 struct qstr *b)
709 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
711 if ((a->len == b->len) &&
712 (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
714 * To preserve case, don't let an existing negative dentry's
715 * case take precedence. If a is not a negative dentry, this
716 * should have no side effects
718 memcpy((void *)a->name, b->name, a->len);
719 return 0;
721 return 1;
724 const struct dentry_operations cifs_ci_dentry_ops = {
725 .d_revalidate = cifs_d_revalidate,
726 .d_hash = cifs_ci_hash,
727 .d_compare = cifs_ci_compare,