btrfs: add readonly flag
setting the readonly flag prevents writes in case an error is detected Signed-off-by: Arne Jansen <sensille@gmx.net>
This commit is contained in:
@@ -2657,7 +2657,7 @@ void btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans,
|
|||||||
|
|
||||||
/* scrub.c */
|
/* scrub.c */
|
||||||
int btrfs_scrub_dev(struct btrfs_root *root, u64 devid, u64 start, u64 end,
|
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(struct btrfs_root *root);
|
||||||
int btrfs_scrub_pause_super(struct btrfs_root *root);
|
int btrfs_scrub_pause_super(struct btrfs_root *root);
|
||||||
int btrfs_scrub_continue(struct btrfs_root *root);
|
int btrfs_scrub_continue(struct btrfs_root *root);
|
||||||
|
@@ -2547,7 +2547,7 @@ static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg)
|
|||||||
return PTR_ERR(sa);
|
return PTR_ERR(sa);
|
||||||
|
|
||||||
ret = btrfs_scrub_dev(root, sa->devid, sa->start, sa->end,
|
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)))
|
if (copy_to_user(arg, sa, sizeof(*sa)))
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
|
@@ -81,6 +81,7 @@ struct btrfs_scrub_progress {
|
|||||||
* Intermittent error. */
|
* Intermittent error. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BTRFS_SCRUB_READONLY 1
|
||||||
struct btrfs_ioctl_scrub_args {
|
struct btrfs_ioctl_scrub_args {
|
||||||
__u64 devid; /* in */
|
__u64 devid; /* in */
|
||||||
__u64 start; /* in */
|
__u64 start; /* in */
|
||||||
|
@@ -42,7 +42,6 @@
|
|||||||
* - In case of a read error on files with nodatasum, map the file and read
|
* - 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
|
* the extent to trigger a writeback of the good copy
|
||||||
* - track and record media errors, throw out bad devices
|
* - track and record media errors, throw out bad devices
|
||||||
* - add a readonly mode
|
|
||||||
* - add a mode to also read unallocated space
|
* - add a mode to also read unallocated space
|
||||||
* - make the prefetch cancellable
|
* - make the prefetch cancellable
|
||||||
*/
|
*/
|
||||||
@@ -99,6 +98,7 @@ struct scrub_dev {
|
|||||||
u16 csum_size;
|
u16 csum_size;
|
||||||
struct list_head csum_list;
|
struct list_head csum_list;
|
||||||
atomic_t cancel_req;
|
atomic_t cancel_req;
|
||||||
|
int readonly;
|
||||||
/*
|
/*
|
||||||
* statistics
|
* statistics
|
||||||
*/
|
*/
|
||||||
@@ -329,14 +329,16 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix)
|
|||||||
if (i == multi->num_stripes)
|
if (i == multi->num_stripes)
|
||||||
goto uncorrectable;
|
goto uncorrectable;
|
||||||
|
|
||||||
/*
|
if (!sdev->readonly) {
|
||||||
* bi_io_vec[ix].bv_page now contains good data, write it back
|
/*
|
||||||
*/
|
* 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,
|
if (scrub_fixup_io(WRITE, sdev->dev->bdev,
|
||||||
sbio->bio->bi_io_vec[ix].bv_page)) {
|
(sbio->physical + ix * PAGE_SIZE) >> 9,
|
||||||
/* I/O-error, writeback failed, give up */
|
sbio->bio->bi_io_vec[ix].bv_page)) {
|
||||||
goto uncorrectable;
|
/* I/O-error, writeback failed, give up */
|
||||||
|
goto uncorrectable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(multi);
|
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,
|
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 scrub_dev *sdev;
|
||||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
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);
|
scrub_workers_put(root);
|
||||||
return PTR_ERR(sdev);
|
return PTR_ERR(sdev);
|
||||||
}
|
}
|
||||||
|
sdev->readonly = readonly;
|
||||||
dev->scrub_device = sdev;
|
dev->scrub_device = sdev;
|
||||||
|
|
||||||
atomic_inc(&fs_info->scrubs_running);
|
atomic_inc(&fs_info->scrubs_running);
|
||||||
|
Reference in New Issue
Block a user