blob: cb573f1efbfc41e28c73d272fd32b277de2ce882 [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)) {
Daniel Campello35c9e242015-07-20 16:23:50 -070054 return 0;
55 }
56
57 parent_dentry = dget_parent(dentry);
58 sdcardfs_get_lower_path(parent_dentry, &parent_lower_path);
59 sdcardfs_get_real_lower(dentry, &lower_path);
60 parent_lower_dentry = parent_lower_path.dentry;
61 lower_dentry = lower_path.dentry;
62 lower_cur_parent_dentry = dget_parent(lower_dentry);
63
Daniel Rosenberg6bf837d2017-04-24 19:49:02 -070064 if ((lower_dentry->d_flags & DCACHE_OP_REVALIDATE)) {
65 err = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
66 if (err == 0) {
Daniel Rosenberg6bf837d2017-04-24 19:49:02 -070067 goto out;
68 }
69 }
70
Daniel Campello35c9e242015-07-20 16:23:50 -070071 spin_lock(&lower_dentry->d_lock);
72 if (d_unhashed(lower_dentry)) {
73 spin_unlock(&lower_dentry->d_lock);
Daniel Campello35c9e242015-07-20 16:23:50 -070074 err = 0;
75 goto out;
76 }
77 spin_unlock(&lower_dentry->d_lock);
78
79 if (parent_lower_dentry != lower_cur_parent_dentry) {
Daniel Campello35c9e242015-07-20 16:23:50 -070080 err = 0;
81 goto out;
82 }
83
84 if (dentry < lower_dentry) {
85 spin_lock(&dentry->d_lock);
Daniel Rosenbergdae31f82017-03-08 17:11:51 -080086 spin_lock_nested(&lower_dentry->d_lock, DENTRY_D_LOCK_NESTED);
Daniel Campello35c9e242015-07-20 16:23:50 -070087 } else {
88 spin_lock(&lower_dentry->d_lock);
Daniel Rosenbergdae31f82017-03-08 17:11:51 -080089 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
Daniel Campello35c9e242015-07-20 16:23:50 -070090 }
91
Daniel Rosenberg721274a2017-03-08 17:20:02 -080092 if (!qstr_case_eq(&dentry->d_name, &lower_dentry->d_name)) {
Daniel Campello35c9e242015-07-20 16:23:50 -070093 err = 0;
94 }
95
96 if (dentry < lower_dentry) {
97 spin_unlock(&lower_dentry->d_lock);
98 spin_unlock(&dentry->d_lock);
99 } else {
100 spin_unlock(&dentry->d_lock);
101 spin_unlock(&lower_dentry->d_lock);
102 }
Daniel Rosenberga56a1052017-05-15 14:03:15 -0700103 if (!err)
104 goto out;
105
106 /* If our top's inode is gone, we may be out of date */
Daniel Rosenbergdb950482017-05-22 13:23:56 -0700107 inode = igrab(d_inode(dentry));
Daniel Rosenberga56a1052017-05-15 14:03:15 -0700108 if (inode) {
109 data = top_data_get(SDCARDFS_I(inode));
Daniel Rosenbergdb950482017-05-22 13:23:56 -0700110 if (!data || data->abandoned) {
Daniel Rosenberga56a1052017-05-15 14:03:15 -0700111 err = 0;
112 }
Daniel Rosenbergdb950482017-05-22 13:23:56 -0700113 if (data)
114 data_put(data);
115 iput(inode);
Daniel Rosenberga56a1052017-05-15 14:03:15 -0700116 }
Daniel Campello35c9e242015-07-20 16:23:50 -0700117
118out:
119 dput(parent_dentry);
120 dput(lower_cur_parent_dentry);
121 sdcardfs_put_lower_path(parent_dentry, &parent_lower_path);
122 sdcardfs_put_real_lower(dentry, &lower_path);
123 return err;
124}
125
Daniel Rosenberg80af4332018-07-06 16:24:27 -0700126/* 1 = delete, 0 = cache */
127static int sdcardfs_d_delete(const struct dentry *d)
128{
129 return SDCARDFS_SB(d->d_sb)->options.nocache ? 1 : 0;
130}
131
Daniel Campello35c9e242015-07-20 16:23:50 -0700132static 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,
Daniel Rosenberg80af4332018-07-06 16:24:27 -0700190 .d_delete = sdcardfs_d_delete,
Daniel Campello35c9e242015-07-20 16:23:50 -0700191 .d_release = sdcardfs_d_release,
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700192 .d_hash = sdcardfs_hash_ci,
Daniel Campello35c9e242015-07-20 16:23:50 -0700193 .d_compare = sdcardfs_cmp_ci,
Daniel Rosenberg973117c2016-04-22 00:00:14 -0700194 .d_canonical_path = sdcardfs_canonical_path,
Daniel Campello35c9e242015-07-20 16:23:50 -0700195};
196