blob: afd97710f7ad051cefb5792a32e946af755491b2 [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
Daniel Rosenberg5e024f62017-03-16 17:42:58 -070049 * whether the base obbpath has been changed or not
50 */
Daniel Campello35c9e242015-07-20 16:23:50 -070051 if (is_obbpath_invalid(dentry)) {
52 d_drop(dentry);
53 return 0;
54 }
55
56 parent_dentry = dget_parent(dentry);
57 sdcardfs_get_lower_path(parent_dentry, &parent_lower_path);
58 sdcardfs_get_real_lower(dentry, &lower_path);
59 parent_lower_dentry = parent_lower_path.dentry;
60 lower_dentry = lower_path.dentry;
61 lower_cur_parent_dentry = dget_parent(lower_dentry);
62
63 spin_lock(&lower_dentry->d_lock);
64 if (d_unhashed(lower_dentry)) {
65 spin_unlock(&lower_dentry->d_lock);
66 d_drop(dentry);
67 err = 0;
68 goto out;
69 }
70 spin_unlock(&lower_dentry->d_lock);
71
72 if (parent_lower_dentry != lower_cur_parent_dentry) {
73 d_drop(dentry);
74 err = 0;
75 goto out;
76 }
77
78 if (dentry < lower_dentry) {
79 spin_lock(&dentry->d_lock);
Daniel Rosenbergdae31f82017-03-08 17:11:51 -080080 spin_lock_nested(&lower_dentry->d_lock, DENTRY_D_LOCK_NESTED);
Daniel Campello35c9e242015-07-20 16:23:50 -070081 } else {
82 spin_lock(&lower_dentry->d_lock);
Daniel Rosenbergdae31f82017-03-08 17:11:51 -080083 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
Daniel Campello35c9e242015-07-20 16:23:50 -070084 }
85
Daniel Rosenberg721274a2017-03-08 17:20:02 -080086 if (!qstr_case_eq(&dentry->d_name, &lower_dentry->d_name)) {
Daniel Campello35c9e242015-07-20 16:23:50 -070087 __d_drop(dentry);
88 err = 0;
89 }
90
91 if (dentry < lower_dentry) {
92 spin_unlock(&lower_dentry->d_lock);
93 spin_unlock(&dentry->d_lock);
94 } else {
95 spin_unlock(&dentry->d_lock);
96 spin_unlock(&lower_dentry->d_lock);
97 }
98
99out:
100 dput(parent_dentry);
101 dput(lower_cur_parent_dentry);
102 sdcardfs_put_lower_path(parent_dentry, &parent_lower_path);
103 sdcardfs_put_real_lower(dentry, &lower_path);
104 return err;
105}
106
107static void sdcardfs_d_release(struct dentry *dentry)
108{
109 /* release and reset the lower paths */
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700110 if (has_graft_path(dentry))
Daniel Campello35c9e242015-07-20 16:23:50 -0700111 sdcardfs_put_reset_orig_path(dentry);
Daniel Campello35c9e242015-07-20 16:23:50 -0700112 sdcardfs_put_reset_lower_path(dentry);
113 free_dentry_private_data(dentry);
Daniel Campello35c9e242015-07-20 16:23:50 -0700114}
115
116static int sdcardfs_hash_ci(const struct dentry *dentry,
Daniel Campellod1d080c2015-07-20 16:27:37 -0700117 struct qstr *qstr)
Daniel Campello35c9e242015-07-20 16:23:50 -0700118{
119 /*
120 * This function is copy of vfat_hashi.
121 * FIXME Should we support national language?
122 * Refer to vfat_hashi()
123 * struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
124 */
125 const unsigned char *name;
126 unsigned int len;
127 unsigned long hash;
128
129 name = qstr->name;
Daniel Campello35c9e242015-07-20 16:23:50 -0700130 len = qstr->len;
131
Amit Pundir48bc6d32016-08-04 21:04:31 +0530132 hash = init_name_hash(dentry);
Daniel Campello35c9e242015-07-20 16:23:50 -0700133 while (len--)
Daniel Campello35c9e242015-07-20 16:23:50 -0700134 hash = partial_name_hash(tolower(*name++), hash);
135 qstr->hash = end_name_hash(hash);
136
137 return 0;
138}
139
140/*
141 * Case insensitive compare of two vfat names.
142 */
Amit Pundirc9bae392016-08-08 12:27:33 +0530143static int sdcardfs_cmp_ci(const struct dentry *dentry,
Daniel Campello35c9e242015-07-20 16:23:50 -0700144 unsigned int len, const char *str, const struct qstr *name)
145{
Daniel Rosenbergd64126c2017-03-16 19:33:35 -0700146 /* FIXME Should we support national language? */
Daniel Campello35c9e242015-07-20 16:23:50 -0700147
Daniel Campello35c9e242015-07-20 16:23:50 -0700148 if (name->len == len) {
Daniel Rosenberg721274a2017-03-08 17:20:02 -0800149 if (str_n_case_eq(name->name, str, len))
Daniel Campello35c9e242015-07-20 16:23:50 -0700150 return 0;
151 }
152 return 1;
153}
154
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700155static void sdcardfs_canonical_path(const struct path *path,
156 struct path *actual_path)
157{
Daniel Rosenberg973117c2016-04-22 00:00:14 -0700158 sdcardfs_get_real_lower(path->dentry, actual_path);
159}
160
Daniel Campello35c9e242015-07-20 16:23:50 -0700161const struct dentry_operations sdcardfs_ci_dops = {
162 .d_revalidate = sdcardfs_d_revalidate,
163 .d_release = sdcardfs_d_release,
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700164 .d_hash = sdcardfs_hash_ci,
Daniel Campello35c9e242015-07-20 16:23:50 -0700165 .d_compare = sdcardfs_cmp_ci,
Daniel Rosenberg973117c2016-04-22 00:00:14 -0700166 .d_canonical_path = sdcardfs_canonical_path,
Daniel Campello35c9e242015-07-20 16:23:50 -0700167};
168