md: allow a resync that is waiting for other resync to complete, to be aborted.
[safe/jmp/linux-2.6] / drivers / md / md.h
index e78b3c1..8e4c75c 100644 (file)
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 */
 
-#ifndef _MD_K_H
-#define _MD_K_H
-
-#ifdef CONFIG_BLOCK
+#ifndef _MD_MD_H
+#define _MD_MD_H
+
+#include <linux/blkdev.h>
+#include <linux/kobject.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
 
 #define MaxSector (~(sector_t)0)
 
@@ -23,20 +30,13 @@ typedef struct mddev_s mddev_t;
 typedef struct mdk_rdev_s mdk_rdev_t;
 
 /*
- * options passed in raidrun:
- */
-
-/* Currently this must fit in an 'int' */
-#define MAX_CHUNK_SIZE (1<<30)
-
-/*
  * MD's 'extended' device
  */
 struct mdk_rdev_s
 {
        struct list_head same_set;      /* RAID devices within the same set */
 
-       sector_t size;                  /* Device size (in blocks) */
+       sector_t sectors;               /* Device size (in 512bytes sectors) */
        mddev_t *mddev;                 /* RAID array if running */
        int last_events;                /* IO event timestamp */
 
@@ -97,6 +97,9 @@ struct mdk_rdev_s
        atomic_t        read_errors;    /* number of consecutive read errors that
                                         * we have tried to ignore.
                                         */
+       struct timespec last_read_error;        /* monotonic time since our
+                                                * last read error
+                                                */
        atomic_t        corrected_errors; /* number of corrected read errors,
                                           * for reporting to userspace and storing
                                           * in superblock.
@@ -119,6 +122,8 @@ struct mddev_s
 #define MD_CHANGE_CLEAN 1      /* transition to or from 'clean' */
 #define MD_CHANGE_PENDING 2    /* superblock update in progress */
 
+       int                             suspended;
+       atomic_t                        active_io;
        int                             ro;
 
        struct gendisk                  *gendisk;
@@ -136,14 +141,17 @@ struct mddev_s
        int                             external;       /* metadata is
                                                         * managed externally */
        char                            metadata_type[17]; /* externally set*/
-       int                             chunk_size;
+       int                             chunk_sectors;
        time_t                          ctime, utime;
        int                             level, layout;
        char                            clevel[16];
        int                             raid_disks;
        int                             max_disks;
-       sector_t                        size; /* used size of component devices */
+       sector_t                        dev_sectors;    /* used size of
+                                                        * component devices */
        sector_t                        array_sectors; /* exported array size */
+       int                             external_size; /* size managed
+                                                       * externally */
        __u64                           events;
 
        char                            uuid[16];
@@ -154,11 +162,19 @@ struct mddev_s
         * If reshape_position is MaxSector, then no reshape is happening (yet).
         */
        sector_t                        reshape_position;
-       int                             delta_disks, new_level, new_layout, new_chunk;
+       int                             delta_disks, new_level, new_layout;
+       int                             new_chunk_sectors;
 
        struct mdk_thread_s             *thread;        /* management thread */
        struct mdk_thread_s             *sync_thread;   /* doing resync or reconstruct */
        sector_t                        curr_resync;    /* last block scheduled */
+       /* As resync requests can complete out of order, we cannot easily track
+        * how much resync has been completed.  So we occasionally pause until
+        * everything completes, then set curr_resync_completed to curr_resync.
+        * As such it may be well behind the real resync mark, but it is a value
+        * we are certain of.
+        */
+       sector_t                        curr_resync_completed;
        unsigned long                   resync_mark;    /* a recent timestamp */
        sector_t                        resync_mark_cnt;/* blocks written at resync_mark */
        sector_t                        curr_mark_cnt; /* blocks scheduled now */
@@ -188,7 +204,7 @@ struct mddev_s
         * INTR:     resync needs to be aborted for some reason
         * DONE:     thread is done and is waiting to be reaped
         * REQUEST:  user-space has requested a sync (used with SYNC)
-        * CHECK:    user-space request for for check-only, no repair
+        * CHECK:    user-space request for check-only, no repair
         * RESHAPE:  A reshape is happening
         *
         * If neither SYNC or RESHAPE are set, then it is a recovery.
@@ -210,6 +226,16 @@ struct mddev_s
                                                            * so we don't loop trying */
 
        int                             in_sync;        /* know to not need resync */
+       /* 'open_mutex' avoids races between 'md_open' and 'do_md_stop', so
+        * that we are never stopping an array while it is open.
+        * 'reconfig_mutex' protects all other reconfiguration.
+        * These locks are separate due to conflicting interactions
+        * with bdev->bd_mutex.
+        * Lock ordering is:
+        *  reconfig_mutex -> bd_mutex : e.g. do_md_run -> revalidate_disk
+        *  bd_mutex -> open_mutex:  e.g. __blkdev_get -> md_open
+        */
+       struct mutex                    open_mutex;
        struct mutex                    reconfig_mutex;
        atomic_t                        active;         /* general refcount */
        atomic_t                        openers;        /* number of active opens */
@@ -257,17 +283,38 @@ struct mddev_s
        unsigned int                    max_write_behind; /* 0 = sync */
 
        struct bitmap                   *bitmap; /* the bitmap for the device */
-       struct file                     *bitmap_file; /* the bitmap file */
-       long                            bitmap_offset; /* offset from superblock of
-                                                       * start of bitmap. May be
-                                                       * negative, but not '0'
-                                                       */
-       long                            default_bitmap_offset; /* this is the offset to use when
-                                                               * hot-adding a bitmap.  It should
-                                                               * eventually be settable by sysfs.
-                                                               */
-
+       struct {
+               struct file             *file; /* the bitmap file */
+               loff_t                  offset; /* offset from superblock of
+                                                * start of bitmap. May be
+                                                * negative, but not '0'
+                                                * For external metadata, offset
+                                                * from start of device. 
+                                                */
+               loff_t                  default_offset; /* this is the offset to use when
+                                                        * hot-adding a bitmap.  It should
+                                                        * eventually be settable by sysfs.
+                                                        */
+               struct mutex            mutex;
+               unsigned long           chunksize;
+               unsigned long           daemon_sleep; /* how many seconds between updates? */
+               unsigned long           max_write_behind; /* write-behind mode */
+               int                     external;
+       } bitmap_info;
+
+       atomic_t                        max_corr_read_errors; /* max read retries */
        struct list_head                all_mddevs;
+
+       /* Generic barrier handling.
+        * If there is a pending barrier request, all other
+        * writes are blocked while the devices are flushed.
+        * The last to finish a flush schedules a worker to
+        * submit the barrier request (without the barrier flag),
+        * then submit more flush requests.
+        */
+       struct bio *barrier;
+       atomic_t flush_pending;
+       struct work_struct barrier_work;
 };
 
 
