4 * Copyright (c) 2013 Samsung Electronics Co. Ltd
5 * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun,
6 * Sunghwan Yun, Sungjong Seo
8 * This program has been developed as a stackable file system based on
9 * the WrapFS which written by
11 * Copyright (c) 1998-2011 Erez Zadok
12 * Copyright (c) 2009 Shrikar Archak
13 * Copyright (c) 2003-2011 Stony Brook University
14 * Copyright (c) 2003-2011 The Research Foundation of SUNY
16 * This file is dual licensed. It may be redistributed and/or modified
17 * under the terms of the Apache 2.0 License OR version 2 of the GNU
18 * General Public License.
22 #include "linux/ctype.h"
25 * returns: -ERRNO if error (returned to user)
26 * 0: tell VFS to invalidate dentry
29 static int sdcardfs_d_revalidate(struct dentry
*dentry
, unsigned int flags
)
32 struct path parent_lower_path
, lower_path
;
33 struct dentry
*parent_dentry
= NULL
;
34 struct dentry
*parent_lower_dentry
= NULL
;
35 struct dentry
*lower_cur_parent_dentry
= NULL
;
36 struct dentry
*lower_dentry
= NULL
;
38 struct sdcardfs_inode_data
*data
;
40 if (flags
& LOOKUP_RCU
)
43 spin_lock(&dentry
->d_lock
);
44 if (IS_ROOT(dentry
)) {
45 spin_unlock(&dentry
->d_lock
);
48 spin_unlock(&dentry
->d_lock
);
50 /* check uninitialized obb_dentry and
51 * whether the base obbpath has been changed or not
53 if (is_obbpath_invalid(dentry
)) {
58 parent_dentry
= dget_parent(dentry
);
59 sdcardfs_get_lower_path(parent_dentry
, &parent_lower_path
);
60 sdcardfs_get_real_lower(dentry
, &lower_path
);
61 parent_lower_dentry
= parent_lower_path
.dentry
;
62 lower_dentry
= lower_path
.dentry
;
63 lower_cur_parent_dentry
= dget_parent(lower_dentry
);
65 if ((lower_dentry
->d_flags
& DCACHE_OP_REVALIDATE
)) {
66 err
= lower_dentry
->d_op
->d_revalidate(lower_dentry
, flags
);
73 spin_lock(&lower_dentry
->d_lock
);
74 if (d_unhashed(lower_dentry
)) {
75 spin_unlock(&lower_dentry
->d_lock
);
80 spin_unlock(&lower_dentry
->d_lock
);
82 if (parent_lower_dentry
!= lower_cur_parent_dentry
) {
88 if (dentry
< lower_dentry
) {
89 spin_lock(&dentry
->d_lock
);
90 spin_lock_nested(&lower_dentry
->d_lock
, DENTRY_D_LOCK_NESTED
);
92 spin_lock(&lower_dentry
->d_lock
);
93 spin_lock_nested(&dentry
->d_lock
, DENTRY_D_LOCK_NESTED
);
96 if (!qstr_case_eq(&dentry
->d_name
, &lower_dentry
->d_name
)) {
101 if (dentry
< lower_dentry
) {
102 spin_unlock(&lower_dentry
->d_lock
);
103 spin_unlock(&dentry
->d_lock
);
105 spin_unlock(&dentry
->d_lock
);
106 spin_unlock(&lower_dentry
->d_lock
);
111 /* If our top's inode is gone, we may be out of date */
112 inode
= igrab(dentry
->d_inode
);
114 data
= top_data_get(SDCARDFS_I(inode
));
115 if (!data
|| data
->abandoned
) {
126 dput(lower_cur_parent_dentry
);
127 sdcardfs_put_lower_path(parent_dentry
, &parent_lower_path
);
128 sdcardfs_put_real_lower(dentry
, &lower_path
);
132 static void sdcardfs_d_release(struct dentry
*dentry
)
134 /* release and reset the lower paths */
135 if (has_graft_path(dentry
))
136 sdcardfs_put_reset_orig_path(dentry
);
137 sdcardfs_put_reset_lower_path(dentry
);
138 free_dentry_private_data(dentry
);
141 static int sdcardfs_hash_ci(const struct dentry
*dentry
,
142 const struct inode
*inode
, struct qstr
*qstr
)
145 * This function is copy of vfat_hashi.
146 * FIXME Should we support national language?
147 * Refer to vfat_hashi()
148 * struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
150 const unsigned char *name
;
157 hash
= init_name_hash();
159 hash
= partial_name_hash(tolower(*name
++), hash
);
160 qstr
->hash
= end_name_hash(hash
);
166 * Case insensitive compare of two vfat names.
168 static int sdcardfs_cmp_ci(const struct dentry
*parent
,
169 const struct inode
*pinode
,
170 const struct dentry
*dentry
, const struct inode
*inode
,
171 unsigned int len
, const char *str
, const struct qstr
*name
)
173 /* FIXME Should we support national language? */
175 if (name
->len
== len
) {
176 if (str_n_case_eq(name
->name
, str
, len
))
182 static void sdcardfs_canonical_path(const struct path
*path
,
183 struct path
*actual_path
)
185 sdcardfs_get_real_lower(path
->dentry
, actual_path
);
188 const struct dentry_operations sdcardfs_ci_dops
= {
189 .d_revalidate
= sdcardfs_d_revalidate
,
190 .d_release
= sdcardfs_d_release
,
191 .d_hash
= sdcardfs_hash_ci
,
192 .d_compare
= sdcardfs_cmp_ci
,
193 .d_canonical_path
= sdcardfs_canonical_path
,