diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/bitmap.c | 2 | ||||
-rw-r--r-- | drivers/md/dm-crypt.c | 2 | ||||
-rw-r--r-- | drivers/md/dm-ioctl.c | 18 | ||||
-rw-r--r-- | drivers/md/dm-log.c | 45 | ||||
-rw-r--r-- | drivers/md/dm-snap.c | 31 | ||||
-rw-r--r-- | drivers/md/dm-snap.h | 4 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 2 | ||||
-rw-r--r-- | drivers/md/dm.c | 41 | ||||
-rw-r--r-- | drivers/md/kcopyd.c | 1 | ||||
-rw-r--r-- | drivers/md/md.c | 1 | ||||
-rw-r--r-- | drivers/md/raid1.c | 4 | ||||
-rw-r--r-- | drivers/md/raid10.c | 4 | ||||
-rw-r--r-- | drivers/md/raid5.c | 10 | ||||
-rw-r--r-- | drivers/md/raid6main.c | 8 |
14 files changed, 95 insertions, 78 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 76a189ceb52..eae4473eadd 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -200,7 +200,7 @@ out: /* if page is completely empty, put it back on the free list, or dealloc it */ /* if page was hijacked, unmark the flag so it might get alloced next time */ /* Note: lock should be held when calling this */ -static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) +static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) { char *ptr; diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index a601a427885..e7a650f9ca0 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -228,7 +228,7 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = { }; -static inline int +static int crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, struct scatterlist *in, unsigned int length, int write, sector_t sector) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 561bda5011e..442e2be6052 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -598,7 +598,7 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) /* * Always use UUID for lookups if it's present, otherwise use name or dev. */ -static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) +static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) { if (*param->uuid) return __get_uuid_cell(param->uuid); @@ -608,7 +608,7 @@ static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) return dm_get_mdptr(huge_decode_dev(param->dev)); } -static inline struct mapped_device *find_device(struct dm_ioctl *param) +static struct mapped_device *find_device(struct dm_ioctl *param) { struct hash_cell *hc; struct mapped_device *md = NULL; @@ -1359,16 +1359,11 @@ static int ctl_ioctl(struct inode *inode, struct file *file, * Copy the parameters into kernel space. */ r = copy_params(user, ¶m); - if (r) { - current->flags &= ~PF_MEMALLOC; - return r; - } - /* - * FIXME: eventually we will remove the PF_MEMALLOC flag - * here. However the tools still do nasty things like - * 'load' while a device is suspended. - */ + current->flags &= ~PF_MEMALLOC; + + if (r) + return r; r = validate_params(cmd, param); if (r) @@ -1386,7 +1381,6 @@ static int ctl_ioctl(struct inode *inode, struct file *file, out: free_params(param); - current->flags &= ~PF_MEMALLOC; return r; } diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index efe4adf7853..74039db846b 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -112,7 +112,7 @@ void dm_destroy_dirty_log(struct dirty_log *log) /* * The on-disk version of the metadata. */ -#define MIRROR_DISK_VERSION 1 +#define MIRROR_DISK_VERSION 2 #define LOG_OFFSET 2 struct log_header { @@ -157,7 +157,6 @@ struct log_c { struct log_header *disk_header; struct io_region bits_location; - uint32_t *disk_bits; }; /* @@ -166,20 +165,20 @@ struct log_c { */ static inline int log_test_bit(uint32_t *bs, unsigned bit) { - return test_bit(bit, (unsigned long *) bs) ? 1 : 0; + return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0; } static inline void log_set_bit(struct log_c *l, uint32_t *bs, unsigned bit) { - set_bit(bit, (unsigned long *) bs); + ext2_set_bit(bit, (unsigned long *) bs); l->touched = 1; } static inline void log_clear_bit(struct log_c *l, uint32_t *bs, unsigned bit) { - clear_bit(bit, (unsigned long *) bs); + ext2_clear_bit(bit, (unsigned long *) bs); l->touched = 1; } @@ -219,6 +218,11 @@ static int read_header(struct log_c *log) log->header.nr_regions = 0; } +#ifdef __LITTLE_ENDIAN + if (log->header.version == 1) + log->header.version = 2; +#endif + if (log->header.version != MIRROR_DISK_VERSION) { DMWARN("incompatible disk log version"); return -EINVAL; @@ -239,45 +243,24 @@ static inline int write_header(struct log_c *log) /*---------------------------------------------------------------- * Bits IO *--------------------------------------------------------------*/ -static inline void bits_to_core(uint32_t *core, uint32_t *disk, unsigned count) -{ - unsigned i; - - for (i = 0; i < count; i++) - core[i] = le32_to_cpu(disk[i]); -} - -static inline void bits_to_disk(uint32_t *core, uint32_t *disk, unsigned count) -{ - unsigned i; - - /* copy across the clean/dirty bitset */ - for (i = 0; i < count; i++) - disk[i] = cpu_to_le32(core[i]); -} - static int read_bits(struct log_c *log) { int r; unsigned long ebits; r = dm_io_sync_vm(1, &log->bits_location, READ, - log->disk_bits, &ebits); + log->clean_bits, &ebits); if (r) return r; - bits_to_core(log->clean_bits, log->disk_bits, - log->bitset_uint32_count); return 0; } static int write_bits(struct log_c *log) { unsigned long ebits; - bits_to_disk(log->clean_bits, log->disk_bits, - log->bitset_uint32_count); return dm_io_sync_vm(1, &log->bits_location, WRITE, - log->disk_bits, &ebits); + log->clean_bits, &ebits); } /*---------------------------------------------------------------- @@ -433,11 +416,6 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti, size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t), 1 << SECTOR_SHIFT); lc->bits_location.count = size >> SECTOR_SHIFT; - lc->disk_bits = vmalloc(size); - if (!lc->disk_bits) { - vfree(lc->disk_header); - goto bad; - } return 0; bad: @@ -451,7 +429,6 @@ static void disk_dtr(struct dirty_log *log) struct log_c *lc = (struct log_c *) log->context; dm_put_device(lc->ti, lc->log_dev); vfree(lc->disk_header); - vfree(lc->disk_bits); core_dtr(log); } diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 4b9dd8fb1e5..f3759dd7828 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -373,16 +373,11 @@ static inline ulong round_up(ulong n, ulong size) static void read_snapshot_metadata(struct dm_snapshot *s) { - if (s->have_metadata) - return; - if (s->store.read_metadata(&s->store)) { down_write(&s->lock); s->valid = 0; up_write(&s->lock); } - - s->have_metadata = 1; } /* @@ -471,7 +466,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) s->chunk_shift = ffs(chunk_size) - 1; s->valid = 1; - s->have_metadata = 0; + s->active = 0; s->last_percent = 0; init_rwsem(&s->lock); s->table = ti->table; @@ -506,7 +501,11 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad5; } + /* Metadata must only be loaded into one table at once */ + read_snapshot_metadata(s); + /* Add snapshot to the list of snapshots for this origin */ + /* Exceptions aren't triggered till snapshot_resume() is called */ if (register_snapshot(s)) { r = -EINVAL; ti->error = "Cannot register snapshot origin"; @@ -691,7 +690,7 @@ static void copy_callback(int read_err, unsigned int write_err, void *context) /* * Dispatches the copy operation to kcopyd. */ -static inline void start_copy(struct pending_exception *pe) +static void start_copy(struct pending_exception *pe) { struct dm_snapshot *s = pe->snap; struct io_region src, dest; @@ -793,6 +792,9 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, if (!s->valid) return -EIO; + if (unlikely(bio_barrier(bio))) + return -EOPNOTSUPP; + /* * Write to snapshot - higher level takes care of RW/RO * flags so we should only get this if we are @@ -862,7 +864,9 @@ static void snapshot_resume(struct dm_target *ti) { struct dm_snapshot *s = (struct dm_snapshot *) ti->private; - read_snapshot_metadata(s); + down_write(&s->lock); + s->active = 1; + up_write(&s->lock); } static int snapshot_status(struct dm_target *ti, status_type_t type, @@ -932,8 +936,8 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) /* Do all the snapshots on this origin */ list_for_each_entry (snap, snapshots, list) { - /* Only deal with valid snapshots */ - if (!snap->valid) + /* Only deal with valid and active snapshots */ + if (!snap->valid || !snap->active) continue; /* Nothing to do if writing beyond end of snapshot */ @@ -1057,6 +1061,9 @@ static int origin_map(struct dm_target *ti, struct bio *bio, struct dm_dev *dev = (struct dm_dev *) ti->private; bio->bi_bdev = dev->bdev; + if (unlikely(bio_barrier(bio))) + return -EOPNOTSUPP; + /* Only tell snapshots if this is a write */ return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; } @@ -1104,7 +1111,7 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result, static struct target_type origin_target = { .name = "snapshot-origin", - .version = {1, 0, 1}, + .version = {1, 1, 0}, .module = THIS_MODULE, .ctr = origin_ctr, .dtr = origin_dtr, @@ -1115,7 +1122,7 @@ static struct target_type origin_target = { static struct target_type snapshot_target = { .name = "snapshot", - .version = {1, 0, 1}, + .version = {1, 1, 0}, .module = THIS_MODULE, .ctr = snapshot_ctr, .dtr = snapshot_dtr, diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h index 375aa24d4d7..fdec1e2dc87 100644 --- a/drivers/md/dm-snap.h +++ b/drivers/md/dm-snap.h @@ -99,7 +99,9 @@ struct dm_snapshot { /* You can't use a snapshot if this is 0 (e.g. if full) */ int valid; - int have_metadata; + + /* Origin writes don't trigger exceptions until this is set */ + int active; /* Used for display of table */ char type; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index a6f2dc66c3d..9b1e2f5ca63 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -508,7 +508,7 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start, if (q->merge_bvec_fn) rs->max_sectors = min_not_zero(rs->max_sectors, - (unsigned short)(PAGE_SIZE >> 9)); + (unsigned int) (PAGE_SIZE >> 9)); rs->max_phys_segments = min_not_zero(rs->max_phys_segments, diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 097d1e54009..e9adeb9d172 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -31,6 +31,7 @@ struct dm_io { int error; struct bio *bio; atomic_t io_count; + unsigned long start_time; }; /* @@ -244,6 +245,36 @@ static inline void free_tio(struct mapped_device *md, struct target_io *tio) mempool_free(tio, md->tio_pool); } +static void start_io_acct(struct dm_io *io) +{ + struct mapped_device *md = io->md; + + io->start_time = jiffies; + + preempt_disable(); + disk_round_stats(dm_disk(md)); + preempt_enable(); + dm_disk(md)->in_flight = atomic_inc_return(&md->pending); +} + +static int end_io_acct(struct dm_io *io) +{ + struct mapped_device *md = io->md; + struct bio *bio = io->bio; + unsigned long duration = jiffies - io->start_time; + int pending; + int rw = bio_data_dir(bio); + + preempt_disable(); + disk_round_stats(dm_disk(md)); + preempt_enable(); + dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); + + disk_stat_add(dm_disk(md), ticks[rw], duration); + + return !pending; +} + /* * Add the bio to the list of deferred io. */ @@ -293,13 +324,13 @@ struct dm_table *dm_get_table(struct mapped_device *md) * Decrements the number of outstanding ios that a bio has been * cloned into, completing the original io if necc. */ -static inline void dec_pending(struct dm_io *io, int error) +static void dec_pending(struct dm_io *io, int error) { if (error) io->error = error; if (atomic_dec_and_test(&io->io_count)) { - if (atomic_dec_and_test(&io->md->pending)) + if (end_io_acct(io)) /* nudge anyone waiting on suspend queue */ wake_up(&io->md->wait); @@ -554,7 +585,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) ci.sector_count = bio_sectors(bio); ci.idx = bio->bi_idx; - atomic_inc(&md->pending); + start_io_acct(ci.io); while (ci.sector_count) __clone_and_map(&ci); @@ -573,10 +604,14 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) static int dm_request(request_queue_t *q, struct bio *bio) { int r; + int rw = bio_data_dir(bio); struct mapped_device *md = q->queuedata; down_read(&md->io_lock); + disk_stat_inc(dm_disk(md), ios[rw]); + disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio)); + /* * If we're suspended we have to queue * this io for later. diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index ca99979c868..8b3515f394a 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -8,6 +8,7 @@ * completion notification. */ +#include <asm/types.h> #include <asm/atomic.h> #include <linux/blkdev.h> diff --git a/drivers/md/md.c b/drivers/md/md.c index 1778104e106..7145cd150f7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3395,6 +3395,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) mddev->ctime = get_seconds(); mddev->level = info->level; + mddev->clevel[0] = 0; mddev->size = info->size; mddev->raid_disks = info->raid_disks; /* don't set md_minor, it is determined by which /dev/md* was diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a06ff91f27e..d39f584cd8b 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio) } } -static inline void free_r1bio(r1bio_t *r1_bio) +static void free_r1bio(r1bio_t *r1_bio) { conf_t *conf = mddev_to_conf(r1_bio->mddev); @@ -190,7 +190,7 @@ static inline void free_r1bio(r1bio_t *r1_bio) mempool_free(r1_bio, conf->r1bio_pool); } -static inline void put_buf(r1bio_t *r1_bio) +static void put_buf(r1bio_t *r1_bio) { conf_t *conf = mddev_to_conf(r1_bio->mddev); int i; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 9e658e519a2..9130d051b47 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio) } } -static inline void free_r10bio(r10bio_t *r10_bio) +static void free_r10bio(r10bio_t *r10_bio) { conf_t *conf = mddev_to_conf(r10_bio->mddev); @@ -190,7 +190,7 @@ static inline void free_r10bio(r10bio_t *r10_bio) mempool_free(r10_bio, conf->r10bio_pool); } -static inline void put_buf(r10bio_t *r10_bio) +static void put_buf(r10bio_t *r10_bio) { conf_t *conf = mddev_to_conf(r10_bio->mddev); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 54f4a9847e3..25976bfb6f9 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -69,7 +69,7 @@ static void print_raid5_conf (raid5_conf_t *conf); -static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) +static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) { if (atomic_dec_and_test(&sh->count)) { if (!list_empty(&sh->lru)) @@ -118,7 +118,7 @@ static inline void remove_hash(struct stripe_head *sh) hlist_del_init(&sh->hash); } -static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) +static void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) { struct hlist_head *hp = stripe_hash(conf, sh->sector); @@ -178,7 +178,7 @@ static int grow_buffers(struct stripe_head *sh, int num) static void raid5_build_block (struct stripe_head *sh, int i); -static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) +static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) { raid5_conf_t *conf = sh->raid_conf; int disks = conf->raid_disks, i; @@ -1415,7 +1415,7 @@ static void handle_stripe(struct stripe_head *sh) } } -static inline void raid5_activate_delayed(raid5_conf_t *conf) +static void raid5_activate_delayed(raid5_conf_t *conf) { if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { while (!list_empty(&conf->delayed_list)) { @@ -1431,7 +1431,7 @@ static inline void raid5_activate_delayed(raid5_conf_t *conf) } } -static inline void activate_bit_delay(raid5_conf_t *conf) +static void activate_bit_delay(raid5_conf_t *conf) { /* device_lock is held */ struct list_head head; diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index 8c823d686a6..f618a53b98b 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -88,7 +88,7 @@ static inline int raid6_next_disk(int disk, int raid_disks) static void print_raid6_conf (raid6_conf_t *conf); -static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) +static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) { if (atomic_dec_and_test(&sh->count)) { if (!list_empty(&sh->lru)) @@ -197,7 +197,7 @@ static int grow_buffers(struct stripe_head *sh, int num) static void raid6_build_block (struct stripe_head *sh, int i); -static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) +static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) { raid6_conf_t *conf = sh->raid_conf; int disks = conf->raid_disks, i; @@ -1577,7 +1577,7 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) } } -static inline void raid6_activate_delayed(raid6_conf_t *conf) +static void raid6_activate_delayed(raid6_conf_t *conf) { if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { while (!list_empty(&conf->delayed_list)) { @@ -1593,7 +1593,7 @@ static inline void raid6_activate_delayed(raid6_conf_t *conf) } } -static inline void activate_bit_delay(raid6_conf_t *conf) +static void activate_bit_delay(raid6_conf_t *conf) { /* device_lock is held */ struct list_head head; |