4 * Copyright (c) 2013 Samsung Electronics Co. Ltd
5 * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun,
6 * Sunghwan Yun, Sungjong Seo
8 * This program has been developed as a stackable file system based on
9 * the WrapFS which written by
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
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.
22 #include <linux/module.h>
23 #include <linux/types.h>
24 #include <linux/parser.h>
32 Opt_multiuser
, // May need?
38 static const match_table_t sdcardfs_tokens
= {
39 {Opt_fsuid
, "fsuid=%u"},
40 {Opt_fsgid
, "fsgid=%u"},
43 {Opt_mask
, "mask=%u"},
44 {Opt_userid
, "userid=%d"},
45 {Opt_multiuser
, "multiuser"},
46 {Opt_reserved_mb
, "reserved_mb=%u"},
50 static int parse_options(struct super_block
*sb
, char *options
, int silent
,
51 int *debug
, struct sdcardfs_vfsmount_options
*vfsopts
,
52 struct sdcardfs_mount_options
*opts
)
55 substring_t args
[MAX_OPT_ARGS
];
58 /* by default, we use AID_MEDIA_RW as uid, gid */
59 opts
->fs_low_uid
= AID_MEDIA_RW
;
60 opts
->fs_low_gid
= AID_MEDIA_RW
;
62 opts
->multiuser
= false;
65 /* by default, 0MB is reserved */
66 opts
->reserved_mb
= 0;
73 while ((p
= strsep(&options
, ",")) != NULL
) {
78 token
= match_token(p
, sdcardfs_tokens
, args
);
85 if (match_int(&args
[0], &option
))
87 opts
->fs_low_uid
= option
;
90 if (match_int(&args
[0], &option
))
92 opts
->fs_low_gid
= option
;
95 if (match_int(&args
[0], &option
))
97 vfsopts
->gid
= option
;
100 if (match_int(&args
[0], &option
))
102 opts
->fs_user_id
= option
;
105 if (match_int(&args
[0], &option
))
107 vfsopts
->mask
= option
;
110 opts
->multiuser
= true;
112 case Opt_reserved_mb
:
113 if (match_int(&args
[0], &option
))
115 opts
->reserved_mb
= option
;
120 printk( KERN_ERR
"Unrecognized mount option \"%s\" "
121 "or missing value", p
);
128 printk( KERN_INFO
"sdcardfs : options - debug:%d\n", *debug
);
129 printk( KERN_INFO
"sdcardfs : options - uid:%d\n",
131 printk( KERN_INFO
"sdcardfs : options - gid:%d\n",
138 int parse_options_remount(struct super_block
*sb
, char *options
, int silent
,
139 struct sdcardfs_vfsmount_options
*vfsopts
)
142 substring_t args
[MAX_OPT_ARGS
];
149 while ((p
= strsep(&options
, ",")) != NULL
) {
154 token
= match_token(p
, sdcardfs_tokens
, args
);
161 if (match_int(&args
[0], &option
))
163 vfsopts
->gid
= option
;
167 if (match_int(&args
[0], &option
))
169 vfsopts
->mask
= option
;
175 case Opt_reserved_mb
:
176 printk( KERN_WARNING
"Option \"%s\" can't be changed during remount\n", p
);
181 printk( KERN_ERR
"Unrecognized mount option \"%s\" "
182 "or missing value", p
);
189 printk( KERN_INFO
"sdcardfs : options - debug:%d\n", debug
);
190 printk( KERN_INFO
"sdcardfs : options - gid:%d\n", vfsopts
->gid
);
191 printk( KERN_INFO
"sdcardfs : options - mask:%d\n", vfsopts
->mask
);
199 * our custom d_alloc_root work-alike
201 * we can't use d_alloc_root if we want to use our own interpose function
202 * unchanged, so we simply call our own "fake" d_alloc_root
204 static struct dentry
*sdcardfs_d_alloc_root(struct super_block
*sb
)
206 struct dentry
*ret
= NULL
;
209 static const struct qstr name
= {
214 ret
= d_alloc(NULL
, &name
);
216 d_set_d_op(ret
, &sdcardfs_ci_dops
);
225 DEFINE_MUTEX(sdcardfs_super_list_lock
);
226 LIST_HEAD(sdcardfs_super_list
);
227 EXPORT_SYMBOL_GPL(sdcardfs_super_list_lock
);
228 EXPORT_SYMBOL_GPL(sdcardfs_super_list
);
231 * There is no need to lock the sdcardfs_super_info's rwsem as there is no
232 * way anyone can have a reference to the superblock at this point in time.
234 static int sdcardfs_read_super(struct vfsmount
*mnt
, struct super_block
*sb
,
235 const char *dev_name
, void *raw_data
, int silent
)
239 struct super_block
*lower_sb
;
240 struct path lower_path
;
241 struct sdcardfs_sb_info
*sb_info
;
242 struct sdcardfs_vfsmount_options
*mnt_opt
= mnt
->data
;
245 printk(KERN_INFO
"sdcardfs version 2.0\n");
249 "sdcardfs: read_super: missing dev_name argument\n");
254 printk(KERN_INFO
"sdcardfs: dev_name -> %s\n", dev_name
);
255 printk(KERN_INFO
"sdcardfs: options -> %s\n", (char *)raw_data
);
256 printk(KERN_INFO
"sdcardfs: mnt -> %p\n", mnt
);
258 /* parse lower path */
259 err
= kern_path(dev_name
, LOOKUP_FOLLOW
| LOOKUP_DIRECTORY
,
262 printk(KERN_ERR
"sdcardfs: error accessing lower directory '%s'\n", dev_name
);
266 /* allocate superblock private data */
267 sb
->s_fs_info
= kzalloc(sizeof(struct sdcardfs_sb_info
), GFP_KERNEL
);
268 if (!SDCARDFS_SB(sb
)) {
269 printk(KERN_CRIT
"sdcardfs: read_super: out of memory\n");
274 sb_info
= sb
->s_fs_info
;
276 err
= parse_options(sb
, raw_data
, silent
, &debug
, mnt_opt
, &sb_info
->options
);
278 printk(KERN_ERR
"sdcardfs: invalid options\n");
282 /* set the lower superblock field of upper superblock */
283 lower_sb
= lower_path
.dentry
->d_sb
;
284 atomic_inc(&lower_sb
->s_active
);
285 sdcardfs_set_lower_super(sb
, lower_sb
);
287 sb
->s_stack_depth
= lower_sb
->s_stack_depth
+ 1;
288 if (sb
->s_stack_depth
> FILESYSTEM_MAX_STACK_DEPTH
) {
289 pr_err("sdcardfs: maximum fs stacking depth exceeded\n");
294 /* inherit maxbytes from lower file system */
295 sb
->s_maxbytes
= lower_sb
->s_maxbytes
;
298 * Our c/m/atime granularity is 1 ns because we may stack on file
299 * systems whose granularity is as good.
303 sb
->s_magic
= SDCARDFS_SUPER_MAGIC
;
304 sb
->s_op
= &sdcardfs_sops
;
306 /* get a new inode and allocate our root dentry */
307 inode
= sdcardfs_iget(sb
, lower_path
.dentry
->d_inode
, 0);
309 err
= PTR_ERR(inode
);
312 sb
->s_root
= d_make_root(inode
);
317 d_set_d_op(sb
->s_root
, &sdcardfs_ci_dops
);
319 /* link the upper and lower dentries */
320 sb
->s_root
->d_fsdata
= NULL
;
321 err
= new_dentry_private_data(sb
->s_root
);
325 /* set the lower dentries for s_root */
326 sdcardfs_set_lower_path(sb
->s_root
, &lower_path
);
329 * No need to call interpose because we already have a positive
330 * dentry, which was instantiated by d_make_root. Just need to
333 d_rehash(sb
->s_root
);
335 /* setup permission policy */
336 sb_info
->obbpath_s
= kzalloc(PATH_MAX
, GFP_KERNEL
);
337 mutex_lock(&sdcardfs_super_list_lock
);
338 if(sb_info
->options
.multiuser
) {
339 setup_derived_state(sb
->s_root
->d_inode
, PERM_PRE_ROOT
, sb_info
->options
.fs_user_id
, AID_ROOT
, false, sb
->s_root
->d_inode
);
340 snprintf(sb_info
->obbpath_s
, PATH_MAX
, "%s/obb", dev_name
);
341 /*err = prepare_dir(sb_info->obbpath_s,
342 sb_info->options.fs_low_uid,
343 sb_info->options.fs_low_gid, 00755);*/
345 setup_derived_state(sb
->s_root
->d_inode
, PERM_ROOT
, sb_info
->options
.fs_user_id
, AID_ROOT
, false, sb
->s_root
->d_inode
);
346 snprintf(sb_info
->obbpath_s
, PATH_MAX
, "%s/Android/obb", dev_name
);
348 fixup_tmp_permissions(sb
->s_root
->d_inode
);
350 list_add(&sb_info
->list
, &sdcardfs_super_list
);
351 mutex_unlock(&sdcardfs_super_list_lock
);
354 printk(KERN_INFO
"sdcardfs: mounted on top of %s type %s\n",
355 dev_name
, lower_sb
->s_type
->name
);
356 goto out
; /* all is well */
358 /* no longer needed: free_dentry_private_data(sb->s_root); */
364 /* drop refs we took earlier */
365 atomic_dec(&lower_sb
->s_active
);
367 kfree(SDCARDFS_SB(sb
));
368 sb
->s_fs_info
= NULL
;
370 path_put(&lower_path
);
376 /* A feature which supports mount_nodev() with options */
377 static struct dentry
*mount_nodev_with_options(struct vfsmount
*mnt
,
378 struct file_system_type
*fs_type
, int flags
, const char *dev_name
, void *data
,
379 int (*fill_super
)(struct vfsmount
*, struct super_block
*, const char *, void *, int))
383 struct super_block
*s
= sget(fs_type
, NULL
, set_anon_super
, flags
, NULL
);
390 error
= fill_super(mnt
, s
, dev_name
, data
, flags
& MS_SILENT
? 1 : 0);
392 deactivate_locked_super(s
);
393 return ERR_PTR(error
);
395 s
->s_flags
|= MS_ACTIVE
;
396 return dget(s
->s_root
);
399 static struct dentry
*sdcardfs_mount(struct vfsmount
*mnt
,
400 struct file_system_type
*fs_type
, int flags
,
401 const char *dev_name
, void *raw_data
)
404 * dev_name is a lower_path_name,
405 * raw_data is a option string.
407 return mount_nodev_with_options(mnt
, fs_type
, flags
, dev_name
,
408 raw_data
, sdcardfs_read_super
);
411 static struct dentry
*sdcardfs_mount_wrn(struct file_system_type
*fs_type
, int flags
,
412 const char *dev_name
, void *raw_data
)
414 WARN(1, "sdcardfs does not support mount. Use mount2.\n");
415 return ERR_PTR(-EINVAL
);
418 void *sdcardfs_alloc_mnt_data(void) {
419 return kmalloc(sizeof(struct sdcardfs_vfsmount_options
), GFP_KERNEL
);
422 void sdcardfs_kill_sb(struct super_block
*sb
) {
423 struct sdcardfs_sb_info
*sbi
;
424 if (sb
->s_magic
== SDCARDFS_SUPER_MAGIC
) {
425 sbi
= SDCARDFS_SB(sb
);
426 mutex_lock(&sdcardfs_super_list_lock
);
427 list_del(&sbi
->list
);
428 mutex_unlock(&sdcardfs_super_list_lock
);
430 generic_shutdown_super(sb
);
433 static struct file_system_type sdcardfs_fs_type
= {
434 .owner
= THIS_MODULE
,
435 .name
= SDCARDFS_NAME
,
436 .mount
= sdcardfs_mount_wrn
,
437 .mount2
= sdcardfs_mount
,
438 .alloc_mnt_data
= sdcardfs_alloc_mnt_data
,
439 .kill_sb
= sdcardfs_kill_sb
,
443 static int __init
init_sdcardfs_fs(void)
447 pr_info("Registering sdcardfs " SDCARDFS_VERSION
"\n");
449 err
= sdcardfs_init_inode_cache();
452 err
= sdcardfs_init_dentry_cache();
455 err
= packagelist_init();
458 err
= register_filesystem(&sdcardfs_fs_type
);
461 sdcardfs_destroy_inode_cache();
462 sdcardfs_destroy_dentry_cache();
468 static void __exit
exit_sdcardfs_fs(void)
470 sdcardfs_destroy_inode_cache();
471 sdcardfs_destroy_dentry_cache();
473 unregister_filesystem(&sdcardfs_fs_type
);
474 pr_info("Completed sdcardfs module unload\n");
477 MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
478 " (http://www.fsl.cs.sunysb.edu/)");
479 MODULE_DESCRIPTION("Wrapfs " SDCARDFS_VERSION
480 " (http://wrapfs.filesystems.org/)");
481 MODULE_LICENSE("GPL");
483 module_init(init_sdcardfs_fs
);
484 module_exit(exit_sdcardfs_fs
);