OSDN Git Service

btrfs: send: limit number of clones and allocated memory size
[tomoyo/tomoyo-test1.git] / fs / btrfs / block-rsv.c
index ec96285..5367a14 100644 (file)
@@ -7,6 +7,8 @@
 #include "transaction.h"
 #include "block-group.h"
 #include "disk-io.h"
+#include "fs.h"
+#include "accessors.h"
 
 /*
  * HOW DO BLOCK RESERVES WORK
@@ -225,7 +227,7 @@ int btrfs_block_rsv_add(struct btrfs_fs_info *fs_info,
        return ret;
 }
 
-int btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_factor)
+int btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_percent)
 {
        u64 num_bytes = 0;
        int ret = -ENOSPC;
@@ -234,7 +236,7 @@ int btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_factor)
                return 0;
 
        spin_lock(&block_rsv->lock);
-       num_bytes = div_factor(block_rsv->size, min_factor);
+       num_bytes = mult_perc(block_rsv->size, min_percent);
        if (block_rsv->reserved >= num_bytes)
                ret = 0;
        spin_unlock(&block_rsv->lock);
@@ -323,31 +325,6 @@ void btrfs_block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv,
        spin_unlock(&block_rsv->lock);
 }
 
-int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info,
-                            struct btrfs_block_rsv *dest, u64 num_bytes,
-                            int min_factor)
-{
-       struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
-       u64 min_bytes;
-
-       if (global_rsv->space_info != dest->space_info)
-               return -ENOSPC;
-
-       spin_lock(&global_rsv->lock);
-       min_bytes = div_factor(global_rsv->size, min_factor);
-       if (global_rsv->reserved < min_bytes + num_bytes) {
-               spin_unlock(&global_rsv->lock);
-               return -ENOSPC;
-       }
-       global_rsv->reserved -= num_bytes;
-       if (global_rsv->reserved < global_rsv->size)
-               global_rsv->full = false;
-       spin_unlock(&global_rsv->lock);
-
-       btrfs_block_rsv_add_bytes(dest, num_bytes, true);
-       return 0;
-}
-
 void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
 {
        struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
@@ -552,5 +529,17 @@ try_reserve:
                if (!ret)
                        return global_rsv;
        }
+
+       /*
+        * All hope is lost, but of course our reservations are overly
+        * pessimistic, so instead of possibly having an ENOSPC abort here, try
+        * one last time to force a reservation if there's enough actual space
+        * on disk to make the reservation.
+        */
+       ret = btrfs_reserve_metadata_bytes(fs_info, block_rsv, blocksize,
+                                          BTRFS_RESERVE_FLUSH_EMERGENCY);
+       if (!ret)
+               return block_rsv;
+
        return ERR_PTR(ret);
 }