btrfs: add readonly flag
authorArne Jansen <sensille@gmx.net>
Wed, 23 Mar 2011 15:34:19 +0000 (16:34 +0100)
committerArne Jansen <sensille@gmx.net>
Thu, 12 May 2011 12:48:31 +0000 (14:48 +0200)
setting the readonly flag prevents writes in case an error is detected

Signed-off-by: Arne Jansen <sensille@gmx.net>
fs/btrfs/ctree.h
fs/btrfs/ioctl.c
fs/btrfs/ioctl.h
fs/btrfs/scrub.c

index b7373b14e4cdc9665932e95c7982bf51a41da9f9..ee904666b766682b7d422a60124ab8feecc70014 100644 (file)
@@ -2657,7 +2657,7 @@ void btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans,
 
 /* scrub.c */
 int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end,
-                   struct btrfs_scrub_progress *progress);
+                   struct btrfs_scrub_progress *progress, int readonly);
 int btrfs_scrub_pause(struct btrfs_root *root);
 int btrfs_scrub_pause_super(struct btrfs_root *root);
 int btrfs_scrub_continue(struct btrfs_root *root);
index 205cd011d2f38fdf2242501d6d0c674e416e0dcc..f0a74f0147482ff8569cf82ca2e9e8e8b3069237 100644 (file)
@@ -2547,7 +2547,7 @@ static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg)
                return PTR_ERR(sa);
 
        ret = btrfs_scrub_dev(root, sa->devid, sa->start, sa->end,
-                             &sa->progress);
+                             &sa->progress, sa->flags & BTRFS_SCRUB_READONLY);
 
        if (copy_to_user(arg, sa, sizeof(*sa)))
                ret = -EFAULT;
index 1a638ceeead8bbd9787ccc92c0d491beb4c53ca5..e5e0ee2cad4e9bb828ffd316ebb585dce549aa8d 100644 (file)
@@ -81,6 +81,7 @@ struct btrfs_scrub_progress {
                                         * Intermittent error. */
 };
 
+#define BTRFS_SCRUB_READONLY   1
 struct btrfs_ioctl_scrub_args {
        __u64 devid;                            /* in */
        __u64 start;                            /* in */
index 6a50801ecfa079bdf20f8ade1cef4dc53ca161fa..a31f2a9bd2e20f43f9be9e6ccabc98ef807164ea 100644 (file)
@@ -42,7 +42,6 @@
  *  - In case of a read error on files with nodatasum, map the file and read
  *    the extent to trigger a writeback of the good copy
  *  - track and record media errors, throw out bad devices
- *  - add a readonly mode
  *  - add a mode to also read unallocated space
  *  - make the prefetch cancellable
  */
@@ -99,6 +98,7 @@ struct scrub_dev {
        u16                     csum_size;
        struct list_head        csum_list;
        atomic_t                cancel_req;
+       int                     readonly;
        /*
         * statistics
         */
@@ -329,14 +329,16 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix)
        if (i == multi->num_stripes)
                goto uncorrectable;
 
-       /*
-        * bi_io_vec[ix].bv_page now contains good data, write it back
-        */
-       if (scrub_fixup_io(WRITE, sdev->dev->bdev,
-                          (sbio->physical + ix * PAGE_SIZE) >> 9,
-                          sbio->bio->bi_io_vec[ix].bv_page)) {
-               /* I/O-error, writeback failed, give up */
-               goto uncorrectable;
+       if (!sdev->readonly) {
+               /*
+                * bi_io_vec[ix].bv_page now contains good data, write it back
+                */
+               if (scrub_fixup_io(WRITE, sdev->dev->bdev,
+                                  (sbio->physical + ix * PAGE_SIZE) >> 9,
+                                  sbio->bio->bi_io_vec[ix].bv_page)) {
+                       /* I/O-error, writeback failed, give up */
+                       goto uncorrectable;
+               }
        }
 
        kfree(multi);
@@ -1156,7 +1158,7 @@ static noinline_for_stack void scrub_workers_put(struct btrfs_root *root)
 
 
 int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end,
-                   struct btrfs_scrub_progress *progress)
+                   struct btrfs_scrub_progress *progress, int readonly)
 {
        struct scrub_dev *sdev;
        struct btrfs_fs_info *fs_info = root->fs_info;
@@ -1209,6 +1211,7 @@ int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end,
                scrub_workers_put(root);
                return PTR_ERR(sdev);
        }
+       sdev->readonly = readonly;
        dev->scrub_device = sdev;
 
        atomic_inc(&fs_info->scrubs_running);