blob: 9d9965afce0d4368f14fefa1d9651d55d99b94a3 [file] [log] [blame]
Daniel Campello3a703812015-07-20 16:23:50 -07001/*
2 * fs/sdcardfs/lookup.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/delay.h"
23
24/* The dentry cache is just so we have properly sized dentries */
25static struct kmem_cache *sdcardfs_dentry_cachep;
26
27int sdcardfs_init_dentry_cache(void)
28{
29 sdcardfs_dentry_cachep =
30 kmem_cache_create("sdcardfs_dentry",
31 sizeof(struct sdcardfs_dentry_info),
32 0, SLAB_RECLAIM_ACCOUNT, NULL);
33
34 return sdcardfs_dentry_cachep ? 0 : -ENOMEM;
35}
36
37void sdcardfs_destroy_dentry_cache(void)
38{
Daniel Rosenberg9189ad72017-03-21 16:29:13 -070039 kmem_cache_destroy(sdcardfs_dentry_cachep);
Daniel Campello3a703812015-07-20 16:23:50 -070040}
41
42void free_dentry_private_data(struct dentry *dentry)
43{
Daniel Campello3a703812015-07-20 16:23:50 -070044 kmem_cache_free(sdcardfs_dentry_cachep, dentry->d_fsdata);
45 dentry->d_fsdata = NULL;
46}
47
48/* allocate new dentry private data */
49int new_dentry_private_data(struct dentry *dentry)
50{
51 struct sdcardfs_dentry_info *info = SDCARDFS_D(dentry);
52
53 /* use zalloc to init dentry_info.lower_path */
54 info = kmem_cache_zalloc(sdcardfs_dentry_cachep, GFP_ATOMIC);
55 if (!info)
56 return -ENOMEM;
57
58 spin_lock_init(&info->lock);
59 dentry->d_fsdata = info;
60
61 return 0;
62}
63
Daniel Rosenberg5c09ef42016-02-03 21:08:21 -080064struct inode_data {
65 struct inode *lower_inode;
66 userid_t id;
67};
68
69static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/)
Daniel Campello3a703812015-07-20 16:23:50 -070070{
71 struct inode *current_lower_inode = sdcardfs_lower_inode(inode);
Daniel Rosenberged4e2532017-05-15 14:03:15 -070072 userid_t current_userid = SDCARDFS_I(inode)->data->userid;
Daniel Rosenbergbeb00302017-03-16 17:42:58 -070073
Daniel Rosenberg5c09ef42016-02-03 21:08:21 -080074 if (current_lower_inode == ((struct inode_data *)candidate_data)->lower_inode &&
75 current_userid == ((struct inode_data *)candidate_data)->id)
Daniel Campello3a703812015-07-20 16:23:50 -070076 return 1; /* found a match */
77 else
78 return 0; /* no match */
79}
80
81static int sdcardfs_inode_set(struct inode *inode, void *lower_inode)
82{
83 /* we do actual inode initialization in sdcardfs_iget */
84 return 0;
85}
86
Daniel Rosenberg5c09ef42016-02-03 21:08:21 -080087struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, userid_t id)
Daniel Campello3a703812015-07-20 16:23:50 -070088{
89 struct sdcardfs_inode_info *info;
Daniel Rosenberg5c09ef42016-02-03 21:08:21 -080090 struct inode_data data;
Daniel Campello3a703812015-07-20 16:23:50 -070091 struct inode *inode; /* the new inode to return */
Daniel Rosenbergdc4c3fc2017-04-18 12:45:48 -070092
93 if (!igrab(lower_inode))
94 return ERR_PTR(-ESTALE);
Daniel Campello3a703812015-07-20 16:23:50 -070095
Daniel Rosenberg5c09ef42016-02-03 21:08:21 -080096 data.id = id;
97 data.lower_inode = lower_inode;
Daniel Campello3a703812015-07-20 16:23:50 -070098 inode = iget5_locked(sb, /* our superblock */
99 /*
100 * hashval: we use inode number, but we can
101 * also use "(unsigned long)lower_inode"
102 * instead.
103 */
104 lower_inode->i_ino, /* hashval */
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700105 sdcardfs_inode_test, /* inode comparison function */
Daniel Campello3a703812015-07-20 16:23:50 -0700106 sdcardfs_inode_set, /* inode init function */
Daniel Rosenberg5c09ef42016-02-03 21:08:21 -0800107 &data); /* data passed to test+set fxns */
Daniel Campello3a703812015-07-20 16:23:50 -0700108 if (!inode) {
Daniel Campello3a703812015-07-20 16:23:50 -0700109 iput(lower_inode);
Daniel Rosenbergdc4c3fc2017-04-18 12:45:48 -0700110 return ERR_PTR(-ENOMEM);
Daniel Campello3a703812015-07-20 16:23:50 -0700111 }
112 /* if found a cached inode, then just return it */
Daniel Rosenbergdc4c3fc2017-04-18 12:45:48 -0700113 if (!(inode->i_state & I_NEW)) {
114 iput(lower_inode);
Daniel Campello3a703812015-07-20 16:23:50 -0700115 return inode;
Daniel Rosenbergdc4c3fc2017-04-18 12:45:48 -0700116 }
Daniel Campello3a703812015-07-20 16:23:50 -0700117
118 /* initialize new inode */
119 info = SDCARDFS_I(inode);
120
121 inode->i_ino = lower_inode->i_ino;
Daniel Campello3a703812015-07-20 16:23:50 -0700122 sdcardfs_set_lower_inode(inode, lower_inode);
123
124 inode->i_version++;
125
126 /* use different set of inode ops for symlinks & directories */
127 if (S_ISDIR(lower_inode->i_mode))
128 inode->i_op = &sdcardfs_dir_iops;
129 else if (S_ISLNK(lower_inode->i_mode))
130 inode->i_op = &sdcardfs_symlink_iops;
131 else
132 inode->i_op = &sdcardfs_main_iops;
133
134 /* use different set of file ops for directories */
135 if (S_ISDIR(lower_inode->i_mode))
136 inode->i_fop = &sdcardfs_dir_fops;
137 else
138 inode->i_fop = &sdcardfs_main_fops;
139
140 inode->i_mapping->a_ops = &sdcardfs_aops;
141
142 inode->i_atime.tv_sec = 0;
143 inode->i_atime.tv_nsec = 0;
144 inode->i_mtime.tv_sec = 0;
145 inode->i_mtime.tv_nsec = 0;
146 inode->i_ctime.tv_sec = 0;
147 inode->i_ctime.tv_nsec = 0;
148
149 /* properly initialize special inodes */
150 if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
151 S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
152 init_special_inode(inode, lower_inode->i_mode,
153 lower_inode->i_rdev);
154
155 /* all well, copy inode attributes */
Daniel Rosenberg5c09ef42016-02-03 21:08:21 -0800156 sdcardfs_copy_and_fix_attrs(inode, lower_inode);
Daniel Campello3a703812015-07-20 16:23:50 -0700157 fsstack_copy_inode_size(inode, lower_inode);
158
Daniel Campello3a703812015-07-20 16:23:50 -0700159 unlock_new_inode(inode);
160 return inode;
161}
162
163/*
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800164 * Helper interpose routine, called directly by ->lookup to handle
165 * spliced dentries.
Daniel Campello3a703812015-07-20 16:23:50 -0700166 */
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800167static struct dentry *__sdcardfs_interpose(struct dentry *dentry,
168 struct super_block *sb,
169 struct path *lower_path,
170 userid_t id)
Daniel Campello3a703812015-07-20 16:23:50 -0700171{
Daniel Campello3a703812015-07-20 16:23:50 -0700172 struct inode *inode;
173 struct inode *lower_inode;
174 struct super_block *lower_sb;
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800175 struct dentry *ret_dentry;
Daniel Campello3a703812015-07-20 16:23:50 -0700176
177 lower_inode = lower_path->dentry->d_inode;
178 lower_sb = sdcardfs_lower_super(sb);
179
180 /* check that the lower file system didn't cross a mount point */
181 if (lower_inode->i_sb != lower_sb) {
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800182 ret_dentry = ERR_PTR(-EXDEV);
Daniel Campello3a703812015-07-20 16:23:50 -0700183 goto out;
184 }
185
186 /*
187 * We allocate our new inode below by calling sdcardfs_iget,
188 * which will initialize some of the new inode's fields
189 */
190
191 /* inherit lower inode number for sdcardfs's inode */
Daniel Rosenberg5c09ef42016-02-03 21:08:21 -0800192 inode = sdcardfs_iget(sb, lower_inode, id);
Daniel Campello3a703812015-07-20 16:23:50 -0700193 if (IS_ERR(inode)) {
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800194 ret_dentry = ERR_CAST(inode);
Daniel Campello3a703812015-07-20 16:23:50 -0700195 goto out;
196 }
197
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800198 ret_dentry = d_splice_alias(inode, dentry);
199 dentry = ret_dentry ?: dentry;
Daniel Rosenbergd14af5a2017-06-07 12:44:50 -0700200 if (!IS_ERR(dentry))
201 update_derived_permission_lock(dentry);
Daniel Campello3a703812015-07-20 16:23:50 -0700202out:
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800203 return ret_dentry;
204}
205
206/*
207 * Connect an sdcardfs inode dentry/inode with several lower ones. This is
208 * the classic stackable file system "vnode interposition" action.
209 *
210 * @dentry: sdcardfs's dentry which interposes on lower one
211 * @sb: sdcardfs's super_block
212 * @lower_path: the lower path (caller does path_get/put)
213 */
214int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
215 struct path *lower_path, userid_t id)
216{
217 struct dentry *ret_dentry;
218
219 ret_dentry = __sdcardfs_interpose(dentry, sb, lower_path, id);
220 return PTR_ERR(ret_dentry);
Daniel Campello3a703812015-07-20 16:23:50 -0700221}
222
223/*
224 * Main driver function for sdcardfs's lookup.
225 *
226 * Returns: NULL (ok), ERR_PTR if an error occurred.
227 * Fills in lower_parent_path with <dentry,mnt> on success.
228 */
229static struct dentry *__sdcardfs_lookup(struct dentry *dentry,
Al Viro986122f2012-06-10 17:13:09 -0400230 unsigned int flags, struct path *lower_parent_path, userid_t id)
Daniel Campello3a703812015-07-20 16:23:50 -0700231{
232 int err = 0;
233 struct vfsmount *lower_dir_mnt;
234 struct dentry *lower_dir_dentry = NULL;
235 struct dentry *lower_dentry;
Daniel Rosenberg2d336b62017-01-31 20:07:51 -0800236 const struct qstr *name;
Daniel Campello3a703812015-07-20 16:23:50 -0700237 struct nameidata lower_nd;
Daniel Rosenberg053c3472017-02-14 20:47:17 -0800238 struct qstr dname;
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800239 struct dentry *ret_dentry = NULL;
Daniel Campello3a703812015-07-20 16:23:50 -0700240 struct sdcardfs_sb_info *sbi;
241
242 sbi = SDCARDFS_SB(dentry->d_sb);
243 /* must initialize dentry operations */
244 d_set_d_op(dentry, &sdcardfs_ci_dops);
245
246 if (IS_ROOT(dentry))
247 goto out;
248
Daniel Rosenberg2d336b62017-01-31 20:07:51 -0800249 name = &dentry->d_name;
Daniel Campello3a703812015-07-20 16:23:50 -0700250
251 /* now start the actual lookup procedure */
252 lower_dir_dentry = lower_parent_path->dentry;
253 lower_dir_mnt = lower_parent_path->mnt;
254
255 /* Use vfs_path_lookup to check if the dentry exists or not */
Daniel Rosenberg2d336b62017-01-31 20:07:51 -0800256 err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name->name, 0,
fluxidd0f23e2016-07-29 18:52:13 +0200257 &lower_nd.path);
Daniel Rosenberg86120a32016-04-27 15:31:29 -0700258 /* check for other cases */
259 if (err == -ENOENT) {
260 struct dentry *child;
261 struct dentry *match = NULL;
Daniel Rosenberga95870e2016-10-26 20:27:20 -0700262 mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
Daniel Rosenberg86120a32016-04-27 15:31:29 -0700263 spin_lock(&lower_dir_dentry->d_lock);
264 list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_child) {
265 if (child && child->d_inode) {
Daniel Rosenberg2d336b62017-01-31 20:07:51 -0800266 if (qstr_case_eq(&child->d_name, name)) {
Daniel Rosenberg86120a32016-04-27 15:31:29 -0700267 match = dget(child);
268 break;
269 }
270 }
271 }
272 spin_unlock(&lower_dir_dentry->d_lock);
Daniel Rosenberga95870e2016-10-26 20:27:20 -0700273 mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
Daniel Rosenberg86120a32016-04-27 15:31:29 -0700274 if (match) {
275 err = vfs_path_lookup(lower_dir_dentry,
276 lower_dir_mnt,
277 match->d_name.name, 0,
278 &lower_nd.path);
279 dput(match);
280 }
281 }
Daniel Campello3a703812015-07-20 16:23:50 -0700282
283 /* no error: handle positive dentries */
284 if (!err) {
285 /* check if the dentry is an obb dentry
286 * if true, the lower_inode must be replaced with
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700287 * the inode of the graft path
288 */
Daniel Campello3a703812015-07-20 16:23:50 -0700289
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700290 if (need_graft_path(dentry)) {
Daniel Campello3a703812015-07-20 16:23:50 -0700291
292 /* setup_obb_dentry()
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700293 * The lower_path will be stored to the dentry's orig_path
Daniel Campello3a703812015-07-20 16:23:50 -0700294 * and the base obbpath will be copyed to the lower_path variable.
295 * if an error returned, there's no change in the lower_path
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700296 * returns: -ERRNO if error (0: no error)
297 */
Daniel Campello3a703812015-07-20 16:23:50 -0700298 err = setup_obb_dentry(dentry, &lower_nd.path);
299
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700300 if (err) {
Daniel Campello3a703812015-07-20 16:23:50 -0700301 /* if the sbi->obbpath is not available, we can optionally
302 * setup the lower_path with its orig_path.
303 * but, the current implementation just returns an error
304 * because the sdcard daemon also regards this case as
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700305 * a lookup fail.
306 */
Daniel Rosenberg720f8572017-03-16 17:46:13 -0700307 pr_info("sdcardfs: base obbpath is not available\n");
Daniel Campello3a703812015-07-20 16:23:50 -0700308 sdcardfs_put_reset_orig_path(dentry);
309 goto out;
310 }
311 }
312
313 sdcardfs_set_lower_path(dentry, &lower_nd.path);
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800314 ret_dentry =
315 __sdcardfs_interpose(dentry, dentry->d_sb, &lower_nd.path, id);
316 if (IS_ERR(ret_dentry)) {
317 err = PTR_ERR(ret_dentry);
318 /* path_put underlying path on error */
Daniel Campello3a703812015-07-20 16:23:50 -0700319 sdcardfs_put_reset_lower_path(dentry);
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800320 }
Daniel Campello3a703812015-07-20 16:23:50 -0700321 goto out;
322 }
323
324 /*
325 * We don't consider ENOENT an error, and we want to return a
326 * negative dentry.
327 */
328 if (err && err != -ENOENT)
329 goto out;
330
331 /* instatiate a new negative dentry */
Daniel Rosenberg053c3472017-02-14 20:47:17 -0800332 dname.name = name->name;
333 dname.len = name->len;
Daniel Rosenberg6248a702017-04-20 18:05:02 -0700334
335 /* See if the low-level filesystem might want
336 * to use its own hash
337 */
338 lower_dentry = d_hash_and_lookup(lower_dir_dentry, &dname);
339 if (IS_ERR(lower_dentry))
340 return lower_dentry;
Daniel Campello3a703812015-07-20 16:23:50 -0700341 if (!lower_dentry) {
Daniel Rosenberg4a109de2017-04-18 22:25:15 -0700342 /* We called vfs_path_lookup earlier, and did not get a negative
343 * dentry then. Don't confuse the lower filesystem by forcing one
344 * on it now...
345 */
346 err = -ENOENT;
Daniel Campello3a703812015-07-20 16:23:50 -0700347 goto out;
348 }
Daniel Campello3a703812015-07-20 16:23:50 -0700349
fluxidd0f23e2016-07-29 18:52:13 +0200350 lower_nd.path.dentry = lower_dentry;
351 lower_nd.path.mnt = mntget(lower_dir_mnt);
352 sdcardfs_set_lower_path(dentry, &lower_nd.path);
Daniel Campello3a703812015-07-20 16:23:50 -0700353
354 /*
355 * If the intent is to create a file, then don't return an error, so
356 * the VFS will continue the process of making this negative dentry
357 * into a positive one.
358 */
Al Viro986122f2012-06-10 17:13:09 -0400359 if (flags & (LOOKUP_CREATE|LOOKUP_RENAME_TARGET))
Daniel Campello3a703812015-07-20 16:23:50 -0700360 err = 0;
361
362out:
Daniel Rosenbergd96de6672017-03-09 22:11:08 -0800363 if (err)
364 return ERR_PTR(err);
365 return ret_dentry;
Daniel Campello3a703812015-07-20 16:23:50 -0700366}
367
368/*
369 * On success:
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700370 * fills dentry object appropriate values and returns NULL.
Daniel Campello3a703812015-07-20 16:23:50 -0700371 * On fail (== error)
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700372 * returns error ptr
Daniel Campello3a703812015-07-20 16:23:50 -0700373 *
374 * @dir : Parent inode. It is locked (dir->i_mutex)
375 * @dentry : Target dentry to lookup. we should set each of fields.
376 * (dentry->d_name is initialized already)
377 * @nd : nameidata of parent inode
378 */
379struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
Al Viro986122f2012-06-10 17:13:09 -0400380 unsigned int flags)
Daniel Campello3a703812015-07-20 16:23:50 -0700381{
382 struct dentry *ret = NULL, *parent;
383 struct path lower_parent_path;
384 int err = 0;
Daniel Campello3a703812015-07-20 16:23:50 -0700385 const struct cred *saved_cred = NULL;
386
387 parent = dget_parent(dentry);
388
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700389 if (!check_caller_access_to_name(parent->d_inode, &dentry->d_name)) {
Daniel Campello3a703812015-07-20 16:23:50 -0700390 ret = ERR_PTR(-EACCES);
Daniel Campello3a703812015-07-20 16:23:50 -0700391 goto out_err;
Daniel Rosenbergbeb00302017-03-16 17:42:58 -0700392 }
Daniel Campello3a703812015-07-20 16:23:50 -0700393
394 /* save current_cred and override it */
Daniel Rosenberg0b9f6012018-07-19 18:08:35 -0700395 saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb),
396 SDCARDFS_I(dir)->data);
397 if (!saved_cred) {
398 ret = ERR_PTR(-ENOMEM);
399 goto out_err;
400 }
Daniel Campello3a703812015-07-20 16:23:50 -0700401
402 sdcardfs_get_lower_path(parent, &lower_parent_path);
403
404 /* allocate dentry private data. We free it in ->d_release */
405 err = new_dentry_private_data(dentry);
406 if (err) {
407 ret = ERR_PTR(err);
408 goto out;
409 }
410
Al Viro986122f2012-06-10 17:13:09 -0400411 ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path,
Daniel Rosenberged4e2532017-05-15 14:03:15 -0700412 SDCARDFS_I(dir)->data->userid);
Daniel Campello3a703812015-07-20 16:23:50 -0700413 if (IS_ERR(ret))
Daniel Campello3a703812015-07-20 16:23:50 -0700414 goto out;
Daniel Campello3a703812015-07-20 16:23:50 -0700415 if (ret)
416 dentry = ret;
417 if (dentry->d_inode) {
418 fsstack_copy_attr_times(dentry->d_inode,
419 sdcardfs_lower_inode(dentry->d_inode));
Daniel Rosenbergdea78322016-08-16 15:19:26 -0700420 /* get derived permission */
Daniel Campello3a703812015-07-20 16:23:50 -0700421 get_derived_permission(parent, dentry);
Daniel Rosenberga95870e2016-10-26 20:27:20 -0700422 fixup_tmp_permissions(dentry->d_inode);
Daniel Rosenbergb7c13d82017-01-25 13:48:45 -0800423 fixup_lower_ownership(dentry, dentry->d_name.name);
Daniel Campello3a703812015-07-20 16:23:50 -0700424 }
425 /* update parent directory's atime */
426 fsstack_copy_attr_atime(parent->d_inode,
427 sdcardfs_lower_inode(parent->d_inode));
428
429out:
430 sdcardfs_put_lower_path(parent, &lower_parent_path);
Daniel Rosenberg0b9f6012018-07-19 18:08:35 -0700431 revert_fsids(saved_cred);
Daniel Campello3a703812015-07-20 16:23:50 -0700432out_err:
433 dput(parent);
434 return ret;
435}