Hi,

This patch (against experimental HEAD) attempts to make shrinking more
robust, by only updating device size if we've succeeded in creating
enough free space without any failures in btrfs_relocate_chunk().

Here's a log with my patch applied.  The two things to note are that a
near-limit shrink now works, and that a failed shrink (in this case,
trying to shrink to less than the used space) no longer updates the
device size erroneously:

  http://dev.laptop.org/~cjb/btrfs/shrink-log

Please review carefully -- I'm still new to btrfs.  The short version of
the patch is:

* create a success path, as a break out of the while(1) relocating
  (rather than going to the "done" label).
* move the device size updating code into that path
* leave "path->reada = 2;" behind in the entry path, since path is
  used by the searching operation rather than the later resize.

Thanks!

Signed-off-by: Chris Ball <c...@laptop.org>

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 1316139..e2fa072 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1815,30 +1815,8 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 
new_size)
        if (!path)
                return -ENOMEM;
 
-       trans = btrfs_start_transaction(root, 1);
-       if (!trans) {
-               ret = -ENOMEM;
-               goto done;
-       }
-
        path->reada = 2;
 
-       lock_chunks(root);
-
-       device->total_bytes = new_size;
-       if (device->writeable)
-               device->fs_devices->total_rw_bytes -= diff;
-       ret = btrfs_update_device(trans, device);
-       if (ret) {
-               unlock_chunks(root);
-               btrfs_end_transaction(trans, root);
-               goto done;
-       }
-       WARN_ON(diff > old_total);
-       btrfs_set_super_total_bytes(super_copy, old_total - diff);
-       unlock_chunks(root);
-       btrfs_end_transaction(trans, root);
-
        key.objectid = device->devid;
        key.offset = (u64)-1;
        key.type = BTRFS_DEV_EXTENT_KEY;
@@ -1867,7 +1845,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 
new_size)
                length = btrfs_dev_extent_length(l, dev_extent);
 
                if (key.offset + length <= new_size)
-                       goto done;
+                       break;
 
                chunk_tree = btrfs_dev_extent_chunk_tree(l, dev_extent);
                chunk_objectid = btrfs_dev_extent_chunk_objectid(l, dev_extent);
@@ -1880,6 +1858,31 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 
new_size)
                        goto done;
        }
 
+       /*
+        * We've succeeded in freeing up enough space and can now update
+        * the device's size.
+        */
+       trans = btrfs_start_transaction(root, 1);
+       if (!trans) {
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       lock_chunks(root);
+       device->total_bytes = new_size;
+       if (device->writeable)
+               device->fs_devices->total_rw_bytes -= diff;
+       ret = btrfs_update_device(trans, device);
+       if (ret) {
+               unlock_chunks(root);
+               btrfs_end_transaction(trans, root);
+               goto done;
+       }
+       WARN_ON(diff > old_total);
+       btrfs_set_super_total_bytes(super_copy, old_total - diff);
+       unlock_chunks(root);
+       btrfs_end_transaction(trans, root);
+
 done:
        btrfs_free_path(path);
        return ret;


-- 
Chris Ball   <c...@laptop.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to