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>
41 static const match_table_t sdcardfs_tokens
= {
42 {Opt_fsuid
, "fsuid=%u"},
43 {Opt_fsgid
, "fsgid=%u"},
46 {Opt_mask
, "mask=%u"},
47 {Opt_userid
, "userid=%d"},
48 {Opt_multiuser
, "multiuser"},
49 {Opt_gid_derivation
, "derive_gid"},
50 {Opt_default_normal
, "default_normal"},
51 {Opt_reserved_mb
, "reserved_mb=%u"},
52 {Opt_nocache
, "nocache"},
56 static int parse_options(struct super_block
*sb
, char *options
, int silent
,
57 int *debug
, struct sdcardfs_vfsmount_options
*vfsopts
,
58 struct sdcardfs_mount_options
*opts
)
61 substring_t args
[MAX_OPT_ARGS
];
64 /* by default, we use AID_MEDIA_RW as uid, gid */
65 opts
->fs_low_uid
= AID_MEDIA_RW
;
66 opts
->fs_low_gid
= AID_MEDIA_RW
;
68 opts
->multiuser
= false;
71 /* by default, 0MB is reserved */
72 opts
->reserved_mb
= 0;
73 /* by default, gid derivation is off */
74 opts
->gid_derivation
= false;
75 opts
->default_normal
= false;
76 opts
->nocache
= false;
83 while ((p
= strsep(&options
, ",")) != NULL
) {
89 token
= match_token(p
, sdcardfs_tokens
, args
);
96 if (match_int(&args
[0], &option
))
98 opts
->fs_low_uid
= option
;
101 if (match_int(&args
[0], &option
))
103 opts
->fs_low_gid
= option
;
106 if (match_int(&args
[0], &option
))
108 vfsopts
->gid
= option
;
111 if (match_int(&args
[0], &option
))
113 opts
->fs_user_id
= option
;
116 if (match_int(&args
[0], &option
))
118 vfsopts
->mask
= option
;
121 opts
->multiuser
= true;
123 case Opt_reserved_mb
:
124 if (match_int(&args
[0], &option
))
126 opts
->reserved_mb
= option
;
128 case Opt_gid_derivation
:
129 opts
->gid_derivation
= true;
131 case Opt_default_normal
:
132 opts
->default_normal
= true;
135 opts
->nocache
= true;
140 pr_err("Unrecognized mount option \"%s\" or missing value", p
);
146 pr_info("sdcardfs : options - debug:%d\n", *debug
);
147 pr_info("sdcardfs : options - uid:%d\n",
149 pr_info("sdcardfs : options - gid:%d\n",
156 int parse_options_remount(struct super_block
*sb
, char *options
, int silent
,
157 struct sdcardfs_vfsmount_options
*vfsopts
)
160 substring_t args
[MAX_OPT_ARGS
];
167 while ((p
= strsep(&options
, ",")) != NULL
) {
173 token
= match_token(p
, sdcardfs_tokens
, args
);
180 if (match_int(&args
[0], &option
))
182 vfsopts
->gid
= option
;
186 if (match_int(&args
[0], &option
))
188 vfsopts
->mask
= option
;
190 case Opt_default_normal
:
195 case Opt_reserved_mb
:
196 pr_warn("Option \"%s\" can't be changed during remount\n", p
);
201 pr_err("Unrecognized mount option \"%s\" or missing value", p
);
207 pr_info("sdcardfs : options - debug:%d\n", debug
);
208 pr_info("sdcardfs : options - gid:%d\n", vfsopts
->gid
);
209 pr_info("sdcardfs : options - mask:%d\n", vfsopts
->mask
);
217 * our custom d_alloc_root work-alike
219 * we can't use d_alloc_root if we want to use our own interpose function
220 * unchanged, so we simply call our own "fake" d_alloc_root
222 static struct dentry
*sdcardfs_d_alloc_root(struct super_block
*sb
)
224 struct dentry
*ret
= NULL
;
227 static const struct qstr name
= {
232 ret
= d_alloc(NULL
, &name
);
234 d_set_d_op(ret
, &sdcardfs_ci_dops
);
243 DEFINE_MUTEX(sdcardfs_super_list_lock
);
244 EXPORT_SYMBOL_GPL(sdcardfs_super_list_lock
);
245 LIST_HEAD(sdcardfs_super_list
);
246 EXPORT_SYMBOL_GPL(sdcardfs_super_list
);
249 * There is no need to lock the sdcardfs_super_info's rwsem as there is no
250 * way anyone can have a reference to the superblock at this point in time.
252 static int sdcardfs_read_super(struct vfsmount
*mnt
, struct super_block
*sb
,
253 const char *dev_name
, void *raw_data
, int silent
)
257 struct super_block
*lower_sb
;
258 struct path lower_path
;
259 struct sdcardfs_sb_info
*sb_info
;
260 struct sdcardfs_vfsmount_options
*mnt_opt
= mnt
->data
;
263 pr_info("sdcardfs version 2.0\n");
266 pr_err("sdcardfs: read_super: missing dev_name argument\n");
271 pr_info("sdcardfs: dev_name -> %s\n", dev_name
);
272 pr_info("sdcardfs: options -> %s\n", (char *)raw_data
);
273 pr_info("sdcardfs: mnt -> %p\n", mnt
);
275 /* parse lower path */
276 err
= kern_path(dev_name
, LOOKUP_FOLLOW
| LOOKUP_DIRECTORY
,
279 pr_err("sdcardfs: error accessing lower directory '%s'\n", dev_name
);
283 /* allocate superblock private data */
284 sb
->s_fs_info
= kzalloc(sizeof(struct sdcardfs_sb_info
), GFP_KERNEL
);
285 if (!SDCARDFS_SB(sb
)) {
286 pr_crit("sdcardfs: read_super: out of memory\n");
291 sb_info
= sb
->s_fs_info
;
293 err
= parse_options(sb
, raw_data
, silent
, &debug
, mnt_opt
, &sb_info
->options
);
295 pr_err("sdcardfs: invalid options\n");
299 /* set the lower superblock field of upper superblock */
300 lower_sb
= lower_path
.dentry
->d_sb
;
301 atomic_inc(&lower_sb
->s_active
);
302 sdcardfs_set_lower_super(sb
, lower_sb
);
304 sb
->s_stack_depth
= lower_sb
->s_stack_depth
+ 1;
305 if (sb
->s_stack_depth
> FILESYSTEM_MAX_STACK_DEPTH
) {
306 pr_err("sdcardfs: maximum fs stacking depth exceeded\n");
311 /* inherit maxbytes from lower file system */
312 sb
->s_maxbytes
= lower_sb
->s_maxbytes
;
315 * Our c/m/atime granularity is 1 ns because we may stack on file
316 * systems whose granularity is as good.
320 sb
->s_magic
= SDCARDFS_SUPER_MAGIC
;
321 sb
->s_op
= &sdcardfs_sops
;
323 /* get a new inode and allocate our root dentry */
324 inode
= sdcardfs_iget(sb
, d_inode(lower_path
.dentry
), 0);
326 err
= PTR_ERR(inode
);
329 sb
->s_root
= d_make_root(inode
);
334 d_set_d_op(sb
->s_root
, &sdcardfs_ci_dops
);
336 /* link the upper and lower dentries */
337 sb
->s_root
->d_fsdata
= NULL
;
338 err
= new_dentry_private_data(sb
->s_root
);
342 /* set the lower dentries for s_root */
343 sdcardfs_set_lower_path(sb
->s_root
, &lower_path
);
346 * No need to call interpose because we already have a positive
347 * dentry, which was instantiated by d_make_root. Just need to
350 d_rehash(sb
->s_root
);
352 /* setup permission policy */
353 sb_info
->obbpath_s
= kzalloc(PATH_MAX
, GFP_KERNEL
);
354 mutex_lock(&sdcardfs_super_list_lock
);
355 if (sb_info
->options
.multiuser
) {
356 setup_derived_state(d_inode(sb
->s_root
), PERM_PRE_ROOT
,
357 sb_info
->options
.fs_user_id
, AID_ROOT
);
358 snprintf(sb_info
->obbpath_s
, PATH_MAX
, "%s/obb", dev_name
);
360 setup_derived_state(d_inode(sb
->s_root
), PERM_ROOT
,
361 sb_info
->options
.fs_user_id
, AID_ROOT
);
362 snprintf(sb_info
->obbpath_s
, PATH_MAX
, "%s/Android/obb", dev_name
);
364 fixup_tmp_permissions(d_inode(sb
->s_root
));
366 list_add(&sb_info
->list
, &sdcardfs_super_list
);
367 mutex_unlock(&sdcardfs_super_list_lock
);
370 pr_info("sdcardfs: mounted on top of %s type %s\n",
371 dev_name
, lower_sb
->s_type
->name
);
372 goto out
; /* all is well */
374 /* no longer needed: free_dentry_private_data(sb->s_root); */
379 /* drop refs we took earlier */
380 atomic_dec(&lower_sb
->s_active
);
382 kfree(SDCARDFS_SB(sb
));
383 sb
->s_fs_info
= NULL
;
385 path_put(&lower_path
);
391 struct sdcardfs_mount_private
{
392 struct vfsmount
*mnt
;
393 const char *dev_name
;
397 static int __sdcardfs_fill_super(
398 struct super_block
*sb
,
399 void *_priv
, int silent
)
401 struct sdcardfs_mount_private
*priv
= _priv
;
403 return sdcardfs_read_super(priv
->mnt
,
404 sb
, priv
->dev_name
, priv
->raw_data
, silent
);
407 static struct dentry
*sdcardfs_mount(struct vfsmount
*mnt
,
408 struct file_system_type
*fs_type
, int flags
,
409 const char *dev_name
, void *raw_data
)
411 struct sdcardfs_mount_private priv
= {
413 .dev_name
= dev_name
,
417 return mount_nodev(fs_type
, flags
,
418 &priv
, __sdcardfs_fill_super
);
421 static struct dentry
*sdcardfs_mount_wrn(struct file_system_type
*fs_type
,
422 int flags
, const char *dev_name
, void *raw_data
)
424 WARN(1, "sdcardfs does not support mount. Use mount2.\n");
425 return ERR_PTR(-EINVAL
);
428 void *sdcardfs_alloc_mnt_data(void)
430 return kmalloc(sizeof(struct sdcardfs_vfsmount_options
), GFP_KERNEL
);
433 void sdcardfs_kill_sb(struct super_block
*sb
)
435 struct sdcardfs_sb_info
*sbi
;
437 if (sb
->s_magic
== SDCARDFS_SUPER_MAGIC
&& sb
->s_fs_info
) {
438 sbi
= SDCARDFS_SB(sb
);
439 mutex_lock(&sdcardfs_super_list_lock
);
440 list_del(&sbi
->list
);
441 mutex_unlock(&sdcardfs_super_list_lock
);
446 static struct file_system_type sdcardfs_fs_type
= {
447 .owner
= THIS_MODULE
,
448 .name
= SDCARDFS_NAME
,
449 .mount
= sdcardfs_mount_wrn
,
450 .mount2
= sdcardfs_mount
,
451 .alloc_mnt_data
= sdcardfs_alloc_mnt_data
,
452 .kill_sb
= sdcardfs_kill_sb
,
455 MODULE_ALIAS_FS(SDCARDFS_NAME
);
457 static int __init
init_sdcardfs_fs(void)
461 pr_info("Registering sdcardfs " SDCARDFS_VERSION
"\n");
463 err
= sdcardfs_init_inode_cache();
466 err
= sdcardfs_init_dentry_cache();
469 err
= packagelist_init();
472 err
= register_filesystem(&sdcardfs_fs_type
);
475 sdcardfs_destroy_inode_cache();
476 sdcardfs_destroy_dentry_cache();
482 static void __exit
exit_sdcardfs_fs(void)
484 sdcardfs_destroy_inode_cache();
485 sdcardfs_destroy_dentry_cache();
487 unregister_filesystem(&sdcardfs_fs_type
);
488 pr_info("Completed sdcardfs module unload\n");
491 /* Original wrapfs authors */
492 MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University (http://www.fsl.cs.sunysb.edu/)");
494 /* Original sdcardfs authors */
495 MODULE_AUTHOR("Woojoong Lee, Daeho Jeong, Kitae Lee, Yeongjin Gil System Memory Lab., Samsung Electronics");
497 /* Current maintainer */
498 MODULE_AUTHOR("Daniel Rosenberg, Google");
499 MODULE_DESCRIPTION("Sdcardfs " SDCARDFS_VERSION
);
500 MODULE_LICENSE("GPL");
502 module_init(init_sdcardfs_fs
);
503 module_exit(exit_sdcardfs_fs
);