diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e163b1b74707..7ef79ce86e25 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2212,7 +2212,12 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
2212 | struct btrfs_trans_handle *trans; | 2212 | struct btrfs_trans_handle *trans; |
2213 | unsigned long nr = 0; | 2213 | unsigned long nr = 0; |
2214 | 2214 | ||
2215 | if (inode->i_size > BTRFS_EMPTY_DIR_SIZE) { | 2215 | /* |
2216 | * the FIRST_FREE_OBJECTID check makes sure we don't try to rmdir | ||
2217 | * the root of a subvolume or snapshot | ||
2218 | */ | ||
2219 | if (inode->i_size > BTRFS_EMPTY_DIR_SIZE || | ||
2220 | inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) { | ||
2216 | return -ENOTEMPTY; | 2221 | return -ENOTEMPTY; |
2217 | } | 2222 | } |
2218 | 2223 | ||
@@ -4410,7 +4415,6 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root, struct dentry *dentry, | |||
4410 | if (error) | 4415 | if (error) |
4411 | return error; | 4416 | return error; |
4412 | 4417 | ||
4413 | atomic_inc(&inode->i_count); | ||
4414 | d_instantiate(dentry, inode); | 4418 | d_instantiate(dentry, inode); |
4415 | return 0; | 4419 | return 0; |
4416 | } | 4420 | } |
@@ -4548,6 +4552,7 @@ static int btrfs_getattr(struct vfsmount *mnt, | |||
4548 | { | 4552 | { |
4549 | struct inode *inode = dentry->d_inode; | 4553 | struct inode *inode = dentry->d_inode; |
4550 | generic_fillattr(inode, stat); | 4554 | generic_fillattr(inode, stat); |
4555 | stat->dev = BTRFS_I(inode)->root->anon_super.s_dev; | ||
4551 | stat->blksize = PAGE_CACHE_SIZE; | 4556 | stat->blksize = PAGE_CACHE_SIZE; |
4552 | stat->blocks = (inode_get_bytes(inode) + | 4557 | stat->blocks = (inode_get_bytes(inode) + |
4553 | BTRFS_I(inode)->delalloc_bytes) >> 9; | 4558 | BTRFS_I(inode)->delalloc_bytes) >> 9; |
@@ -4565,6 +4570,11 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
4565 | u64 index = 0; | 4570 | u64 index = 0; |
4566 | int ret; | 4571 | int ret; |
4567 | 4572 | ||
4573 | /* we're not allowed to rename between subvolumes */ | ||
4574 | if (BTRFS_I(old_inode)->root->root_key.objectid != | ||
4575 | BTRFS_I(new_dir)->root->root_key.objectid) | ||
4576 | return -EXDEV; | ||
4577 | |||
4568 | if (S_ISDIR(old_inode->i_mode) && new_inode && | 4578 | if (S_ISDIR(old_inode->i_mode) && new_inode && |
4569 | new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) { | 4579 | new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) { |
4570 | return -ENOTEMPTY; | 4580 | return -ENOTEMPTY; |
@@ -4920,6 +4930,7 @@ static int btrfs_permission(struct inode *inode, int mask) | |||
4920 | } | 4930 | } |
4921 | 4931 | ||
4922 | static struct inode_operations btrfs_dir_inode_operations = { | 4932 | static struct inode_operations btrfs_dir_inode_operations = { |
4933 | .getattr = btrfs_getattr, | ||
4923 | .lookup = btrfs_lookup, | 4934 | .lookup = btrfs_lookup, |
4924 | .create = btrfs_create, | 4935 | .create = btrfs_create, |
4925 | .unlink = btrfs_unlink, | 4936 | .unlink = btrfs_unlink, |