blob: e4156a6fa8c8f2b70cff734f585fda2254773d1b [file] [log] [blame]
Daniel Campello35c9e242015-07-20 16:23:50 -07001/*
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 */
Daniel Campellod1d080c2015-07-20 16:27:37 -070029static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags)
Daniel Campello35c9e242015-07-20 16:23:50 -070030{
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
Daniel Campellod1d080c2015-07-20 16:27:37 -070038 if (flags & LOOKUP_RCU)
Daniel Campello35c9e242015-07-20 16:23:50 -070039 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);
79 spin_lock(&lower_dentry->d_lock);
80 } else {
81 spin_lock(&lower_dentry->d_lock);
82 spin_lock(&dentry->d_lock);
83 }
84
85 if (dentry->d_name.len != lower_dentry->d_name.len) {
86 __d_drop(dentry);
87 err = 0;
88 } else if (strncasecmp(dentry->d_name.name, lower_dentry->d_name.name,
89 dentry->d_name.len) != 0) {
90 __d_drop(dentry);
91 err = 0;
92 }
93
94 if (dentry < lower_dentry) {
95 spin_unlock(&lower_dentry->d_lock);
96 spin_unlock(&dentry->d_lock);
97 } else {
98 spin_unlock(&dentry->d_lock);
99 spin_unlock(&lower_dentry->d_lock);
100 }
101
102out:
103 dput(parent_dentry);
104 dput(lower_cur_parent_dentry);
105 sdcardfs_put_lower_path(parent_dentry, &parent_lower_path);
106 sdcardfs_put_real_lower(dentry, &lower_path);
107 return err;
108}
109
110static void sdcardfs_d_release(struct dentry *dentry)
111{
112 /* release and reset the lower paths */
113 if(has_graft_path(dentry)) {
114 sdcardfs_put_reset_orig_path(dentry);
115 }
116 sdcardfs_put_reset_lower_path(dentry);
117 free_dentry_private_data(dentry);
118 return;
119}
120
121static int sdcardfs_hash_ci(const struct dentry *dentry,
Daniel Campellod1d080c2015-07-20 16:27:37 -0700122 struct qstr *qstr)
Daniel Campello35c9e242015-07-20 16:23:50 -0700123{
124 /*
125 * This function is copy of vfat_hashi.
126 * FIXME Should we support national language?
127 * Refer to vfat_hashi()
128 * struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
129 */
130 const unsigned char *name;
131 unsigned int len;
132 unsigned long hash;
133
134 name = qstr->name;
135 //len = vfat_striptail_len(qstr);
136 len = qstr->len;
137
Amit Pundir48bc6d32016-08-04 21:04:31 +0530138 hash = init_name_hash(dentry);
Daniel Campello35c9e242015-07-20 16:23:50 -0700139 while (len--)
140 //hash = partial_name_hash(nls_tolower(t, *name++), hash);
141 hash = partial_name_hash(tolower(*name++), hash);
142 qstr->hash = end_name_hash(hash);
143
144 return 0;
145}
146
147/*
148 * Case insensitive compare of two vfat names.
149 */
150static int sdcardfs_cmp_ci(const struct dentry *parent,
Daniel Campellod1d080c2015-07-20 16:27:37 -0700151 const struct dentry *dentry,
Daniel Campello35c9e242015-07-20 16:23:50 -0700152 unsigned int len, const char *str, const struct qstr *name)
153{
154 /* This function is copy of vfat_cmpi */
155 // FIXME Should we support national language?
156 //struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
157 //unsigned int alen, blen;
158
159 /* A filename cannot end in '.' or we treat it like it has none */
160 /*
161 alen = vfat_striptail_len(name);
162 blen = __vfat_striptail_len(len, str);
163 if (alen == blen) {
164 if (nls_strnicmp(t, name->name, str, alen) == 0)
165 return 0;
166 }
167 */
168 if (name->len == len) {
169 if (strncasecmp(name->name, str, len) == 0)
170 return 0;
171 }
172 return 1;
173}
174
Daniel Rosenberg973117c2016-04-22 00:00:14 -0700175static void sdcardfs_canonical_path(const struct path *path, struct path *actual_path) {
176 sdcardfs_get_real_lower(path->dentry, actual_path);
177}
178
Daniel Campello35c9e242015-07-20 16:23:50 -0700179const struct dentry_operations sdcardfs_ci_dops = {
180 .d_revalidate = sdcardfs_d_revalidate,
181 .d_release = sdcardfs_d_release,
182 .d_hash = sdcardfs_hash_ci,
183 .d_compare = sdcardfs_cmp_ci,
Daniel Rosenberg973117c2016-04-22 00:00:14 -0700184 .d_canonical_path = sdcardfs_canonical_path,
Daniel Campello35c9e242015-07-20 16:23:50 -0700185};
186