blob: 7d26c269da355fef73d85460f5f26dbffa4c84f2 [file] [log] [blame]
Daniel Campello35c9e242015-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{
39 if (sdcardfs_dentry_cachep)
40 kmem_cache_destroy(sdcardfs_dentry_cachep);
41}
42
43void free_dentry_private_data(struct dentry *dentry)
44{
45 if (!dentry || !dentry->d_fsdata)
46 return;
47 kmem_cache_free(sdcardfs_dentry_cachep, dentry->d_fsdata);
48 dentry->d_fsdata = NULL;
49}
50
51/* allocate new dentry private data */
52int new_dentry_private_data(struct dentry *dentry)
53{
54 struct sdcardfs_dentry_info *info = SDCARDFS_D(dentry);
55
56 /* use zalloc to init dentry_info.lower_path */
57 info = kmem_cache_zalloc(sdcardfs_dentry_cachep, GFP_ATOMIC);
58 if (!info)
59 return -ENOMEM;
60
61 spin_lock_init(&info->lock);
62 dentry->d_fsdata = info;
63
64 return 0;
65}
66
Daniel Rosenberg497ac902016-02-03 21:08:21 -080067struct inode_data {
68 struct inode *lower_inode;
69 userid_t id;
70};
71
72static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/)
Daniel Campello35c9e242015-07-20 16:23:50 -070073{
74 struct inode *current_lower_inode = sdcardfs_lower_inode(inode);
Daniel Rosenberg497ac902016-02-03 21:08:21 -080075 userid_t current_userid = SDCARDFS_I(inode)->userid;
76 if (current_lower_inode == ((struct inode_data *)candidate_data)->lower_inode &&
77 current_userid == ((struct inode_data *)candidate_data)->id)
Daniel Campello35c9e242015-07-20 16:23:50 -070078 return 1; /* found a match */
79 else
80 return 0; /* no match */
81}
82
83static int sdcardfs_inode_set(struct inode *inode, void *lower_inode)
84{
85 /* we do actual inode initialization in sdcardfs_iget */
86 return 0;
87}
88
Daniel Rosenberg497ac902016-02-03 21:08:21 -080089struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, userid_t id)
Daniel Campello35c9e242015-07-20 16:23:50 -070090{
91 struct sdcardfs_inode_info *info;
Daniel Rosenberg497ac902016-02-03 21:08:21 -080092 struct inode_data data;
Daniel Campello35c9e242015-07-20 16:23:50 -070093 struct inode *inode; /* the new inode to return */
94 int err;
95
Daniel Rosenberg497ac902016-02-03 21:08:21 -080096 data.id = id;
97 data.lower_inode = lower_inode;
Daniel Campello35c9e242015-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 */
105 sdcardfs_inode_test, /* inode comparison function */
106 sdcardfs_inode_set, /* inode init function */
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800107 &data); /* data passed to test+set fxns */
Daniel Campello35c9e242015-07-20 16:23:50 -0700108 if (!inode) {
109 err = -EACCES;
110 iput(lower_inode);
111 return ERR_PTR(err);
112 }
113 /* if found a cached inode, then just return it */
114 if (!(inode->i_state & I_NEW))
115 return inode;
116
117 /* initialize new inode */
118 info = SDCARDFS_I(inode);
119
120 inode->i_ino = lower_inode->i_ino;
121 if (!igrab(lower_inode)) {
122 err = -ESTALE;
123 return ERR_PTR(err);
124 }
125 sdcardfs_set_lower_inode(inode, lower_inode);
126
127 inode->i_version++;
128
129 /* use different set of inode ops for symlinks & directories */
130 if (S_ISDIR(lower_inode->i_mode))
131 inode->i_op = &sdcardfs_dir_iops;
132 else if (S_ISLNK(lower_inode->i_mode))
133 inode->i_op = &sdcardfs_symlink_iops;
134 else
135 inode->i_op = &sdcardfs_main_iops;
136
137 /* use different set of file ops for directories */
138 if (S_ISDIR(lower_inode->i_mode))
139 inode->i_fop = &sdcardfs_dir_fops;
140 else
141 inode->i_fop = &sdcardfs_main_fops;
142
143 inode->i_mapping->a_ops = &sdcardfs_aops;
144
145 inode->i_atime.tv_sec = 0;
146 inode->i_atime.tv_nsec = 0;
147 inode->i_mtime.tv_sec = 0;
148 inode->i_mtime.tv_nsec = 0;
149 inode->i_ctime.tv_sec = 0;
150 inode->i_ctime.tv_nsec = 0;
151
152 /* properly initialize special inodes */
153 if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
154 S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
155 init_special_inode(inode, lower_inode->i_mode,
156 lower_inode->i_rdev);
157
158 /* all well, copy inode attributes */
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800159 sdcardfs_copy_and_fix_attrs(inode, lower_inode);
Daniel Campello35c9e242015-07-20 16:23:50 -0700160 fsstack_copy_inode_size(inode, lower_inode);
161
Daniel Campello35c9e242015-07-20 16:23:50 -0700162 unlock_new_inode(inode);
163 return inode;
164}
165
166/*
167 * Connect a sdcardfs inode dentry/inode with several lower ones. This is
168 * the classic stackable file system "vnode interposition" action.
169 *
170 * @dentry: sdcardfs's dentry which interposes on lower one
171 * @sb: sdcardfs's super_block
172 * @lower_path: the lower path (caller does path_get/put)
173 */
174int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800175 struct path *lower_path, userid_t id)
Daniel Campello35c9e242015-07-20 16:23:50 -0700176{
177 int err = 0;
178 struct inode *inode;
179 struct inode *lower_inode;
180 struct super_block *lower_sb;
181
Daniel Rosenberg63d20762016-12-01 14:36:29 -0800182 lower_inode = d_inode(lower_path->dentry);
Daniel Campello35c9e242015-07-20 16:23:50 -0700183 lower_sb = sdcardfs_lower_super(sb);
184
185 /* check that the lower file system didn't cross a mount point */
186 if (lower_inode->i_sb != lower_sb) {
187 err = -EXDEV;
188 goto out;
189 }
190
191 /*
192 * We allocate our new inode below by calling sdcardfs_iget,
193 * which will initialize some of the new inode's fields
194 */
195
196 /* inherit lower inode number for sdcardfs's inode */
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800197 inode = sdcardfs_iget(sb, lower_inode, id);
Daniel Campello35c9e242015-07-20 16:23:50 -0700198 if (IS_ERR(inode)) {
199 err = PTR_ERR(inode);
200 goto out;
201 }
202
203 d_add(dentry, inode);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800204 update_derived_permission_lock(dentry);
Daniel Campello35c9e242015-07-20 16:23:50 -0700205out:
206 return err;
207}
208
Daniel Rosenbergfe0756d2017-03-01 17:04:41 -0800209struct sdcardfs_name_data {
210 struct dir_context ctx;
211 const struct qstr *to_find;
212 char *name;
213 bool found;
214};
215
216static int sdcardfs_name_match(struct dir_context *ctx, const char *name, int namelen,
217 loff_t offset, u64 ino, unsigned int d_type)
218{
219 struct sdcardfs_name_data *buf = container_of(ctx, struct sdcardfs_name_data, ctx);
220 struct qstr candidate = QSTR_INIT(name, namelen);
221
222 if (qstr_case_eq(buf->to_find, &candidate)) {
223 memcpy(buf->name, name, namelen);
224 buf->name[namelen] = 0;
225 buf->found = true;
226 return 1;
227 }
228 return 0;
229}
230
Daniel Campello35c9e242015-07-20 16:23:50 -0700231/*
232 * Main driver function for sdcardfs's lookup.
233 *
234 * Returns: NULL (ok), ERR_PTR if an error occurred.
235 * Fills in lower_parent_path with <dentry,mnt> on success.
236 */
237static struct dentry *__sdcardfs_lookup(struct dentry *dentry,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800238 unsigned int flags, struct path *lower_parent_path, userid_t id)
Daniel Campello35c9e242015-07-20 16:23:50 -0700239{
240 int err = 0;
241 struct vfsmount *lower_dir_mnt;
242 struct dentry *lower_dir_dentry = NULL;
243 struct dentry *lower_dentry;
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800244 const struct qstr *name;
Daniel Campello35c9e242015-07-20 16:23:50 -0700245 struct path lower_path;
Daniel Rosenberg8e818ff2017-02-14 20:47:17 -0800246 struct qstr dname;
Daniel Campello35c9e242015-07-20 16:23:50 -0700247 struct sdcardfs_sb_info *sbi;
248
249 sbi = SDCARDFS_SB(dentry->d_sb);
250 /* must initialize dentry operations */
251 d_set_d_op(dentry, &sdcardfs_ci_dops);
252
253 if (IS_ROOT(dentry))
254 goto out;
255
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800256 name = &dentry->d_name;
Daniel Campello35c9e242015-07-20 16:23:50 -0700257
258 /* now start the actual lookup procedure */
259 lower_dir_dentry = lower_parent_path->dentry;
260 lower_dir_mnt = lower_parent_path->mnt;
261
262 /* Use vfs_path_lookup to check if the dentry exists or not */
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800263 err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name->name, 0,
Daniel Campellod1d080c2015-07-20 16:27:37 -0700264 &lower_path);
Daniel Rosenberg7c4dcd22016-04-27 15:31:29 -0700265 /* check for other cases */
266 if (err == -ENOENT) {
Daniel Rosenbergfe0756d2017-03-01 17:04:41 -0800267 struct file *file;
268 const struct cred *cred = current_cred();
269
270 struct sdcardfs_name_data buffer = {
271 .ctx.actor = sdcardfs_name_match,
272 .to_find = name,
273 .name = __getname(),
274 .found = false,
275 };
276
277 if (!buffer.name) {
278 err = -ENOMEM;
279 goto out;
Daniel Rosenberg7c4dcd22016-04-27 15:31:29 -0700280 }
Daniel Rosenbergfe0756d2017-03-01 17:04:41 -0800281 file = dentry_open(lower_parent_path, O_RDONLY, cred);
282 if (IS_ERR(file)) {
283 err = PTR_ERR(file);
284 goto put_name;
285 }
286 err = iterate_dir(file, &buffer.ctx);
287 fput(file);
288 if (err)
289 goto put_name;
290
291 if (buffer.found)
Daniel Rosenberg7c4dcd22016-04-27 15:31:29 -0700292 err = vfs_path_lookup(lower_dir_dentry,
293 lower_dir_mnt,
Daniel Rosenbergfe0756d2017-03-01 17:04:41 -0800294 buffer.name, 0,
Daniel Rosenberg7c4dcd22016-04-27 15:31:29 -0700295 &lower_path);
Daniel Rosenbergfe0756d2017-03-01 17:04:41 -0800296 else
297 err = -ENOENT;
298put_name:
299 __putname(buffer.name);
Daniel Rosenberg7c4dcd22016-04-27 15:31:29 -0700300 }
Daniel Campello35c9e242015-07-20 16:23:50 -0700301
302 /* no error: handle positive dentries */
303 if (!err) {
304 /* check if the dentry is an obb dentry
305 * if true, the lower_inode must be replaced with
306 * the inode of the graft path */
307
308 if(need_graft_path(dentry)) {
309
310 /* setup_obb_dentry()
311 * The lower_path will be stored to the dentry's orig_path
312 * and the base obbpath will be copyed to the lower_path variable.
313 * if an error returned, there's no change in the lower_path
314 * returns: -ERRNO if error (0: no error) */
Daniel Campellod1d080c2015-07-20 16:27:37 -0700315 err = setup_obb_dentry(dentry, &lower_path);
Daniel Campello35c9e242015-07-20 16:23:50 -0700316
317 if(err) {
318 /* if the sbi->obbpath is not available, we can optionally
319 * setup the lower_path with its orig_path.
320 * but, the current implementation just returns an error
321 * because the sdcard daemon also regards this case as
322 * a lookup fail. */
323 printk(KERN_INFO "sdcardfs: base obbpath is not available\n");
324 sdcardfs_put_reset_orig_path(dentry);
325 goto out;
326 }
327 }
328
Daniel Campellod1d080c2015-07-20 16:27:37 -0700329 sdcardfs_set_lower_path(dentry, &lower_path);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800330 err = sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
Daniel Campello35c9e242015-07-20 16:23:50 -0700331 if (err) /* path_put underlying path on error */
332 sdcardfs_put_reset_lower_path(dentry);
333 goto out;
334 }
335
336 /*
337 * We don't consider ENOENT an error, and we want to return a
338 * negative dentry.
339 */
340 if (err && err != -ENOENT)
341 goto out;
342
343 /* instatiate a new negative dentry */
Daniel Rosenberg8e818ff2017-02-14 20:47:17 -0800344 dname.name = name->name;
345 dname.len = name->len;
346 dname.hash = full_name_hash(lower_dir_dentry, dname.name, dname.len);
347 lower_dentry = d_lookup(lower_dir_dentry, &dname);
Daniel Campello35c9e242015-07-20 16:23:50 -0700348 if (lower_dentry)
349 goto setup_lower;
350
Daniel Rosenberg8e818ff2017-02-14 20:47:17 -0800351 lower_dentry = d_alloc(lower_dir_dentry, &dname);
Daniel Campello35c9e242015-07-20 16:23:50 -0700352 if (!lower_dentry) {
353 err = -ENOMEM;
354 goto out;
355 }
356 d_add(lower_dentry, NULL); /* instantiate and hash */
357
358setup_lower:
359 lower_path.dentry = lower_dentry;
360 lower_path.mnt = mntget(lower_dir_mnt);
361 sdcardfs_set_lower_path(dentry, &lower_path);
362
363 /*
364 * If the intent is to create a file, then don't return an error, so
365 * the VFS will continue the process of making this negative dentry
366 * into a positive one.
367 */
Daniel Campellod1d080c2015-07-20 16:27:37 -0700368 if (flags & (LOOKUP_CREATE|LOOKUP_RENAME_TARGET))
Daniel Campello35c9e242015-07-20 16:23:50 -0700369 err = 0;
370
371out:
372 return ERR_PTR(err);
373}
374
375/*
376 * On success:
377 * fills dentry object appropriate values and returns NULL.
378 * On fail (== error)
379 * returns error ptr
380 *
Amit Pundirb47e1102016-06-01 21:53:20 +0530381 * @dir : Parent inode.
Daniel Campello35c9e242015-07-20 16:23:50 -0700382 * @dentry : Target dentry to lookup. we should set each of fields.
383 * (dentry->d_name is initialized already)
384 * @nd : nameidata of parent inode
385 */
386struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
Daniel Campellod1d080c2015-07-20 16:27:37 -0700387 unsigned int flags)
Daniel Campello35c9e242015-07-20 16:23:50 -0700388{
389 struct dentry *ret = NULL, *parent;
390 struct path lower_parent_path;
391 int err = 0;
Daniel Campello35c9e242015-07-20 16:23:50 -0700392 const struct cred *saved_cred = NULL;
393
394 parent = dget_parent(dentry);
395
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800396 if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) {
Daniel Campello35c9e242015-07-20 16:23:50 -0700397 ret = ERR_PTR(-EACCES);
Daniel Campello35c9e242015-07-20 16:23:50 -0700398 goto out_err;
399 }
400
401 /* save current_cred and override it */
Daniel Rosenbergad905252017-01-25 13:48:45 -0800402 OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
Daniel Campello35c9e242015-07-20 16:23:50 -0700403
404 sdcardfs_get_lower_path(parent, &lower_parent_path);
405
406 /* allocate dentry private data. We free it in ->d_release */
407 err = new_dentry_private_data(dentry);
408 if (err) {
409 ret = ERR_PTR(err);
410 goto out;
411 }
412
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800413 ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path, SDCARDFS_I(dir)->userid);
Daniel Campello35c9e242015-07-20 16:23:50 -0700414 if (IS_ERR(ret))
415 {
416 goto out;
417 }
418 if (ret)
419 dentry = ret;
Daniel Rosenberg63d20762016-12-01 14:36:29 -0800420 if (d_inode(dentry)) {
421 fsstack_copy_attr_times(d_inode(dentry),
422 sdcardfs_lower_inode(d_inode(dentry)));
Daniel Rosenbergcb1b9452016-08-16 15:19:26 -0700423 /* get derived permission */
Daniel Campello35c9e242015-07-20 16:23:50 -0700424 get_derived_permission(parent, dentry);
Daniel Rosenberg90219272016-10-26 20:27:20 -0700425 fixup_tmp_permissions(d_inode(dentry));
Daniel Rosenbergad905252017-01-25 13:48:45 -0800426 fixup_lower_ownership(dentry, dentry->d_name.name);
Daniel Campello35c9e242015-07-20 16:23:50 -0700427 }
428 /* update parent directory's atime */
Daniel Rosenberg63d20762016-12-01 14:36:29 -0800429 fsstack_copy_attr_atime(d_inode(parent),
430 sdcardfs_lower_inode(d_inode(parent)));
Daniel Campello35c9e242015-07-20 16:23:50 -0700431
432out:
433 sdcardfs_put_lower_path(parent, &lower_parent_path);
434 REVERT_CRED(saved_cred);
435out_err:
436 dput(parent);
437 return ret;
438}