Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.cz>2013-03-28 13:03:03 +0100
committerDavid Sterba <dsterba@suse.cz>2013-03-28 13:03:45 +0100
commit1de7f1b87d04e72d92f0d3588bb80ef3c490a5f2 (patch)
treebde468eb882955c4e3ae1e3c280de525052c46b9
parente6c853a81ee459ec76812604496e6e2ab37e72c4 (diff)
- btrfs: deprecate subvolrootid mount option.rpm-3.0.70-0.7
- btrfs: clean snapshots one by one. - btrfs: cover more error codes in btrfs_decode_error. - Btrfs: fix EIO from btrfs send in is_extent_unchanged for punched holes. - Btrfs: fix space leak when we fail to reserve metadata space. - Btrfs: fix space accounting for unlink and rename. - Btrfs: hold the ordered operations mutex when waiting on ordered extents. - Btrfs: limit the global reserve to 512mb. suse-commit: d30f6aa29ceb16da895151e3783b30a598b73239
-rw-r--r--fs/btrfs/disk-io.c13
-rw-r--r--fs/btrfs/extent-tree.c49
-rw-r--r--fs/btrfs/file.c3
-rw-r--r--fs/btrfs/inode.c6
-rw-r--r--fs/btrfs/ordered-data.c2
-rw-r--r--fs/btrfs/send.c10
-rw-r--r--fs/btrfs/super.c22
-rw-r--r--fs/btrfs/transaction.c5
8 files changed, 62 insertions, 48 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index dcec96014754..e7e9320c6784 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1695,19 +1695,16 @@ static int cleaner_kthread(void *arg)
do {
vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
- if (!down_read_trylock(&root->fs_info->sb->s_umount))
- goto skip;
-
if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&
+ down_read_trylock(&root->fs_info->sb->s_umount) &&
mutex_trylock(&root->fs_info->cleaner_mutex)) {
btrfs_run_delayed_iputs(root);
btrfs_clean_old_snapshots(root);
mutex_unlock(&root->fs_info->cleaner_mutex);
btrfs_run_defrag_inodes(root->fs_info);
+ up_read(&root->fs_info->sb->s_umount);
}
- up_read(&root->fs_info->sb->s_umount);
-skip:
if (freezing(current)) {
refrigerator();
} else {
@@ -3459,11 +3456,13 @@ int close_ctree(struct btrfs_root *root)
btrfs_scrub_cancel(fs_info);
+ /* wait for any defraggers to finish */
+ wait_event(fs_info->transaction_wait,
+ (atomic_read(&fs_info->defrag_running) == 0));
+
/* clear out the rbtree of defraggable inodes */
btrfs_cleanup_defrag_inodes(fs_info);
- BUG_ON(atomic_read(&fs_info->defrag_running));
-
if (!(fs_info->sb->s_flags & MS_RDONLY)) {
ret = btrfs_commit_super(root);
if (ret)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 68afd352239f..7f35deac75e2 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4457,7 +4457,7 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
spin_lock(&sinfo->lock);
spin_lock(&block_rsv->lock);
- block_rsv->size = num_bytes;
+ block_rsv->size = min_t(u64, num_bytes, 512 * 1024 * 1024);
num_bytes = sinfo->bytes_used + sinfo->bytes_pinned +
sinfo->bytes_reserved + sinfo->bytes_readonly +
@@ -4812,14 +4812,49 @@ out_fail:
* If the inodes csum_bytes is the same as the original
* csum_bytes then we know we haven't raced with any free()ers
* so we can just reduce our inodes csum bytes and carry on.
- * Otherwise we have to do the normal free thing to account for
- * the case that the free side didn't free up its reserve
- * because of this outstanding reservation.
*/
- if (BTRFS_I(inode)->csum_bytes == csum_bytes)
+ if (BTRFS_I(inode)->csum_bytes == csum_bytes) {
calc_csum_metadata_size(inode, num_bytes, 0);
- else
- to_free = calc_csum_metadata_size(inode, num_bytes, 0);
+ } else {
+ u64 orig_csum_bytes = BTRFS_I(inode)->csum_bytes;
+ u64 bytes;
+
+ /*
+ * This is tricky, but first we need to figure out how much we
+ * free'd from any free-ers that occured during this
+ * reservation, so we reset ->csum_bytes to the csum_bytes
+ * before we dropped our lock, and then call the free for the
+ * number of bytes that were freed while we were trying our
+ * reservation.
+ */
+ bytes = csum_bytes - BTRFS_I(inode)->csum_bytes;
+ BTRFS_I(inode)->csum_bytes = csum_bytes;
+ to_free = calc_csum_metadata_size(inode, bytes, 0);
+
+
+ /*
+ * Now we need to see how much we would have freed had we not
+ * been making this reservation and our ->csum_bytes were not
+ * artificially inflated.
+ */
+ BTRFS_I(inode)->csum_bytes = csum_bytes - num_bytes;
+ bytes = csum_bytes - orig_csum_bytes;
+ bytes = calc_csum_metadata_size(inode, bytes, 0);
+
+ /*
+ * Now reset ->csum_bytes to what it should be. If bytes is
+ * more than to_free then we would have free'd more space had we
+ * not had an artificially high ->csum_bytes, so we need to free
+ * the remainder. If bytes is the same or less then we don't
+ * need to do anything, the other free-ers did the correct
+ * thing.
+ */
+ BTRFS_I(inode)->csum_bytes = orig_csum_bytes - num_bytes;
+ if (bytes > to_free)
+ to_free = bytes - to_free;
+ else
+ to_free = 0;
+ }
spin_unlock(&BTRFS_I(inode)->lock);
if (dropped)
to_free += btrfs_calc_trans_metadata_size(root, dropped);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 5d6460f395de..2a945a5bfcb8 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -136,8 +136,7 @@ static inline int __need_auto_defrag(struct btrfs_root *root)
if (!btrfs_test_opt(root, AUTO_DEFRAG))
return 0;
- if (btrfs_fs_closing(root->fs_info)
- || (root->fs_info->sb->s_flags & MS_RDONLY))
+ if (btrfs_fs_closing(root->fs_info))
return 0;
return 1;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 0ee1c35215cf..153186622b9a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3694,11 +3694,9 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir,
* 1 for the dir item
* 1 for the dir index
* 1 for the inode ref
- * 1 for the inode ref in the tree log
- * 2 for the dir entries in the log
* 1 for the inode
*/
- trans = btrfs_start_transaction(root, 8);
+ trans = btrfs_start_transaction(root, 5);
if (!IS_ERR(trans) || PTR_ERR(trans) != -ENOSPC)
return trans;
@@ -8122,7 +8120,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
* inodes. So 5 * 2 is 10, plus 1 for the new link, so 11 total items
* should cover the worst case number of items we'll modify.
*/
- trans = btrfs_start_transaction(root, 20);
+ trans = btrfs_start_transaction(root, 11);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
goto out_notrans;
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 261710b453cb..48b202e68024 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -557,6 +557,7 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput)
INIT_LIST_HEAD(&splice);
INIT_LIST_HEAD(&works);
+ mutex_lock(&root->fs_info->ordered_operations_mutex);
spin_lock(&root->fs_info->ordered_extent_lock);
list_splice_init(&root->fs_info->ordered_extents, &splice);
while (!list_empty(&splice)) {
@@ -600,6 +601,7 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput)
cond_resched();
}
+ mutex_unlock(&root->fs_info->ordered_operations_mutex);
}
/*
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index f14fc25c0d04..54754d2ee3b5 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -3944,12 +3944,10 @@ static int is_extent_unchanged(struct send_ctx *sctx,
found_key.type != key.type) {
key.offset += right_len;
break;
- } else {
- if (found_key.offset != key.offset + right_len) {
- /* Should really not happen */
- ret = -EIO;
- goto out;
- }
+ }
+ if (found_key.offset != key.offset + right_len) {
+ ret = 0;
+ goto out;
}
key = found_key;
}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 5ed88f7142c8..3c8f11381938 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -644,7 +644,7 @@ out:
*/
static int btrfs_parse_early_options(const char *options, fmode_t flags,
void *holder, char **subvol_name, u64 *subvol_objectid,
- u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices)
+ struct btrfs_fs_devices **fs_devices)
{
substring_t args[MAX_OPT_ARGS];
char *device_name, *opts, *orig, *p;
@@ -687,16 +687,8 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
}
break;
case Opt_subvolrootid:
- intarg = 0;
- error = match_int(&args[0], &intarg);
- if (!error) {
- /* we want the original fs_tree */
- if (!intarg)
- *subvol_rootid =
- BTRFS_FS_TREE_OBJECTID;
- else
- *subvol_rootid = intarg;
- }
+ printk(KERN_WARNING
+ "btrfs: 'subvolrootid' mount option is deprecated and has no effect\n");
break;
case Opt_device:
device_name = match_strdup(&args[0]);
@@ -1103,7 +1095,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
fmode_t mode = FMODE_READ;
char *subvol_name = NULL;
u64 subvol_objectid = 0;
- u64 subvol_rootid = 0;
int error = 0;
if (!(flags & MS_RDONLY))
@@ -1111,7 +1102,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
error = btrfs_parse_early_options(data, mode, fs_type,
&subvol_name, &subvol_objectid,
- &subvol_rootid, &fs_devices);
+ &fs_devices);
if (error) {
kfree(subvol_name);
return ERR_PTR(error);
@@ -1297,11 +1288,6 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
ret = btrfs_commit_super(root);
if (ret)
goto restore;
-
- /* clear out the rbtree of defraggable inodes */
- btrfs_run_defrag_inodes(fs_info);
-
- BUG_ON(atomic_read(&fs_info->defrag_running));
} else {
if (fs_info->fs_devices->rw_devices == 0) {
ret = -EACCES;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index ae08ada32546..dbeae5cf87e1 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1890,10 +1890,7 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root)
ret = btrfs_drop_snapshot(root, NULL, 0, 0);
else
ret =btrfs_drop_snapshot(root, NULL, 1, 0);
- /*
- * Continue after a transaction abort during drop
- */
- BUG_ON(ret < 0 && ret != -EROFS && ret != -ENOSPC);
+ BUG_ON(ret < 0);
}
return 0;
}