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

Reply via email to