3c9454e5e1c6e9539393608a9ad0a6aea64a2ecd
[firefly-linux-kernel-4.4.55.git] / fs / sdcardfs / lookup.c
1 /*
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 */
25 static struct kmem_cache *sdcardfs_dentry_cachep;
26
27 int 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
37 void sdcardfs_destroy_dentry_cache(void)
38 {
39         if (sdcardfs_dentry_cachep)
40                 kmem_cache_destroy(sdcardfs_dentry_cachep);
41 }
42
43 void 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 */
52 int 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
67 struct inode_data {
68         struct inode *lower_inode;
69         userid_t id;
70 };
71
72 static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/)
73 {
74         struct inode *current_lower_inode = sdcardfs_lower_inode(inode);
75         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)
78                 return 1; /* found a match */
79         else
80                 return 0; /* no match */
81 }
82
83 static 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
89 struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, userid_t id)
90 {
91         struct sdcardfs_inode_info *info;
92         struct inode_data data;
93         struct inode *inode; /* the new inode to return */
94         int err;
95
96         data.id = id;
97         data.lower_inode = lower_inode;
98         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 */
107                              &data); /* data passed to test+set fxns */
108         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 */
159         sdcardfs_copy_and_fix_attrs(inode, lower_inode);
160         fsstack_copy_inode_size(inode, lower_inode);
161
162         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  */
174 int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
175                      struct path *lower_path, userid_t id)
176 {
177         int err = 0;
178         struct inode *inode;
179         struct inode *lower_inode;
180         struct super_block *lower_sb;
181
182         lower_inode = d_inode(lower_path->dentry);
183         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 */
197         inode = sdcardfs_iget(sb, lower_inode, id);
198         if (IS_ERR(inode)) {
199                 err = PTR_ERR(inode);
200                 goto out;
201         }
202
203         d_add(dentry, inode);
204         update_derived_permission_lock(dentry);
205 out:
206         return err;
207 }
208
209 /*
210  * Main driver function for sdcardfs's lookup.
211  *
212  * Returns: NULL (ok), ERR_PTR if an error occurred.
213  * Fills in lower_parent_path with <dentry,mnt> on success.
214  */
215 static struct dentry *__sdcardfs_lookup(struct dentry *dentry,
216                 unsigned int flags, struct path *lower_parent_path, userid_t id)
217 {
218         int err = 0;
219         struct vfsmount *lower_dir_mnt;
220         struct dentry *lower_dir_dentry = NULL;
221         struct dentry *lower_dentry;
222         const char *name;
223         struct path lower_path;
224         struct qstr this;
225         struct sdcardfs_sb_info *sbi;
226
227         sbi = SDCARDFS_SB(dentry->d_sb);
228         /* must initialize dentry operations */
229         d_set_d_op(dentry, &sdcardfs_ci_dops);
230
231         if (IS_ROOT(dentry))
232                 goto out;
233
234         name = dentry->d_name.name;
235
236         /* now start the actual lookup procedure */
237         lower_dir_dentry = lower_parent_path->dentry;
238         lower_dir_mnt = lower_parent_path->mnt;
239
240         /* Use vfs_path_lookup to check if the dentry exists or not */
241         err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0,
242                                 &lower_path);
243         /* check for other cases */
244         if (err == -ENOENT) {
245                 struct dentry *child;
246                 struct dentry *match = NULL;
247                 mutex_lock(&d_inode(lower_dir_dentry)->i_mutex);
248                 spin_lock(&lower_dir_dentry->d_lock);
249                 list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_child) {
250                         if (child && d_inode(child)) {
251                                 if (strcasecmp(child->d_name.name, name)==0) {
252                                         match = dget(child);
253                                         break;
254                                 }
255                         }
256                 }
257                 spin_unlock(&lower_dir_dentry->d_lock);
258                 mutex_unlock(&d_inode(lower_dir_dentry)->i_mutex);
259                 if (match) {
260                         err = vfs_path_lookup(lower_dir_dentry,
261                                                 lower_dir_mnt,
262                                                 match->d_name.name, 0,
263                                                 &lower_path);
264                         dput(match);
265                 }
266         }
267
268         /* no error: handle positive dentries */
269         if (!err) {
270                 /* check if the dentry is an obb dentry
271                  * if true, the lower_inode must be replaced with
272                  * the inode of the graft path */
273
274                 if(need_graft_path(dentry)) {
275
276                         /* setup_obb_dentry()
277                          * The lower_path will be stored to the dentry's orig_path
278                          * and the base obbpath will be copyed to the lower_path variable.
279                          * if an error returned, there's no change in the lower_path
280                          *              returns: -ERRNO if error (0: no error) */
281                         err = setup_obb_dentry(dentry, &lower_path);
282
283                         if(err) {
284                                 /* if the sbi->obbpath is not available, we can optionally
285                                  * setup the lower_path with its orig_path.
286                                  * but, the current implementation just returns an error
287                                  * because the sdcard daemon also regards this case as
288                                  * a lookup fail. */
289                                 printk(KERN_INFO "sdcardfs: base obbpath is not available\n");
290                                 sdcardfs_put_reset_orig_path(dentry);
291                                 goto out;
292                         }
293                 }
294
295                 sdcardfs_set_lower_path(dentry, &lower_path);
296                 err = sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
297                 if (err) /* path_put underlying path on error */
298                         sdcardfs_put_reset_lower_path(dentry);
299                 goto out;
300         }
301
302         /*
303          * We don't consider ENOENT an error, and we want to return a
304          * negative dentry.
305          */
306         if (err && err != -ENOENT)
307                 goto out;
308
309         /* instatiate a new negative dentry */
310         this.name = name;
311         this.len = strlen(name);
312         this.hash = full_name_hash(this.name, this.len);
313         lower_dentry = d_lookup(lower_dir_dentry, &this);
314         if (lower_dentry)
315                 goto setup_lower;
316
317         lower_dentry = d_alloc(lower_dir_dentry, &this);
318         if (!lower_dentry) {
319                 err = -ENOMEM;
320                 goto out;
321         }
322         d_add(lower_dentry, NULL); /* instantiate and hash */
323
324 setup_lower:
325         lower_path.dentry = lower_dentry;
326         lower_path.mnt = mntget(lower_dir_mnt);
327         sdcardfs_set_lower_path(dentry, &lower_path);
328
329         /*
330          * If the intent is to create a file, then don't return an error, so
331          * the VFS will continue the process of making this negative dentry
332          * into a positive one.
333          */
334         if (flags & (LOOKUP_CREATE|LOOKUP_RENAME_TARGET))
335                 err = 0;
336
337 out:
338         return ERR_PTR(err);
339 }
340
341 /*
342  * On success:
343  *      fills dentry object appropriate values and returns NULL.
344  * On fail (== error)
345  *      returns error ptr
346  *
347  * @dir : Parent inode. It is locked (dir->i_mutex)
348  * @dentry : Target dentry to lookup. we should set each of fields.
349  *           (dentry->d_name is initialized already)
350  * @nd : nameidata of parent inode
351  */
352 struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
353                              unsigned int flags)
354 {
355         struct dentry *ret = NULL, *parent;
356         struct path lower_parent_path;
357         int err = 0;
358         const struct cred *saved_cred = NULL;
359
360         parent = dget_parent(dentry);
361
362         if(!check_caller_access_to_name(d_inode(parent), dentry->d_name.name)) {
363                 ret = ERR_PTR(-EACCES);
364                 printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
365                          "      dentry: %s, task:%s\n",
366                                                  __func__, dentry->d_name.name, current->comm);
367                 goto out_err;
368         }
369
370         /* save current_cred and override it */
371         OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
372
373         sdcardfs_get_lower_path(parent, &lower_parent_path);
374
375         /* allocate dentry private data.  We free it in ->d_release */
376         err = new_dentry_private_data(dentry);
377         if (err) {
378                 ret = ERR_PTR(err);
379                 goto out;
380         }
381
382         ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path, SDCARDFS_I(dir)->userid);
383         if (IS_ERR(ret))
384         {
385                 goto out;
386         }
387         if (ret)
388                 dentry = ret;
389         if (d_inode(dentry)) {
390                 fsstack_copy_attr_times(d_inode(dentry),
391                                         sdcardfs_lower_inode(d_inode(dentry)));
392                 /* get derived permission */
393                 get_derived_permission(parent, dentry);
394                 fixup_tmp_permissions(d_inode(dentry));
395                 fixup_lower_ownership(dentry, dentry->d_name.name);
396         }
397         /* update parent directory's atime */
398         fsstack_copy_attr_atime(d_inode(parent),
399                                 sdcardfs_lower_inode(d_inode(parent)));
400
401 out:
402         sdcardfs_put_lower_path(parent, &lower_parent_path);
403         REVERT_CRED(saved_cred);
404 out_err:
405         dput(parent);
406         return ret;
407 }