void get_derived_permission(struct dentry *parent, struct dentry *dentry)
{
	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
	struct sdcardfs_inode_info *info = SDCARDFS_I(dentry->d_inode);
	struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
	appid_t appid;

	/* By default, each inode inherits from its parent.
	 * the properties are maintained on its private fields
	 * because the inode attributes will be modified with that of
	 * its lower inode.
	 * The derived state will be updated on the last
	 * stage of each system call by fix_derived_permission(inode).
	 */

	inherit_derived_state(parent->d_inode, dentry->d_inode);

	/* Derive custom permissions based on parent and current node */
	switch (parent_info->perm) {
		case PERM_INHERIT:
			/* Already inherited above */
			break;
        case PERM_PRE_ROOT:
			/* Legacy internal layout places users at top level */
			info->perm = PERM_ROOT;
			info->userid = simple_strtoul(dentry->d_name.name, NULL, 10);
            if (sbi->options.sdfs_gid == AID_SDCARD_RW)
                info->d_gid = sbi->options.sdfs_gid;
            else
                info->d_gid = multiuser_get_uid(info->userid, sbi->options.sdfs_gid);
			break;
		case PERM_ROOT:
			/* Assume masked off by default. */
			if (!strcasecmp(dentry->d_name.name, "Android")) {
				/* App-specific directories inside; let anyone traverse */
				info->perm = PERM_ANDROID;
                info->d_under_android = true;
            }
			break;
		case PERM_ANDROID:
			if (!strcasecmp(dentry->d_name.name, "data")) {
				/* App-specific directories inside; let anyone traverse */
				info->perm = PERM_ANDROID_DATA;
			} else if (!strcasecmp(dentry->d_name.name, "obb")) {
				/* App-specific directories inside; let anyone traverse */
				info->perm = PERM_ANDROID_OBB;
				// FIXME : this feature will be implemented later.
				/* Single OBB directory is always shared */
                // ex. Fuse daemon..
                // node->graft_path = fuse->obb_path;
                // node->graft_pathlen = strlen(fuse->obb_path);
			} else if (!strcasecmp(dentry->d_name.name, "media")) {
				/* App-specific directories inside; let anyone traverse */
				info->perm = PERM_ANDROID_MEDIA;
			}
			break;
		/* same policy will be applied on PERM_ANDROID_DATA
		 * and PERM_ANDROID_OBB */
		case PERM_ANDROID_DATA:
		case PERM_ANDROID_OBB:
		case PERM_ANDROID_MEDIA:
			appid = get_appid(sbi->pkgl_id, dentry->d_name.name);
			if (appid != 0) {
				info->d_uid = multiuser_get_uid(parent_info->userid, appid);
			}
			break;
	}
}
void get_derived_permission_lollipop(struct dentry *parent, struct dentry *dentry)
{
	struct sdcardfslp_sb_info *sbi = SDCARDFSLP_SB(dentry->d_sb);
	struct sdcardfslp_inode_info *info = SDCARDFSLP_I(dentry->d_inode);
	struct sdcardfslp_inode_info *parent_info= SDCARDFSLP_I(parent->d_inode);
	appid_t appid;

	/* By default, each inode inherits from its parent.
	 * the properties are maintained on its private fields
	 * because the inode attributes will be modified with that of
	 * its lower inode.
	 * The derived state will be updated on the last
	 * stage of each system call by fix_derived_permission(inode).
	 */

	inherit_derived_state(parent->d_inode, dentry->d_inode);

	//printk(KERN_INFO "sdcardfslp: derived: %s, %s, %d\n", parent->d_name.name,
	//				dentry->d_name.name, parent_info->perm);

	if (sbi->options.derive == DERIVE_NONE) {
		return;
	}

	/* Derive custom permissions based on parent and current node */
	switch (parent_info->perm) {
		case PERM_INHERIT:
			/* Already inherited above */
			break;
		case PERM_LEGACY_PRE_ROOT:
			/* Legacy internal layout places users at top level */
			info->perm = PERM_ROOT;
			info->userid = simple_strtoul(dentry->d_name.name, NULL, 10);
			break;
		case PERM_ROOT:
			/* Assume masked off by default. */
			info->d_mode = 00770;
			if (!strcasecmp(dentry->d_name.name, "Android")) {
				/* App-specific directories inside; let anyone traverse */
				info->perm = PERM_ANDROID;
				info->d_mode = 00771;
			} else if (sbi->options.split_perms) {
				if (!strcasecmp(dentry->d_name.name, "DCIM")
					|| !strcasecmp(dentry->d_name.name, "Pictures")) {
					info->d_gid = AID_SDCARD_PICS;
				} else if (!strcasecmp(dentry->d_name.name, "Alarms")
						|| !strcasecmp(dentry->d_name.name, "Movies")
						|| !strcasecmp(dentry->d_name.name, "Music")
						|| !strcasecmp(dentry->d_name.name, "Notifications")
						|| !strcasecmp(dentry->d_name.name, "Podcasts")
						|| !strcasecmp(dentry->d_name.name, "Ringtones")) {
					info->d_gid = AID_SDCARD_AV;
				}
			}
			break;
		case PERM_ANDROID:
			if (!strcasecmp(dentry->d_name.name, "data")) {
				/* App-specific directories inside; let anyone traverse */
				info->perm = PERM_ANDROID_DATA;
				info->d_mode = 00771;
			} else if (!strcasecmp(dentry->d_name.name, "obb")) {
				/* App-specific directories inside; let anyone traverse */
				info->perm = PERM_ANDROID_OBB;
				info->d_mode = 00771;
				// FIXME : this feature will be implemented later.
				/* Single OBB directory is always shared */
			} else if (!strcasecmp(dentry->d_name.name, "media")) {
				/* App-specific directories inside; let anyone traverse */
				info->perm = PERM_ANDROID_MEDIA;
				info->d_mode = 00771;
			} else if (!strcasecmp(dentry->d_name.name, "user")) {
				/* User directories must only be accessible to system, protected
				 * by sdcard_all. Zygote will bind mount the appropriate user-
				 * specific path. */
				info->perm = PERM_ANDROID_USER;
				info->d_gid = AID_SDCARD_ALL;
				info->d_mode = 00770;
			}
			break;
		/* same policy will be applied on PERM_ANDROID_DATA
		 * and PERM_ANDROID_OBB */
		case PERM_ANDROID_DATA:
		case PERM_ANDROID_OBB:
		case PERM_ANDROID_MEDIA:
			appid = get_appid_lollipop(sbi->pkgl_id, dentry->d_name.name);
			if (appid != 0) {
				info->d_uid = multiuser_get_uid(parent_info->userid, appid);
			}
			info->d_mode = 00770;
			break;
		case PERM_ANDROID_USER:
			/* Root of a secondary user */
			info->perm = PERM_ROOT;
			info->userid = simple_strtoul(dentry->d_name.name, NULL, 10);
			info->d_gid = AID_SDCARD_R;
			info->d_mode = 00771;
			break;
	}
}