btrfs: copy dir permission and time when creating a stub subvolume
btrfs supports creating nested subvolumes however snapshots are not recursive. When a snapshot is taken of a volume which contains a subvolume the subvolume is replaced with a stub subvolume which has the same name and uses inode number 2[1]. The stub subvolume kept the directory name but did not set the time or permissions of the stub subvolume. This resulted in all time information being the current time and ownership defaulting to root. When subvolumes and snapshots are created using unshare this results in a snapshot directory the user created but has no permissions for. Test case: [vmuser@archvm ~]# sudo -i [root@archvm ~]# mkdir -p /mnt/btrfs/test [root@archvm ~]# chown vmuser:users /mnt/btrfs/test/ [root@archvm ~]# exit logout [vmuser@archvm ~]$ cd /mnt/btrfs/test [vmuser@archvm test]$ unshare --user --keep-caps --map-auto --map-root-user [root@archvm test]# btrfs subvolume create subvolume Create subvolume './subvolume' [root@archvm test]# btrfs subvolume create subvolume/subsubvolume Create subvolume 'subvolume/subsubvolume' [root@archvm test]# btrfs subvolume snapshot subvolume snapshot Create a snapshot of 'subvolume' in './snapshot' [root@archvm test]# exit logout [vmuser@archvm test]$ tree -ug [vmuser users ] . ├── [vmuser users ] snapshot │ └── [vmuser users ] subsubvolume <-- Without patch perm is root:root └── [vmuser users ] subvolume └── [vmuser users ] subsubvolume 5 directories, 0 files [1] https://btrfs.readthedocs.io/en/latest/btrfs-subvolume.html#nested-subvolumes Signed-off-by: Lee Trager <lee@trager.us> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
6b604c9a0c
commit
94628ad944
|
@ -5585,11 +5585,11 @@ struct inode *btrfs_iget(struct super_block *s, u64 ino, struct btrfs_root *root
|
|||
return btrfs_iget_path(s, ino, root, NULL);
|
||||
}
|
||||
|
||||
static struct inode *new_simple_dir(struct super_block *s,
|
||||
static struct inode *new_simple_dir(struct inode *dir,
|
||||
struct btrfs_key *key,
|
||||
struct btrfs_root *root)
|
||||
{
|
||||
struct inode *inode = new_inode(s);
|
||||
struct inode *inode = new_inode(dir->i_sb);
|
||||
|
||||
if (!inode)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
@ -5608,9 +5608,11 @@ static struct inode *new_simple_dir(struct super_block *s,
|
|||
inode->i_fop = &simple_dir_operations;
|
||||
inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
|
||||
inode->i_mtime = current_time(inode);
|
||||
inode->i_atime = inode->i_mtime;
|
||||
inode->i_ctime = inode->i_mtime;
|
||||
inode->i_atime = dir->i_atime;
|
||||
inode->i_ctime = dir->i_ctime;
|
||||
BTRFS_I(inode)->i_otime = inode->i_mtime;
|
||||
inode->i_uid = dir->i_uid;
|
||||
inode->i_gid = dir->i_gid;
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
@ -5669,7 +5671,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
|
|||
if (ret != -ENOENT)
|
||||
inode = ERR_PTR(ret);
|
||||
else
|
||||
inode = new_simple_dir(dir->i_sb, &location, root);
|
||||
inode = new_simple_dir(dir, &location, root);
|
||||
} else {
|
||||
inode = btrfs_iget(dir->i_sb, location.objectid, sub_root);
|
||||
btrfs_put_root(sub_root);
|
||||
|
|
Loading…
Reference in New Issue