1 // SPDX-License-Identifier: LGPL-2.1
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)
11 #include <linux/stat.h>
12 #include <linux/slab.h>
13 #include <linux/namei.h>
14 #include <linux/mount.h>
15 #include <linux/file.h>
19 #include "cifsproto.h"
20 #include "cifs_debug.h"
21 #include "cifs_fs_sb.h"
22 #include "cifs_unicode.h"
23 #include "fs_context.h"
24 #include "cifs_ioctl.h"
28 renew_parental_timestamps(struct dentry
*direntry
)
30 /* BB check if there is a way to get the kernel to do this or if we
33 cifs_set_time(direntry
, jiffies
);
34 direntry
= direntry
->d_parent
;
35 } while (!IS_ROOT(direntry
));
39 cifs_build_path_to_root(struct smb3_fs_context
*ctx
, struct cifs_sb_info
*cifs_sb
,
40 struct cifs_tcon
*tcon
, int add_treename
)
42 int pplen
= ctx
->prepath
? strlen(ctx
->prepath
) + 1 : 0;
44 char *full_path
= NULL
;
46 /* if no prefix path, simply set path to the root of share to "" */
48 full_path
= kzalloc(1, GFP_KERNEL
);
53 dfsplen
= strnlen(tcon
->tree_name
, MAX_TREE_SIZE
+ 1);
57 full_path
= kmalloc(dfsplen
+ pplen
+ 1, GFP_KERNEL
);
58 if (full_path
== NULL
)
62 memcpy(full_path
, tcon
->tree_name
, dfsplen
);
63 full_path
[dfsplen
] = CIFS_DIR_SEP(cifs_sb
);
64 memcpy(full_path
+ dfsplen
+ 1, ctx
->prepath
, pplen
);
65 convert_delimiter(full_path
, CIFS_DIR_SEP(cifs_sb
));
69 /* Note: caller must free return buffer */
71 build_path_from_dentry(struct dentry
*direntry
, void *page
)
73 struct cifs_sb_info
*cifs_sb
= CIFS_SB(direntry
->d_sb
);
74 struct cifs_tcon
*tcon
= cifs_sb_master_tcon(cifs_sb
);
75 bool prefix
= tcon
->Flags
& SMB_SHARE_IS_IN_DFS
;
77 return build_path_from_dentry_optional_prefix(direntry
, page
,
81 char *__build_path_from_dentry_optional_prefix(struct dentry
*direntry
, void *page
,
82 const char *tree
, int tree_len
,
87 struct cifs_sb_info
*cifs_sb
= CIFS_SB(direntry
->d_sb
);
88 char dirsep
= CIFS_DIR_SEP(cifs_sb
);
92 return ERR_PTR(-ENOMEM
);
95 dfsplen
= strnlen(tree
, tree_len
+ 1);
99 if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_USE_PREFIX_PATH
)
100 pplen
= cifs_sb
->prepath
? strlen(cifs_sb
->prepath
) + 1 : 0;
102 s
= dentry_path_raw(direntry
, page
, PATH_MAX
);
105 if (!s
[1]) // for root we want "", not "/"
107 if (s
< (char *)page
+ pplen
+ dfsplen
)
108 return ERR_PTR(-ENAMETOOLONG
);
110 cifs_dbg(FYI
, "using cifs_sb prepath <%s>\n", cifs_sb
->prepath
);
112 memcpy(s
+ 1, cifs_sb
->prepath
, pplen
- 1);
116 /* BB test paths to Windows with '/' in the midst of prepath */
125 memcpy(s
, tree
, dfsplen
);
126 if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_POSIX_PATHS
) {
128 for (i
= 0; i
< dfsplen
; i
++) {
137 char *build_path_from_dentry_optional_prefix(struct dentry
*direntry
, void *page
,
140 struct cifs_sb_info
*cifs_sb
= CIFS_SB(direntry
->d_sb
);
141 struct cifs_tcon
*tcon
= cifs_sb_master_tcon(cifs_sb
);
143 return __build_path_from_dentry_optional_prefix(direntry
, page
, tcon
->tree_name
,
144 MAX_TREE_SIZE
, prefix
);
148 * Don't allow path components longer than the server max.
149 * Don't allow the separator character in a path component.
150 * The VFS will not allow "/", but "\" is allowed by posix.
153 check_name(struct dentry
*direntry
, struct cifs_tcon
*tcon
)
155 struct cifs_sb_info
*cifs_sb
= CIFS_SB(direntry
->d_sb
);
158 if (unlikely(tcon
->fsAttrInfo
.MaxPathNameComponentLength
&&
159 direntry
->d_name
.len
>
160 le32_to_cpu(tcon
->fsAttrInfo
.MaxPathNameComponentLength
)))
161 return -ENAMETOOLONG
;
163 if (!(cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_POSIX_PATHS
)) {
164 for (i
= 0; i
< direntry
->d_name
.len
; i
++) {
165 if (direntry
->d_name
.name
[i
] == '\\') {
166 cifs_dbg(FYI
, "Invalid file name\n");
175 /* Inode operations in similar order to how they appear in Linux file fs.h */
177 static int cifs_do_create(struct inode
*inode
, struct dentry
*direntry
, unsigned int xid
,
178 struct tcon_link
*tlink
, unsigned int oflags
, umode_t mode
, __u32
*oplock
,
179 struct cifs_fid
*fid
, struct cifs_open_info_data
*buf
)
182 int create_options
= CREATE_NOT_DIR
;
184 struct cifs_sb_info
*cifs_sb
= CIFS_SB(inode
->i_sb
);
185 struct cifs_tcon
*tcon
= tlink_tcon(tlink
);
186 const char *full_path
;
187 void *page
= alloc_dentry_path();
188 struct inode
*newinode
= NULL
;
190 struct TCP_Server_Info
*server
= tcon
->ses
->server
;
191 struct cifs_open_parms oparms
;
192 int rdwr_for_fscache
= 0;
195 if (tcon
->ses
->server
->oplocks
)
196 *oplock
= REQ_OPLOCK
;
198 full_path
= build_path_from_dentry(direntry
, page
);
199 if (IS_ERR(full_path
)) {
200 free_dentry_path(page
);
201 return PTR_ERR(full_path
);
204 /* If we're caching, we need to be able to fill in around partial writes. */
205 if (cifs_fscache_enabled(inode
) && (oflags
& O_ACCMODE
) == O_WRONLY
)
206 rdwr_for_fscache
= 1;
208 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
209 if (tcon
->unix_ext
&& cap_unix(tcon
->ses
) && !tcon
->broken_posix_open
&&
210 (CIFS_UNIX_POSIX_PATH_OPS_CAP
&
211 le64_to_cpu(tcon
->fsUnixInfo
.Capability
))) {
212 rc
= cifs_posix_open(full_path
, &newinode
, inode
->i_sb
, mode
,
213 oflags
, oplock
, &fid
->netfid
, xid
);
216 if (newinode
== NULL
) {
217 /* query inode info */
218 goto cifs_create_get_file_info
;
221 if (S_ISDIR(newinode
->i_mode
)) {
222 CIFSSMBClose(xid
, tcon
, fid
->netfid
);
228 if (!S_ISREG(newinode
->i_mode
)) {
230 * The server may allow us to open things like
231 * FIFOs, but the client isn't set up to deal
232 * with that. If it's not a regular file, just
233 * close it and proceed as if it were a normal
236 CIFSSMBClose(xid
, tcon
, fid
->netfid
);
237 goto cifs_create_get_file_info
;
239 /* success, no need to query */
240 goto cifs_create_set_dentry
;
243 goto cifs_create_get_file_info
;
248 * EIO could indicate that (posix open) operation is not
249 * supported, despite what server claimed in capability
252 * POSIX open in samba versions 3.3.1 and earlier could
253 * incorrectly fail with invalid parameter.
255 tcon
->broken_posix_open
= true;
261 * EREMOTE indicates DFS junction, which is not handled
262 * in posix open. If either that or op not supported
263 * returned, follow the normal lookup.
271 * fallthrough to retry, using older open call, this is case
272 * where server does not support this SMB level, and falsely
273 * claims capability (also get here for DFS case which should be
274 * rare for path not covered on files)
277 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
280 if (OPEN_FMODE(oflags
) & FMODE_READ
)
281 desired_access
|= GENERIC_READ
; /* is this too little? */
282 if (OPEN_FMODE(oflags
) & FMODE_WRITE
)
283 desired_access
|= GENERIC_WRITE
;
284 if (rdwr_for_fscache
== 1)
285 desired_access
|= GENERIC_READ
;
287 disposition
= FILE_OVERWRITE_IF
;
288 if ((oflags
& (O_CREAT
| O_EXCL
)) == (O_CREAT
| O_EXCL
))
289 disposition
= FILE_CREATE
;
290 else if ((oflags
& (O_CREAT
| O_TRUNC
)) == (O_CREAT
| O_TRUNC
))
291 disposition
= FILE_OVERWRITE_IF
;
292 else if ((oflags
& O_CREAT
) == O_CREAT
)
293 disposition
= FILE_OPEN_IF
;
295 cifs_dbg(FYI
, "Create flag not set in create function\n");
298 * BB add processing to set equivalent of mode - e.g. via CreateX with
302 if (!server
->ops
->open
) {
308 * if we're not using unix extensions, see if we need to set
309 * ATTR_READONLY on the create call
311 if (!tcon
->unix_ext
&& (mode
& S_IWUGO
) == 0)
312 create_options
|= CREATE_OPTION_READONLY
;
315 oparms
= (struct cifs_open_parms
) {
318 .desired_access
= desired_access
,
319 .create_options
= cifs_create_options(cifs_sb
, create_options
),
320 .disposition
= disposition
,
325 rc
= server
->ops
->open(xid
, &oparms
, oplock
, buf
);
327 cifs_dbg(FYI
, "cifs_create returned 0x%x\n", rc
);
328 if (rc
== -EACCES
&& rdwr_for_fscache
== 1) {
329 desired_access
&= ~GENERIC_READ
;
330 rdwr_for_fscache
= 2;
335 if (rdwr_for_fscache
== 2)
336 cifs_invalidate_cache(inode
, FSCACHE_INVAL_DIO_WRITE
);
338 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
340 * If Open reported that we actually created a file then we now have to
341 * set the mode if possible.
343 if ((tcon
->unix_ext
) && (*oplock
& CIFS_CREATE_ACTION
)) {
344 struct cifs_unix_set_info_args args
= {
346 .ctime
= NO_CHANGE_64
,
347 .atime
= NO_CHANGE_64
,
348 .mtime
= NO_CHANGE_64
,
352 if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_SET_UID
) {
353 args
.uid
= current_fsuid();
354 if (inode
->i_mode
& S_ISGID
)
355 args
.gid
= inode
->i_gid
;
357 args
.gid
= current_fsgid();
359 args
.uid
= INVALID_UID
; /* no change */
360 args
.gid
= INVALID_GID
; /* no change */
362 CIFSSMBUnixSetFileInfo(xid
, tcon
, &args
, fid
->netfid
,
366 * BB implement mode setting via Windows security
369 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
371 /* Could set r/o dos attribute if mode & 0222 == 0 */
374 cifs_create_get_file_info
:
375 /* server might mask mode so we have to query for it */
377 rc
= cifs_get_inode_info_unix(&newinode
, full_path
, inode
->i_sb
,
382 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
383 /* TODO: Add support for calling POSIX query info here, but passing in fid */
384 rc
= cifs_get_inode_info(&newinode
, full_path
, buf
, inode
->i_sb
, xid
, fid
);
386 if (server
->ops
->set_lease_key
)
387 server
->ops
->set_lease_key(newinode
, fid
);
388 if ((*oplock
& CIFS_CREATE_ACTION
) && S_ISREG(newinode
->i_mode
)) {
389 if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_DYNPERM
)
390 newinode
->i_mode
= mode
;
391 if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_SET_UID
) {
392 newinode
->i_uid
= current_fsuid();
393 if (inode
->i_mode
& S_ISGID
)
394 newinode
->i_gid
= inode
->i_gid
;
396 newinode
->i_gid
= current_fsgid();
402 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
403 cifs_create_set_dentry
:
404 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
406 cifs_dbg(FYI
, "Create worked, get_inode_info failed rc = %d\n",
412 if (S_ISDIR(newinode
->i_mode
)) {
418 d_add(direntry
, newinode
);
421 free_dentry_path(page
);
425 if (server
->ops
->close
)
426 server
->ops
->close(xid
, tcon
, fid
);
433 cifs_atomic_open(struct inode
*inode
, struct dentry
*direntry
,
434 struct file
*file
, unsigned oflags
, umode_t mode
)
438 struct tcon_link
*tlink
;
439 struct cifs_tcon
*tcon
;
440 struct TCP_Server_Info
*server
;
441 struct cifs_fid fid
= {};
442 struct cifs_pending_open open
;
444 struct cifsFileInfo
*file_info
;
445 struct cifs_open_info_data buf
= {};
447 if (unlikely(cifs_forced_shutdown(CIFS_SB(inode
->i_sb
))))
451 * Posix open is only called (at lookup time) for file create now. For
452 * opens (rather than creates), because we do not know if it is a file
453 * or directory yet, and current Samba no longer allows us to do posix
454 * open on dirs, we could end up wasting an open call on what turns out
455 * to be a dir. For file opens, we wait to call posix open till
456 * cifs_open. It could be added to atomic_open in the future but the
457 * performance tradeoff of the extra network request when EISDIR or
458 * EACCES is returned would have to be weighed against the 50% reduction
459 * in network traffic in the other paths.
461 if (!(oflags
& O_CREAT
)) {
465 * Check for hashed negative dentry. We have already revalidated
466 * the dentry and it is fine. No need to perform another lookup.
468 if (!d_in_lookup(direntry
))
471 res
= cifs_lookup(inode
, direntry
, 0);
475 return finish_no_open(file
, res
);
480 cifs_dbg(FYI
, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
481 inode
, direntry
, direntry
);
483 tlink
= cifs_sb_tlink(CIFS_SB(inode
->i_sb
));
489 tcon
= tlink_tcon(tlink
);
491 rc
= check_name(direntry
, tcon
);
495 server
= tcon
->ses
->server
;
497 if (server
->ops
->new_lease_key
)
498 server
->ops
->new_lease_key(&fid
);
500 cifs_add_pending_open(&fid
, tlink
, &open
);
502 rc
= cifs_do_create(inode
, direntry
, xid
, tlink
, oflags
, mode
,
503 &oplock
, &fid
, &buf
);
505 cifs_del_pending_open(&open
);
509 if ((oflags
& (O_CREAT
| O_EXCL
)) == (O_CREAT
| O_EXCL
))
510 file
->f_mode
|= FMODE_CREATED
;
512 rc
= finish_open(file
, direntry
, generic_file_open
);
514 if (server
->ops
->close
)
515 server
->ops
->close(xid
, tcon
, &fid
);
516 cifs_del_pending_open(&open
);
520 if (file
->f_flags
& O_DIRECT
&&
521 CIFS_SB(inode
->i_sb
)->mnt_cifs_flags
& CIFS_MOUNT_STRICT_IO
) {
522 if (CIFS_SB(inode
->i_sb
)->mnt_cifs_flags
& CIFS_MOUNT_NO_BRL
)
523 file
->f_op
= &cifs_file_direct_nobrl_ops
;
525 file
->f_op
= &cifs_file_direct_ops
;
528 file_info
= cifs_new_fileinfo(&fid
, file
, tlink
, oplock
, buf
.symlink_target
);
529 if (file_info
== NULL
) {
530 if (server
->ops
->close
)
531 server
->ops
->close(xid
, tcon
, &fid
);
532 cifs_del_pending_open(&open
);
537 fscache_use_cookie(cifs_inode_cookie(file_inode(file
)),
538 file
->f_mode
& FMODE_WRITE
);
541 cifs_put_tlink(tlink
);
544 cifs_free_open_info(&buf
);
548 int cifs_create(struct mnt_idmap
*idmap
, struct inode
*inode
,
549 struct dentry
*direntry
, umode_t mode
, bool excl
)
552 unsigned int xid
= get_xid();
554 * BB below access is probably too much for mknod to request
555 * but we have to do query and setpathinfo so requesting
556 * less could fail (unless we want to request getatr and setatr
557 * permissions (only). At least for POSIX we do not have to
560 unsigned oflags
= O_EXCL
| O_CREAT
| O_RDWR
;
561 struct tcon_link
*tlink
;
562 struct cifs_tcon
*tcon
;
563 struct TCP_Server_Info
*server
;
566 struct cifs_open_info_data buf
= {};
568 cifs_dbg(FYI
, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
569 inode
, direntry
, direntry
);
571 if (unlikely(cifs_forced_shutdown(CIFS_SB(inode
->i_sb
)))) {
576 tlink
= cifs_sb_tlink(CIFS_SB(inode
->i_sb
));
581 tcon
= tlink_tcon(tlink
);
582 server
= tcon
->ses
->server
;
584 if (server
->ops
->new_lease_key
)
585 server
->ops
->new_lease_key(&fid
);
587 rc
= cifs_do_create(inode
, direntry
, xid
, tlink
, oflags
, mode
, &oplock
, &fid
, &buf
);
588 if (!rc
&& server
->ops
->close
)
589 server
->ops
->close(xid
, tcon
, &fid
);
591 cifs_free_open_info(&buf
);
592 cifs_put_tlink(tlink
);
598 int cifs_mknod(struct mnt_idmap
*idmap
, struct inode
*inode
,
599 struct dentry
*direntry
, umode_t mode
, dev_t device_number
)
603 struct cifs_sb_info
*cifs_sb
;
604 struct tcon_link
*tlink
;
605 struct cifs_tcon
*tcon
;
606 const char *full_path
;
609 if (!old_valid_dev(device_number
))
612 cifs_sb
= CIFS_SB(inode
->i_sb
);
613 if (unlikely(cifs_forced_shutdown(cifs_sb
)))
616 tlink
= cifs_sb_tlink(cifs_sb
);
618 return PTR_ERR(tlink
);
620 page
= alloc_dentry_path();
621 tcon
= tlink_tcon(tlink
);
624 full_path
= build_path_from_dentry(direntry
, page
);
625 if (IS_ERR(full_path
)) {
626 rc
= PTR_ERR(full_path
);
630 trace_smb3_mknod_enter(xid
, tcon
->ses
->Suid
, tcon
->tid
, full_path
);
632 rc
= tcon
->ses
->server
->ops
->make_node(xid
, inode
, direntry
, tcon
,
638 trace_smb3_mknod_err(xid
, tcon
->ses
->Suid
, tcon
->tid
, rc
);
640 trace_smb3_mknod_done(xid
, tcon
->ses
->Suid
, tcon
->tid
);
642 free_dentry_path(page
);
644 cifs_put_tlink(tlink
);
649 cifs_lookup(struct inode
*parent_dir_inode
, struct dentry
*direntry
,
653 int rc
= 0; /* to get around spurious gcc warning, set to zero here */
654 struct cifs_sb_info
*cifs_sb
;
655 struct tcon_link
*tlink
;
656 struct cifs_tcon
*pTcon
;
657 struct inode
*newInode
= NULL
;
658 const char *full_path
;
664 cifs_dbg(FYI
, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
665 parent_dir_inode
, direntry
, direntry
);
667 /* check whether path exists */
669 cifs_sb
= CIFS_SB(parent_dir_inode
->i_sb
);
670 tlink
= cifs_sb_tlink(cifs_sb
);
673 return ERR_CAST(tlink
);
675 pTcon
= tlink_tcon(tlink
);
677 rc
= check_name(direntry
, pTcon
);
679 cifs_put_tlink(tlink
);
684 /* can not grab the rename sem here since it would
685 deadlock in the cases (beginning of sys_rename itself)
686 in which we already have the sb rename sem */
687 page
= alloc_dentry_path();
688 full_path
= build_path_from_dentry(direntry
, page
);
689 if (IS_ERR(full_path
)) {
690 cifs_put_tlink(tlink
);
692 free_dentry_path(page
);
693 return ERR_CAST(full_path
);
696 if (d_really_is_positive(direntry
)) {
697 cifs_dbg(FYI
, "non-NULL inode in lookup\n");
699 cifs_dbg(FYI
, "NULL inode in lookup\n");
701 cifs_dbg(FYI
, "Full path: %s inode = 0x%p\n",
702 full_path
, d_inode(direntry
));
705 if (pTcon
->posix_extensions
) {
706 rc
= smb311_posix_get_inode_info(&newInode
, full_path
, NULL
,
707 parent_dir_inode
->i_sb
, xid
);
708 } else if (pTcon
->unix_ext
) {
709 rc
= cifs_get_inode_info_unix(&newInode
, full_path
,
710 parent_dir_inode
->i_sb
, xid
);
712 rc
= cifs_get_inode_info(&newInode
, full_path
, NULL
,
713 parent_dir_inode
->i_sb
, xid
, NULL
);
717 /* since paths are not looked up by component - the parent
718 directories are presumed to be good here */
719 renew_parental_timestamps(direntry
);
720 } else if (rc
== -EAGAIN
&& retry_count
++ < 10) {
722 } else if (rc
== -ENOENT
) {
723 cifs_set_time(direntry
, jiffies
);
727 cifs_dbg(FYI
, "Unexpected lookup error %d\n", rc
);
728 /* We special case check for Access Denied - since that
729 is a common return code */
731 newInode
= ERR_PTR(rc
);
733 free_dentry_path(page
);
734 cifs_put_tlink(tlink
);
736 return d_splice_alias(newInode
, direntry
);
740 cifs_d_revalidate(struct dentry
*direntry
, unsigned int flags
)
745 if (flags
& LOOKUP_RCU
)
748 if (d_really_is_positive(direntry
)) {
749 inode
= d_inode(direntry
);
750 if ((flags
& LOOKUP_REVAL
) && !CIFS_CACHE_READ(CIFS_I(inode
)))
751 CIFS_I(inode
)->time
= 0; /* force reval */
753 rc
= cifs_revalidate_dentry(direntry
);
755 cifs_dbg(FYI
, "cifs_revalidate_dentry failed with rc=%d", rc
);
760 * Those errors mean the dentry is invalid
761 * (file was deleted or recreated)
766 * Otherwise some unexpected error happened
767 * report it as-is to VFS layer
774 * If the inode wasn't known to be a dfs entry when
775 * the dentry was instantiated, such as when created
776 * via ->readdir(), it needs to be set now since the
777 * attributes will have been updated by
778 * cifs_revalidate_dentry().
780 if (IS_AUTOMOUNT(inode
) &&
781 !(direntry
->d_flags
& DCACHE_NEED_AUTOMOUNT
)) {
782 spin_lock(&direntry
->d_lock
);
783 direntry
->d_flags
|= DCACHE_NEED_AUTOMOUNT
;
784 spin_unlock(&direntry
->d_lock
);
792 * This may be nfsd (or something), anyway, we can't see the
793 * intent of this. So, since this can be for creation, drop it.
799 * Drop the negative dentry, in order to make sure to use the
800 * case sensitive name which is specified by user if this is
803 if (flags
& (LOOKUP_CREATE
| LOOKUP_RENAME_TARGET
))
806 if (time_after(jiffies
, cifs_get_time(direntry
) + HZ
) || !lookupCacheEnabled
)
812 /* static int cifs_d_delete(struct dentry *direntry)
816 cifs_dbg(FYI, "In cifs d_delete, name = %pd\n", direntry);
821 const struct dentry_operations cifs_dentry_ops
= {
822 .d_revalidate
= cifs_d_revalidate
,
823 .d_automount
= cifs_d_automount
,
824 /* d_delete: cifs_d_delete, */ /* not needed except for debugging */
827 static int cifs_ci_hash(const struct dentry
*dentry
, struct qstr
*q
)
829 struct nls_table
*codepage
= CIFS_SB(dentry
->d_sb
)->local_nls
;
834 hash
= init_name_hash(dentry
);
835 for (i
= 0; i
< q
->len
; i
+= charlen
) {
836 charlen
= codepage
->char2uni(&q
->name
[i
], q
->len
- i
, &c
);
837 /* error out if we can't convert the character */
838 if (unlikely(charlen
< 0))
840 hash
= partial_name_hash(cifs_toupper(c
), hash
);
842 q
->hash
= end_name_hash(hash
);
847 static int cifs_ci_compare(const struct dentry
*dentry
,
848 unsigned int len
, const char *str
, const struct qstr
*name
)
850 struct nls_table
*codepage
= CIFS_SB(dentry
->d_sb
)->local_nls
;
855 * We make the assumption here that uppercase characters in the local
856 * codepage are always the same length as their lowercase counterparts.
858 * If that's ever not the case, then this will fail to match it.
860 if (name
->len
!= len
)
863 for (i
= 0; i
< len
; i
+= l1
) {
864 /* Convert characters in both strings to UTF-16. */
865 l1
= codepage
->char2uni(&str
[i
], len
- i
, &c1
);
866 l2
= codepage
->char2uni(&name
->name
[i
], name
->len
- i
, &c2
);
869 * If we can't convert either character, just declare it to
870 * be 1 byte long and compare the original byte.
872 if (unlikely(l1
< 0 && l2
< 0)) {
873 if (str
[i
] != name
->name
[i
])
880 * Here, we again ass|u|me that upper/lowercase versions of
881 * a character are the same length in the local NLS.
886 /* Now compare uppercase versions of these characters */
887 if (cifs_toupper(c1
) != cifs_toupper(c2
))
894 const struct dentry_operations cifs_ci_dentry_ops
= {
895 .d_revalidate
= cifs_d_revalidate
,
896 .d_hash
= cifs_ci_hash
,
897 .d_compare
= cifs_ci_compare
,
898 .d_automount
= cifs_d_automount
,