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
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>
32 #include "cifsproto.h"
33 #include "cifs_debug.h"
34 #include "cifs_fs_sb.h"
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
42 direntry
->d_time
= jiffies
;
43 direntry
= direntry
->d_parent
;
44 } while (!IS_ROOT(direntry
));
47 /* Note: caller must free return buffer */
49 build_path_from_dentry(struct dentry
*direntry
)
57 struct cifs_sb_info
*cifs_sb
= CIFS_SB(direntry
->d_sb
);
58 struct cifsTconInfo
*tcon
= cifs_sb_master_tcon(cifs_sb
);
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);
72 namelen
= pplen
+ dfsplen
;
73 for (temp
= direntry
; !IS_ROOT(temp
);) {
74 namelen
+= (1 + temp
->d_name
.len
);
75 temp
= temp
->d_parent
;
77 cERROR(1, "corrupt dentry");
82 full_path
= kmalloc(namelen
+1, GFP_KERNEL
);
83 if (full_path
== NULL
)
85 full_path
[namelen
] = 0; /* trailing null */
86 for (temp
= direntry
; !IS_ROOT(temp
);) {
87 namelen
-= 1 + temp
->d_name
.len
;
91 full_path
[namelen
] = dirsep
;
92 strncpy(full_path
+ namelen
+ 1, temp
->d_name
.name
,
94 cFYI(0, "name: %s", full_path
+ namelen
);
96 temp
= temp
->d_parent
;
98 cERROR(1, "corrupt dentry");
103 if (namelen
!= pplen
+ dfsplen
) {
104 cERROR(1, "did not end path lookup where expected namelen is %d",
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) */
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 */
120 strncpy(full_path
, tcon
->treeName
, dfsplen
);
121 if (cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_POSIX_PATHS
) {
123 for (i
= 0; i
< dfsplen
; i
++) {
124 if (full_path
[i
] == '\\')
129 strncpy(full_path
+ dfsplen
, CIFS_SB(direntry
->d_sb
)->prepath
, pplen
);
133 static void setup_cifs_dentry(struct cifsTconInfo
*tcon
,
134 struct dentry
*direntry
,
135 struct inode
*newinode
)
138 direntry
->d_op
= &cifs_ci_dentry_ops
;
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
)
152 int create_options
= CREATE_NOT_DIR
;
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
162 int desiredAccess
= GENERIC_READ
| GENERIC_WRITE
;
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
;
174 cifs_sb
= CIFS_SB(inode
->i_sb
);
175 tlink
= cifs_sb_tlink(cifs_sb
);
178 return PTR_ERR(tlink
);
180 tcon
= tlink_tcon(tlink
);
185 if (nd
&& (nd
->flags
& LOOKUP_OPEN
))
186 oflags
= nd
->intent
.open
.file
->f_flags
;
188 oflags
= O_RDONLY
| O_CREAT
;
190 full_path
= build_path_from_dentry(direntry
);
191 if (full_path
== NULL
) {
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 */
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 */
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
;
236 cFYI(1, "Create flag not set in create function");
239 /* BB add processing to set equivalent of mode - e.g. via CreateX with
242 buf
= kmalloc(sizeof(FILE_ALL_INFO
), GFP_KERNEL
);
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
);
261 rc
= -EIO
; /* no NT SMB support fall into legacy open below */
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
);
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
= {
280 .ctime
= NO_CHANGE_64
,
281 .atime
= NO_CHANGE_64
,
282 .mtime
= NO_CHANGE_64
,
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
;
291 args
.gid
= (__u64
) current_fsgid();
293 args
.uid
= NO_CHANGE_64
;
294 args
.gid
= NO_CHANGE_64
;
296 CIFSSMBUnixSetPathInfo(xid
, tcon
, full_path
, &args
,
298 cifs_sb
->mnt_cifs_flags
&
299 CIFS_MOUNT_MAP_SPECIAL_CHR
);
301 /* BB implement mode setting via Windows security
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 */
311 rc
= cifs_get_inode_info_unix(&newinode
, full_path
,
314 rc
= cifs_get_inode_info(&newinode
, full_path
, buf
,
315 inode
->i_sb
, xid
, &fileHandle
);
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
;
325 newinode
->i_gid
= current_fsgid();
330 cifs_create_set_dentry
:
332 setup_cifs_dentry(tcon
, direntry
, newinode
);
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
;
340 filp
= lookup_instantiate_filp(nd
, direntry
, generic_file_open
);
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
) {
350 CIFSSMBClose(xid
, tcon
, fileHandle
);
354 CIFSSMBClose(xid
, tcon
, fileHandle
);
360 cifs_put_tlink(tlink
);
365 int cifs_mknod(struct inode
*inode
, struct dentry
*direntry
, int mode
,
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
;
377 FILE_ALL_INFO
*buf
= NULL
;
378 unsigned int bytes_written
;
379 struct win_dev
*pdev
;
381 if (!old_valid_dev(device_number
))
384 cifs_sb
= CIFS_SB(inode
->i_sb
);
385 tlink
= cifs_sb_tlink(cifs_sb
);
387 return PTR_ERR(tlink
);
389 pTcon
= tlink_tcon(tlink
);
393 full_path
= build_path_from_dentry(direntry
);
394 if (full_path
== NULL
) {
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();
411 args
.uid
= NO_CHANGE_64
;
412 args
.gid
= NO_CHANGE_64
;
414 rc
= CIFSSMBUnixSetPathInfo(xid
, pTcon
, full_path
, &args
,
416 cifs_sb
->mnt_cifs_flags
&
417 CIFS_MOUNT_MAP_SPECIAL_CHR
);
421 rc
= cifs_get_inode_info_unix(&newinode
, full_path
,
424 direntry
->d_op
= &cifs_ci_dentry_ops
;
426 direntry
->d_op
= &cifs_dentry_ops
;
429 d_instantiate(direntry
, newinode
);
433 if (!(cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_UNX_EMUL
))
437 cFYI(1, "sfu compat create special file");
439 buf
= kmalloc(sizeof(FILE_ALL_INFO
), GFP_KERNEL
);
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
);
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
;
460 memcpy(pdev
->type
, "IntxCHR", 8);
462 cpu_to_le64(MAJOR(device_number
));
464 cpu_to_le64(MINOR(device_number
));
465 rc
= CIFSSMBWrite(xid
, pTcon
,
467 sizeof(struct win_dev
),
468 0, &bytes_written
, (char *)pdev
,
470 } else if (S_ISBLK(mode
)) {
471 memcpy(pdev
->type
, "IntxBLK", 8);
473 cpu_to_le64(MAJOR(device_number
));
475 cpu_to_le64(MINOR(device_number
));
476 rc
= CIFSSMBWrite(xid
, pTcon
,
478 sizeof(struct win_dev
),
479 0, &bytes_written
, (char *)pdev
,
481 } /* else if (S_ISFIFO) */
482 CIFSSMBClose(xid
, pTcon
, fileHandle
);
485 /* FIXME: add code here to set EAs */
491 cifs_put_tlink(tlink
);
496 cifs_lookup(struct inode
*parent_dir_inode
, struct dentry
*direntry
,
497 struct nameidata
*nd
)
500 int rc
= 0; /* to get around spurious gcc warning, set to zero here */
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
;
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
);
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
)) {
533 for (i
= 0; i
< direntry
->d_name
.len
; i
++)
534 if (direntry
->d_name
.name
[i
] == '\\') {
535 cFYI(1, "Invalid file name");
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
);
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
) {
560 if (direntry
->d_inode
!= NULL
) {
561 cFYI(1, "non-NULL inode in lookup");
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
,
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
593 if ((rc
== 0) || (rc
== -ENOENT
))
595 else if ((rc
== -EINVAL
) || (rc
!= -EOPNOTSUPP
))
596 pTcon
->broken_posix_open
= true;
599 rc
= cifs_get_inode_info_unix(&newInode
, full_path
,
600 parent_dir_inode
->i_sb
, xid
);
602 rc
= cifs_get_inode_info(&newInode
, full_path
, NULL
,
603 parent_dir_inode
->i_sb
, xid
, NULL
);
605 if ((rc
== 0) && (newInode
!= NULL
)) {
607 direntry
->d_op
= &cifs_ci_dentry_ops
;
609 direntry
->d_op
= &cifs_dentry_ops
;
610 d_add(direntry
, newInode
);
612 filp
= lookup_instantiate_filp(nd
, direntry
,
616 CIFSSMBClose(xid
, pTcon
, fileHandle
);
620 cfile
= cifs_new_fileinfo(fileHandle
, filp
, tlink
,
624 CIFSSMBClose(xid
, pTcon
, fileHandle
);
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
) {
635 direntry
->d_time
= jiffies
;
637 direntry
->d_op
= &cifs_ci_dentry_ops
;
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 */
651 cifs_put_tlink(tlink
);
657 cifs_d_revalidate(struct dentry
*direntry
, struct nameidata
*nd
)
659 if (direntry
->d_inode
) {
660 if (cifs_revalidate_dentry(direntry
))
667 * This may be nfsd (or something), anyway, we can't see the
668 * intent of this. So, since this can be for creation, drop it.
674 * Drop the negative dentry, in order to make sure to use the
675 * case sensitive name which is specified by user if this is
678 if (!(nd
->flags
& (LOOKUP_CONTINUE
| LOOKUP_PARENT
))) {
679 if (nd
->flags
& (LOOKUP_CREATE
| LOOKUP_RENAME_TARGET
))
683 if (time_after(jiffies
, direntry
->d_time
+ HZ
) || !lookupCacheEnabled
)
689 /* static int cifs_d_delete(struct dentry *direntry)
693 cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
698 const struct dentry_operations cifs_dentry_ops
= {
699 .d_revalidate
= cifs_d_revalidate
,
700 /* d_delete: cifs_d_delete, */ /* not needed except for debugging */
703 static int cifs_ci_hash(struct dentry
*dentry
, struct qstr
*q
)
705 struct nls_table
*codepage
= CIFS_SB(dentry
->d_inode
->i_sb
)->local_nls
;
709 hash
= init_name_hash();
710 for (i
= 0; i
< q
->len
; i
++)
711 hash
= partial_name_hash(nls_tolower(codepage
, q
->name
[i
]),
713 q
->hash
= end_name_hash(hash
);
718 static int cifs_ci_compare(struct dentry
*dentry
, struct qstr
*a
,
721 struct nls_table
*codepage
= CIFS_SB(dentry
->d_inode
->i_sb
)->local_nls
;
723 if ((a
->len
== b
->len
) &&
724 (nls_strnicmp(codepage
, a
->name
, b
->name
, a
->len
) == 0))
729 const struct dentry_operations cifs_ci_dentry_ops
= {
730 .d_revalidate
= cifs_d_revalidate
,
731 .d_hash
= cifs_ci_hash
,
732 .d_compare
= cifs_ci_compare
,