On Fri, Mar 11, 2011 at 03:49:42PM +0100, Arne Jansen wrote: > Add structures and state information needed for scrub > > Signed-off-by: Arne Jansen <sensi...@gmx.net> > --- > fs/btrfs/ctree.h | 26 ++++++++++++++++++++++++++ > fs/btrfs/disk-io.c | 15 +++++++++++++++ > fs/btrfs/ioctl.h | 17 +++++++++++++++++ > fs/btrfs/volumes.h | 3 +++ > 4 files changed, 61 insertions(+), 0 deletions(-) > > diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h > index 030c321..3584179 100644 > --- a/fs/btrfs/ctree.h > +++ b/fs/btrfs/ctree.h > @@ -23,6 +23,7 @@ > #include <linux/mm.h> > #include <linux/highmem.h> > #include <linux/fs.h> > +#include <linux/rwsem.h> > #include <linux/completion.h> > #include <linux/backing-dev.h> > #include <linux/wait.h> > @@ -32,6 +33,7 @@ > #include "extent_io.h" > #include "extent_map.h" > #include "async-thread.h" > +#include "ioctl.h" > > struct btrfs_trans_handle; > struct btrfs_transaction; > @@ -48,6 +50,8 @@ struct btrfs_ordered_sum; > > #define BTRFS_COMPAT_EXTENT_TREE_V0 > > +#define SCRUB_BTRFS_WORKER > + > /* > * files bigger than this get some pre-flushing when they are added > * to the ordered operations list. That way we limit the total > @@ -508,6 +512,12 @@ struct btrfs_extent_item_v0 { > /* use full backrefs for extent pointers in the block */ > #define BTRFS_BLOCK_FLAG_FULL_BACKREF (1ULL << 8) > > +/* > + * this flag is only used internally by scrub and may be changed at any time > + * it is only declared here to avoid collisions > + */ > +#define BTRFS_EXTENT_FLAG_SUPER (1ULL << 48) > + > struct btrfs_tree_block_info { > struct btrfs_disk_key key; > u8 level; > @@ -1067,6 +1077,22 @@ struct btrfs_fs_info { > > void *bdev_holder; > > + /* private scrub information */ > + struct mutex scrub_lock; > + struct scrub_info *scrub_info; ^^^^^^^^^^
I did not find any reference to this item > + atomic_t scrubs_running; > + atomic_t scrub_pause_req; > + atomic_t scrubs_paused; > + atomic_t scrub_cancel_req; This make me think ... you declare atomics and yet lock (nearly) every variable use like + mutex_lock(&fs_info->scrub_lock); + atomic_inc(&fs_info->scrubs_running); + mutex_unlock(&fs_info->scrub_lock); or + mutex_lock(&fs_info->scrub_lock); + if (!atomic_read(&fs_info->scrubs_running)) { + mutex_unlock(&fs_info->scrub_lock); + return -ENOTCONN; + } imho this is not needed with atomics. Moreover, the locking is not consistent, quick grep for atomic_read shows many statements without any locks around. > + wait_queue_head_t scrub_pause_wait; > + struct rw_semaphore scrub_super_lock; > + int scrub_workers_refcnt; A refcount could be an atomic too ... > +#ifdef SCRUB_BTRFS_WORKER > + struct btrfs_workers scrub_workers; > +#else > + struct workqueue_struct *scrub_workers; > +#endif > + Apart from the atomics and scrub_workers_refcnt, there is only scrub_workers left that needs locking protection, which can be done under a spinlock. dave > /* filesystem state */ > u64 fs_state; > }; > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 924a366..4d62bc3 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -1677,6 +1677,21 @@ struct btrfs_root *open_ctree(struct super_block *sb, > INIT_LIST_HEAD(&fs_info->ordered_extents); > spin_lock_init(&fs_info->ordered_extent_lock); > > + mutex_init(&fs_info->scrub_lock); > + atomic_set(&fs_info->scrubs_running, 0); > + atomic_set(&fs_info->scrub_pause_req, 0); > + atomic_set(&fs_info->scrubs_paused, 0); > + atomic_set(&fs_info->scrub_cancel_req, 0); > + init_waitqueue_head(&fs_info->scrub_pause_wait); > + init_rwsem(&fs_info->scrub_super_lock); > + fs_info->scrub_workers_refcnt = 0; > +#ifdef SCRUB_BTRFS_WORKER > + btrfs_init_workers(&fs_info->scrub_workers, "scrub", > + fs_info->thread_pool_size, &fs_info->generic_worker); > +#else > + fs_info->scrub_workers = NULL; > +#endif > + > sb->s_blocksize = 4096; > sb->s_blocksize_bits = blksize_bits(4096); > sb->s_bdi = &fs_info->bdi; > diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h > index 8fb3821..973e7c8 100644 > --- a/fs/btrfs/ioctl.h > +++ b/fs/btrfs/ioctl.h > @@ -42,6 +42,23 @@ struct btrfs_ioctl_vol_args_v2 { > char name[BTRFS_SUBVOL_NAME_MAX + 1]; > }; > > +struct btrfs_scrub_progress { > + __u64 data_extents_scrubbed; > + __u64 tree_extents_scrubbed; > + __u64 data_bytes_scrubbed; > + __u64 tree_bytes_scrubbed; > + __u64 read_errors; > + __u64 csum_errors; > + __u64 verify_errors; > + __u64 no_csum; > + __u64 csum_discards; > + __u64 super_errors; > + __u64 malloc_errors; > + __u64 uncorrectable_errors; > + __u64 corrected_errors; > + __u64 last_physical; > +}; > + > #define BTRFS_INO_LOOKUP_PATH_MAX 4080 > struct btrfs_ioctl_ino_lookup_args { > __u64 treeid; > diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h > index 0ccc982..92204d9 100644 > --- a/fs/btrfs/volumes.h > +++ b/fs/btrfs/volumes.h > @@ -86,6 +86,9 @@ struct btrfs_device { > /* physical drive uuid (or lvm uuid) */ > u8 uuid[BTRFS_UUID_SIZE]; > > + /* per-device scrub information */ > + struct scrub_dev *scrub_device; > + > struct btrfs_work work; > }; > > -- > 1.7.3.4 > > -- > 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 -- 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