blob: 166f14b2400bff12d22df44918186b93eb91766d [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;
Daniel Rosenberga56a1052017-05-15 14:03:15 -070037 struct inode *inode;
38 struct sdcardfs_inode_data *data;
Daniel Campello35c9e242015-07-20 16:23:50 -070039
Daniel Campellod1d080c2015-07-20 16:27:37 -070040 if (flags & LOOKUP_RCU)
Daniel Campello35c9e242015-07-20 16:23:50 -070041 return -ECHILD;
42
43 spin_lock(&dentry->d_lock);
44 if (IS_ROOT(dentry)) {
45 spin_unlock(&dentry->d_lock);
46 return 1;
47 }
48 spin_unlock(&dentry->d_lock);
49
50 /* check uninitialized obb_dentry and
Daniel Rosenberg5e024f62017-03-16 17:42:58 -070051 * whether the base obbpath has been changed or not
52 */
Daniel Campello35c9e242015-07-20 16:23:50 -070053 if (is_obbpath_invalid(dentry)) {
54 d_drop(dentry);
55 return 0;
56 }
57
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);
64
Daniel Rosenberg6bf837d2017-04-24 19:49:02 -070065 if ((lower_dentry->d_flags & DCACHE_OP_REVALIDATE)) {
66 err = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
67 if (err == 0) {
68 d_drop(dentry);
69 goto out;
70 }
71 }
72
Daniel Campello35c9e242015-07-20 16:23:50 -070073 spin_lock(&lower_dentry->d_lock);
74 if (d_unhashed(lower_dentry)) {
75 spin_unlock(&lower_dentry->d_lock);
76 d_drop(dentry);
77 err = 0;
78 goto out;
79 }
80 spin_unlock(&lower_dentry->d_lock);
81
82 if (parent_lower_dentry != lower_cur_parent_dentry) {
83 d_drop(dentry);
84 err = 0;
85 goto out;
86 }
87
88 if (dentry < lower_dentry) {
89 spin_lock(&dentry->d_lock);
Daniel Rosenbergdae31f82017-03-08 17:11:51 -080090 spin_lock_nested(&lower_dentry->d_lock, DENTRY_D_LOCK_NESTED);
Daniel Campello35c9e242015-07-20 16:23:50 -070091 } else {
92 spin_lock(&lower_dentry->d_lock);
Daniel Rosenbergdae31f82017-03-08 17:11:51 -080093 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
Daniel Campello35c9e242015-07-20 16:23:50 -070094 }
95
Daniel Rosenberg721274a2017-03-08 17:20:02 -080096 if (!qstr_case_eq(&dentry->d_name, &lower_dentry->d_name)) {
Daniel Campello35c9e242015-07-20 16:23:50 -070097 __d_drop(dentry);
98 err = 0;
99 }
100
101 if (dentry < lower_dentry) {
102 spin_unlock(&lower_dentry->d_lock);
103 spin_unlock(&dentry->d_lock);
104 } else {
105 spin_unlock(&dentry->d_lock);
106 spin_unlock(&lower_dentry->d_lock);
107 }
Daniel Rosenberga56a1052017-05-15 14:03:15 -0700108 if (!err)
109 goto out;
110
111 /* If our top's inode is gone, we may be out of date */
Daniel Rosenbergdb950482017-05-22 13:23:56 -0700112 inode = igrab(d_inode(dentry));
Daniel Rosenberga56a1052017-05-15 14:03:15 -0700113 if (inode) {
114 data = top_data_get(SDCARDFS_I(inode));
Daniel Rosenbergdb950482017-05-22 13:23:56 -0700115 if (!data || data->abandoned) {
Daniel Rosenberga56a1052017-05-15 14:03:15 -0700116 d_drop(dentry);
117 err = 0;
118 }
Daniel Rosenbergdb950482017-05-22 13:23:56 -0700119 if (data)
120 data_put(data);
121 iput(inode);
Daniel Rosenberga56a1052017-05-15 14:03:15 -0700122 }
Daniel Campello35c9e242015-07-20 16:23:50 -0700123
124out:
125 dput(parent_dentry);
126 dput(lower_cur_parent_dentry);
127 sdcardfs_put_lower_path(parent_dentry, &parent_lower_path);
128 sdcardfs_put_real_lower(dentry, &lower_path);
129 return err;
130}
131
132static void sdcardfs_d_release(struct dentry *dentry)
133{
Daniel Rosenberga0838172018-04-11 16:19:10 -0700134 if (!dentry || !dentry->d_fsdata)
135 return;
Daniel Campello35c9e242015-07-20 16:23:50 -0700136 /* release and reset the lower paths */
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700137 if (has_graft_path(dentry))
Daniel Campello35c9e242015-07-20 16:23:50 -0700138 sdcardfs_put_reset_orig_path(dentry);
Daniel Campello35c9e242015-07-20 16:23:50 -0700139 sdcardfs_put_reset_lower_path(dentry);
140 free_dentry_private_data(dentry);
Daniel Campello35c9e242015-07-20 16:23:50 -0700141}
142
143static int sdcardfs_hash_ci(const struct dentry *dentry,
Daniel Campellod1d080c2015-07-20 16:27:37 -0700144 struct qstr *qstr)
Daniel Campello35c9e242015-07-20 16:23:50 -0700145{
146 /*
147 * This function is copy of vfat_hashi.
148 * FIXME Should we support national language?
149 * Refer to vfat_hashi()
150 * struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
151 */
152 const unsigned char *name;
153 unsigned int len;
154 unsigned long hash;
155
156 name = qstr->name;
Daniel Campello35c9e242015-07-20 16:23:50 -0700157 len = qstr->len;
158
Amit Pundir48bc6d32016-08-04 21:04:31 +0530159 hash = init_name_hash(dentry);
Daniel Campello35c9e242015-07-20 16:23:50 -0700160 while (len--)
Daniel Campello35c9e242015-07-20 16:23:50 -0700161 hash = partial_name_hash(tolower(*name++), hash);
162 qstr->hash = end_name_hash(hash);
163
164 return 0;
165}
166
167/*
168 * Case insensitive compare of two vfat names.
169 */
Amit Pundirc9bae392016-08-08 12:27:33 +0530170static int sdcardfs_cmp_ci(const struct dentry *dentry,
Daniel Campello35c9e242015-07-20 16:23:50 -0700171 unsigned int len, const char *str, const struct qstr *name)
172{
Daniel Rosenbergd64126c2017-03-16 19:33:35 -0700173 /* FIXME Should we support national language? */
Daniel Campello35c9e242015-07-20 16:23:50 -0700174
Daniel Campello35c9e242015-07-20 16:23:50 -0700175 if (name->len == len) {
Daniel Rosenberg721274a2017-03-08 17:20:02 -0800176 if (str_n_case_eq(name->name, str, len))
Daniel Campello35c9e242015-07-20 16:23:50 -0700177 return 0;
178 }
179 return 1;
180}
181
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700182static void sdcardfs_canonical_path(const struct path *path,
183 struct path *actual_path)
184{
Daniel Rosenberg973117c2016-04-22 00:00:14 -0700185 sdcardfs_get_real_lower(path->dentry, actual_path);
186}
187
Daniel Campello35c9e242015-07-20 16:23:50 -0700188const struct dentry_operations sdcardfs_ci_dops = {
189 .d_revalidate = sdcardfs_d_revalidate,
190 .d_release = sdcardfs_d_release,
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700191 .d_hash = sdcardfs_hash_ci,
Daniel Campello35c9e242015-07-20 16:23:50 -0700192 .d_compare = sdcardfs_cmp_ci,
Daniel Rosenberg973117c2016-04-22 00:00:14 -0700193 .d_canonical_path = sdcardfs_canonical_path,
Daniel Campello35c9e242015-07-20 16:23:50 -0700194};
195