ANDROID: sdcardfs: Added top to sdcardfs_inode_info
Adding packages to the package list and moving files
takes a large amount of locks, and is currently a
heavy operation. This adds a 'top' field to the
inode_info, which points to the inode for the top
most directory whose owner you would like to match.
On permission checks and get_attr, we look up the
owner based on the information at top. When we change
a package mapping, we need only modify the information
in the corresponding top inode_info's. When renaming,
we must ensure top is set correctly in all children.
This happens when an app specific folder gets moved
outside of the folder for that app.
Change-Id: Ib749c60b568e9a45a46f8ceed985c1338246ec6c
Signed-off-by: Daniel Rosenberg <drosen@google.com>
diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c
index 1a23c0c..67bcee2 100644
--- a/fs/sdcardfs/inode.c
+++ b/fs/sdcardfs/inode.c
@@ -515,7 +515,7 @@
* we pass along new_dentry for the name.*/
get_derived_permission_new(new_dentry->d_parent, old_dentry, new_dentry);
fix_derived_permission(d_inode(old_dentry));
- get_derive_permissions_recursive(old_dentry);
+ fixup_top_recursive(old_dentry);
out:
unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
dput(lower_old_dir_dentry);
@@ -587,6 +587,16 @@
static int sdcardfs_permission(struct inode *inode, int mask)
{
int err;
+ struct inode *top = grab_top(SDCARDFS_I(inode));
+
+ if (!top)
+ return -EINVAL;
+ /* Ensure owner is up to date */
+ if (!uid_eq(inode->i_uid, top->i_uid)) {
+ SDCARDFS_I(inode)->d_uid = SDCARDFS_I(top)->d_uid;
+ fix_derived_permission(inode);
+ }
+ release_top(SDCARDFS_I(inode));
/*
* Permission check on sdcardfs inode.
@@ -725,6 +735,30 @@
return err;
}
+static int sdcardfs_fillattr(struct inode *inode, struct kstat *stat)
+{
+ struct sdcardfs_inode_info *info = SDCARDFS_I(inode);
+ struct inode *top = grab_top(info);
+ if (!top)
+ return -EINVAL;
+
+ stat->dev = inode->i_sb->s_dev;
+ stat->ino = inode->i_ino;
+ stat->mode = (inode->i_mode & S_IFMT) | get_mode(SDCARDFS_I(top));
+ stat->nlink = inode->i_nlink;
+ stat->uid = make_kuid(&init_user_ns, SDCARDFS_I(top)->d_uid);
+ stat->gid = make_kgid(&init_user_ns, get_gid(SDCARDFS_I(top)));
+ stat->rdev = inode->i_rdev;
+ stat->size = i_size_read(inode);
+ stat->atime = inode->i_atime;
+ stat->mtime = inode->i_mtime;
+ stat->ctime = inode->i_ctime;
+ stat->blksize = (1 << inode->i_blkbits);
+ stat->blocks = inode->i_blocks;
+ release_top(info);
+ return 0;
+}
+
static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
@@ -733,6 +767,7 @@
struct inode *lower_inode;
struct path lower_path;
struct dentry *parent;
+ int err;
parent = dget_parent(dentry);
if(!check_caller_access_to_name(d_inode(parent), dentry->d_name.name)) {
@@ -750,14 +785,12 @@
lower_dentry = lower_path.dentry;
lower_inode = sdcardfs_lower_inode(inode);
-
sdcardfs_copy_and_fix_attrs(inode, lower_inode);
fsstack_copy_inode_size(inode, lower_inode);
-
- generic_fillattr(inode, stat);
+ err = sdcardfs_fillattr(inode, stat);
sdcardfs_put_lower_path(dentry, &lower_path);
- return 0;
+ return err;
}
const struct inode_operations sdcardfs_symlink_iops = {
@@ -775,9 +808,7 @@
const struct inode_operations sdcardfs_dir_iops = {
.create = sdcardfs_create,
.lookup = sdcardfs_lookup,
-#if 0
.permission = sdcardfs_permission,
-#endif
.unlink = sdcardfs_unlink,
.mkdir = sdcardfs_mkdir,
.rmdir = sdcardfs_rmdir,