diff options
author | Arne Jansen <sensille@gmx.net> | 2011-03-23 11:34:19 -0400 |
---|---|---|
committer | Arne Jansen <sensille@gmx.net> | 2011-05-12 08:48:31 -0400 |
commit | 8628764e1a5e1998a42b9713e9edea7753653d01 (patch) | |
tree | 19c88f4d4eb806f7d5de83a1fc36996658ace17d /fs/btrfs | |
parent | 96e369208e65a7d017a52361fd572df41fde8472 (diff) |
btrfs: add readonly flag
setting the readonly flag prevents writes in case an error is detected
Signed-off-by: Arne Jansen <sensille@gmx.net>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 2 | ||||
-rw-r--r-- | fs/btrfs/ioctl.h | 1 | ||||
-rw-r--r-- | fs/btrfs/scrub.c | 23 |
4 files changed, 16 insertions, 12 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index b7373b14e4cd..ee904666b766 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -2657,7 +2657,7 @@ void btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans, | |||
2657 | 2657 | ||
2658 | /* scrub.c */ | 2658 | /* scrub.c */ |
2659 | int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end, | 2659 | int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end, |
2660 | struct btrfs_scrub_progress *progress); | 2660 | struct btrfs_scrub_progress *progress, int readonly); |
2661 | int btrfs_scrub_pause(struct btrfs_root *root); | 2661 | int btrfs_scrub_pause(struct btrfs_root *root); |
2662 | int btrfs_scrub_pause_super(struct btrfs_root *root); | 2662 | int btrfs_scrub_pause_super(struct btrfs_root *root); |
2663 | int btrfs_scrub_continue(struct btrfs_root *root); | 2663 | int btrfs_scrub_continue(struct btrfs_root *root); |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 205cd011d2f3..f0a74f014748 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -2547,7 +2547,7 @@ static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg) | |||
2547 | return PTR_ERR(sa); | 2547 | return PTR_ERR(sa); |
2548 | 2548 | ||
2549 | ret = btrfs_scrub_dev(root, sa->devid, sa->start, sa->end, | 2549 | ret = btrfs_scrub_dev(root, sa->devid, sa->start, sa->end, |
2550 | &sa->progress); | 2550 | &sa->progress, sa->flags & BTRFS_SCRUB_READONLY); |
2551 | 2551 | ||
2552 | if (copy_to_user(arg, sa, sizeof(*sa))) | 2552 | if (copy_to_user(arg, sa, sizeof(*sa))) |
2553 | ret = -EFAULT; | 2553 | ret = -EFAULT; |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 1a638ceeead8..e5e0ee2cad4e 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
@@ -81,6 +81,7 @@ struct btrfs_scrub_progress { | |||
81 | * Intermittent error. */ | 81 | * Intermittent error. */ |
82 | }; | 82 | }; |
83 | 83 | ||
84 | #define BTRFS_SCRUB_READONLY 1 | ||
84 | struct btrfs_ioctl_scrub_args { | 85 | struct btrfs_ioctl_scrub_args { |
85 | __u64 devid; /* in */ | 86 | __u64 devid; /* in */ |
86 | __u64 start; /* in */ | 87 | __u64 start; /* in */ |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 6a50801ecfa0..a31f2a9bd2e2 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -42,7 +42,6 @@ | |||
42 | * - In case of a read error on files with nodatasum, map the file and read | 42 | * - In case of a read error on files with nodatasum, map the file and read |
43 | * the extent to trigger a writeback of the good copy | 43 | * the extent to trigger a writeback of the good copy |
44 | * - track and record media errors, throw out bad devices | 44 | * - track and record media errors, throw out bad devices |
45 | * - add a readonly mode | ||
46 | * - add a mode to also read unallocated space | 45 | * - add a mode to also read unallocated space |
47 | * - make the prefetch cancellable | 46 | * - make the prefetch cancellable |
48 | */ | 47 | */ |
@@ -99,6 +98,7 @@ struct scrub_dev { | |||
99 | u16 csum_size; | 98 | u16 csum_size; |
100 | struct list_head csum_list; | 99 | struct list_head csum_list; |
101 | atomic_t cancel_req; | 100 | atomic_t cancel_req; |
101 | int readonly; | ||
102 | /* | 102 | /* |
103 | * statistics | 103 | * statistics |
104 | */ | 104 | */ |
@@ -329,14 +329,16 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) | |||
329 | if (i == multi->num_stripes) | 329 | if (i == multi->num_stripes) |
330 | goto uncorrectable; | 330 | goto uncorrectable; |
331 | 331 | ||
332 | /* | 332 | if (!sdev->readonly) { |
333 | * bi_io_vec[ix].bv_page now contains good data, write it back | 333 | /* |
334 | */ | 334 | * bi_io_vec[ix].bv_page now contains good data, write it back |
335 | if (scrub_fixup_io(WRITE, sdev->dev->bdev, | 335 | */ |
336 | (sbio->physical + ix * PAGE_SIZE) >> 9, | 336 | if (scrub_fixup_io(WRITE, sdev->dev->bdev, |
337 | sbio->bio->bi_io_vec[ix].bv_page)) { | 337 | (sbio->physical + ix * PAGE_SIZE) >> 9, |
338 | /* I/O-error, writeback failed, give up */ | 338 | sbio->bio->bi_io_vec[ix].bv_page)) { |
339 | goto uncorrectable; | 339 | /* I/O-error, writeback failed, give up */ |
340 | goto uncorrectable; | ||
341 | } | ||
340 | } | 342 | } |
341 | 343 | ||
342 | kfree(multi); | 344 | kfree(multi); |
@@ -1156,7 +1158,7 @@ static noinline_for_stack void scrub_workers_put(struct btrfs_root *root) | |||
1156 | 1158 | ||
1157 | 1159 | ||
1158 | int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end, | 1160 | int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end, |
1159 | struct btrfs_scrub_progress *progress) | 1161 | struct btrfs_scrub_progress *progress, int readonly) |
1160 | { | 1162 | { |
1161 | struct scrub_dev *sdev; | 1163 | struct scrub_dev *sdev; |
1162 | struct btrfs_fs_info *fs_info = root->fs_info; | 1164 | 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, | |||
1209 | scrub_workers_put(root); | 1211 | scrub_workers_put(root); |
1210 | return PTR_ERR(sdev); | 1212 | return PTR_ERR(sdev); |
1211 | } | 1213 | } |
1214 | sdev->readonly = readonly; | ||
1212 | dev->scrub_device = sdev; | 1215 | dev->scrub_device = sdev; |
1213 | 1216 | ||
1214 | atomic_inc(&fs_info->scrubs_running); | 1217 | atomic_inc(&fs_info->scrubs_running); |