aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorArne Jansen <sensille@gmx.net>2011-03-23 11:34:19 -0400
committerArne Jansen <sensille@gmx.net>2011-05-12 08:48:31 -0400
commit8628764e1a5e1998a42b9713e9edea7753653d01 (patch)
tree19c88f4d4eb806f7d5de83a1fc36996658ace17d /fs/btrfs
parent96e369208e65a7d017a52361fd572df41fde8472 (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.h2
-rw-r--r--fs/btrfs/ioctl.c2
-rw-r--r--fs/btrfs/ioctl.h1
-rw-r--r--fs/btrfs/scrub.c23
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 */
2659int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end, 2659int 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);
2661int btrfs_scrub_pause(struct btrfs_root *root); 2661int btrfs_scrub_pause(struct btrfs_root *root);
2662int btrfs_scrub_pause_super(struct btrfs_root *root); 2662int btrfs_scrub_pause_super(struct btrfs_root *root);
2663int btrfs_scrub_continue(struct btrfs_root *root); 2663int 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
84struct btrfs_ioctl_scrub_args { 85struct 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
1158int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end, 1160int 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);