@@ -302,15 +349,26 @@ struct mdk_personality
        int (*spare_active) (mddev_t *mddev);
        sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
        int (*resize) (mddev_t *mddev, sector_t sectors);
+       sector_t (*size) (mddev_t *mddev, sector_t sectors, int raid_disks);
        int (*check_reshape) (mddev_t *mddev);
        int (*start_reshape) (mddev_t *mddev);
-       int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
+       void (*finish_reshape) (mddev_t *mddev);
        /* quiesce moves between quiescence states
         * 0 - fully active
         * 1 - no new requests allowed
         * others - reserved
         */
        void (*quiesce) (mddev_t *mddev, int state);
+       /* takeover is used to transition an array from one
+        * personality to another.  The new personality must be able
+        * to handle the data in the current layout.
+        * e.g. 2drive raid1 -> 2drive raid5
+        *      ndrive raid5 -> degraded n+1drive raid6 with special layout
+        * If the takeover succeeds, a new 'private' structure is returned.
+        * This needs to be installed and then ->run used to activate the
+        * array.
+        */
+       void *(*takeover) (mddev_t *mddev);
 };
 
 
@@ -319,7 +377,7 @@ struct md_sysfs_entry {
        ssize_t (*show)(mddev_t *, char *);
        ssize_t (*store)(mddev_t *, const char *, size_t);
 };
-
+extern struct attribute_group md_bitmap_group;
 
 static inline char * mdname (mddev_t * mddev)
 {
@@ -384,10 +442,6 @@ static inline void safe_put_page(struct page *p)
        if (p) put_page(p);
 }
 
-#endif /* CONFIG_BLOCK */
-#endif
-
-
 extern int register_md_personality(struct mdk_personality *p);
 extern int unregister_md_personality(struct mdk_personality *p);
 extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev),
@@ -400,6 +454,8 @@ extern void md_write_end(mddev_t *mddev);
 extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
 extern void md_error(mddev_t *mddev, mdk_rdev_t *rdev);
 
+extern int mddev_congested(mddev_t *mddev, int bits);
+extern void md_barrier_request(mddev_t *mddev, struct bio *bio);
 extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
                           sector_t sector, int size, struct page *page);
 extern void md_super_wait(mddev_t *mddev);
@@ -409,3 +465,11 @@ extern void md_do_sync(mddev_t *mddev);
 extern void md_new_event(mddev_t *mddev);
 extern int md_allow_write(mddev_t *mddev);
 extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
+extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
+extern int md_check_no_bitmap(mddev_t *mddev);
+extern int md_integrity_register(mddev_t *mddev);
+extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
+extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
+extern void restore_bitmap_write_access(struct file *file);
+
+#endif /* _MD_MD_H */