ANDROID: sdcardfs: declare MODULE_ALIAS_FS
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / fs / sdcardfs / dentry.c
CommitLineData
ee184c81
DC
1/*
2 * fs/sdcardfs/dentry.c
3 *
4 * Copyright (c) 2013 Samsung Electronics Co. Ltd
5 * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun,
6 * Sunghwan Yun, Sungjong Seo
7 *
8 * This program has been developed as a stackable file system based on
9 * the WrapFS which written by
10 *
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
15 *
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.
19 */
20
21#include "sdcardfs.h"
22#include "linux/ctype.h"
23
24/*
25 * returns: -ERRNO if error (returned to user)
26 * 0: tell VFS to invalidate dentry
27 * 1: dentry is valid
28 */
542a676e 29static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags)
ee184c81
DC
30{
31 int err = 1;
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;
37
542a676e 38 if (flags & LOOKUP_RCU)
ee184c81
DC
39 return -ECHILD;
40
41 spin_lock(&dentry->d_lock);
42 if (IS_ROOT(dentry)) {
43 spin_unlock(&dentry->d_lock);
44 return 1;
45 }
46 spin_unlock(&dentry->d_lock);
47
48 /* check uninitialized obb_dentry and
49 * whether the base obbpath has been changed or not */
50 if (is_obbpath_invalid(dentry)) {
51 d_drop(dentry);
52 return 0;
53 }
54
55 parent_dentry = dget_parent(dentry);
56 sdcardfs_get_lower_path(parent_dentry, &parent_lower_path);
57 sdcardfs_get_real_lower(dentry, &lower_path);
58 parent_lower_dentry = parent_lower_path.dentry;
59 lower_dentry = lower_path.dentry;
60 lower_cur_parent_dentry = dget_parent(lower_dentry);
61
62 spin_lock(&lower_dentry->d_lock);
63 if (d_unhashed(lower_dentry)) {
64 spin_unlock(&lower_dentry->d_lock);
65 d_drop(dentry);
66 err = 0;
67 goto out;
68 }
69 spin_unlock(&lower_dentry->d_lock);
70
71 if (parent_lower_dentry != lower_cur_parent_dentry) {
72 d_drop(dentry);
73 err = 0;
74 goto out;
75 }
76
77 if (dentry < lower_dentry) {
78 spin_lock(&dentry->d_lock);
ea97094b 79 spin_lock_nested(&lower_dentry->d_lock, DENTRY_D_LOCK_NESTED);
ee184c81
DC
80 } else {
81 spin_lock(&lower_dentry->d_lock);
ea97094b 82 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
ee184c81
DC
83 }
84
16e0ee27 85 if (!qstr_case_eq(&dentry->d_name, &lower_dentry->d_name)) {
ee184c81
DC
86 __d_drop(dentry);
87 err = 0;
88 }
89
90 if (dentry < lower_dentry) {
91 spin_unlock(&lower_dentry->d_lock);
92 spin_unlock(&dentry->d_lock);
93 } else {
94 spin_unlock(&dentry->d_lock);
95 spin_unlock(&lower_dentry->d_lock);
96 }
97
98out:
99 dput(parent_dentry);
100 dput(lower_cur_parent_dentry);
101 sdcardfs_put_lower_path(parent_dentry, &parent_lower_path);
102 sdcardfs_put_real_lower(dentry, &lower_path);
103 return err;
104}
105
106static void sdcardfs_d_release(struct dentry *dentry)
107{
108 /* release and reset the lower paths */
109 if(has_graft_path(dentry)) {
110 sdcardfs_put_reset_orig_path(dentry);
111 }
112 sdcardfs_put_reset_lower_path(dentry);
113 free_dentry_private_data(dentry);
114 return;
115}
116
117static int sdcardfs_hash_ci(const struct dentry *dentry,
118 const struct inode *inode, struct qstr *qstr)
119{
120 /*
121 * This function is copy of vfat_hashi.
122 * FIXME Should we support national language?
123 * Refer to vfat_hashi()
124 * struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
125 */
126 const unsigned char *name;
127 unsigned int len;
128 unsigned long hash;
129
130 name = qstr->name;
131 //len = vfat_striptail_len(qstr);
132 len = qstr->len;
133
134 hash = init_name_hash();
135 while (len--)
136 //hash = partial_name_hash(nls_tolower(t, *name++), hash);
137 hash = partial_name_hash(tolower(*name++), hash);
138 qstr->hash = end_name_hash(hash);
139
140 return 0;
141}
142
143/*
144 * Case insensitive compare of two vfat names.
145 */
146static int sdcardfs_cmp_ci(const struct dentry *parent,
147 const struct inode *pinode,
148 const struct dentry *dentry, const struct inode *inode,
149 unsigned int len, const char *str, const struct qstr *name)
150{
151 /* This function is copy of vfat_cmpi */
152 // FIXME Should we support national language?
153 //struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
154 //unsigned int alen, blen;
155
156 /* A filename cannot end in '.' or we treat it like it has none */
157 /*
158 alen = vfat_striptail_len(name);
159 blen = __vfat_striptail_len(len, str);
160 if (alen == blen) {
161 if (nls_strnicmp(t, name->name, str, alen) == 0)
162 return 0;
163 }
164 */
165 if (name->len == len) {
16e0ee27 166 if (str_n_case_eq(name->name, str, len))
ee184c81
DC
167 return 0;
168 }
169 return 1;
170}
171
3e336725
DR
172static void sdcardfs_canonical_path(const struct path *path, struct path *actual_path) {
173 sdcardfs_get_real_lower(path->dentry, actual_path);
174}
175
ee184c81
DC
176const struct dentry_operations sdcardfs_ci_dops = {
177 .d_revalidate = sdcardfs_d_revalidate,
178 .d_release = sdcardfs_d_release,
179 .d_hash = sdcardfs_hash_ci,
180 .d_compare = sdcardfs_cmp_ci,
3e336725 181 .d_canonical_path = sdcardfs_canonical_path,
ee184c81
DC
182};
183