2434 lines · 64.3 KB · C
RawDownload
/* * bitmap.c two-level bitmap (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003 * * bitmap_create  - sets up the bitmap structure * bitmap_destroy - destroys the bitmap structure * * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.: * - added disk storage for bitmap * - changes to allow various bitmap chunk sizes */ /* * Still to do: * * flush after percent set rather than just time based. (maybe both). */ #include <linux/blkdev.h>#include <linux/module.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/sched.h>#include <linux/list.h>#include <linux/file.h>#include <linux/mount.h>#include <linux/buffer_head.h>#include <linux/seq_file.h>#include "md.h"#include "bitmap.h" static inline char *bmname(struct bitmap *bitmap){	return bitmap->mddev ? mdname(bitmap->mddev) : "mdX";} /* * check a page and, if necessary, allocate it (or hijack it if the alloc fails) * * 1) check to see if this page is allocated, if it's not then try to alloc * 2) if the alloc fails, set the page's hijacked flag so we'll use the *    page pointer directly as a counter * * if we find our page, we increment the page's refcount so that it stays * allocated while we're using it */static int bitmap_checkpage(struct bitmap_counts *bitmap,			    unsigned long page, int create)__releases(bitmap->lock)__acquires(bitmap->lock){	unsigned char *mappage; 	if (page >= bitmap->pages) {		/* This can happen if bitmap_start_sync goes beyond		 * End-of-device while looking for a whole page.		 * It is harmless.		 */		return -EINVAL;	} 	if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */		return 0; 	if (bitmap->bp[page].map) /* page is already allocated, just return */		return 0; 	if (!create)		return -ENOENT; 	/* this page has not been allocated yet */ 	spin_unlock_irq(&bitmap->lock);	/* It is possible that this is being called inside a	 * prepare_to_wait/finish_wait loop from raid5c:make_request().	 * In general it is not permitted to sleep in that context as it	 * can cause the loop to spin freely.	 * That doesn't apply here as we can only reach this point	 * once with any loop.	 * When this function completes, either bp[page].map or	 * bp[page].hijacked.  In either case, this function will	 * abort before getting to this point again.  So there is	 * no risk of a free-spin, and so it is safe to assert	 * that sleeping here is allowed.	 */	sched_annotate_sleep();	mappage = kzalloc(PAGE_SIZE, GFP_NOIO);	spin_lock_irq(&bitmap->lock); 	if (mappage == NULL) {		pr_debug("md/bitmap: map page allocation failed, hijacking\n");		/* failed - set the hijacked flag so that we can use the		 * pointer as a counter */		if (!bitmap->bp[page].map)			bitmap->bp[page].hijacked = 1;	} else if (bitmap->bp[page].map ||		   bitmap->bp[page].hijacked) {		/* somebody beat us to getting the page */		kfree(mappage);		return 0;	} else { 		/* no page was in place and we have one, so install it */ 		bitmap->bp[page].map = mappage;		bitmap->missing_pages--;	}	return 0;} /* 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 void bitmap_checkfree(struct bitmap_counts *bitmap, unsigned long page){	char *ptr; 	if (bitmap->bp[page].count) /* page is still busy */		return; 	/* page is no longer in use, it can be released */ 	if (bitmap->bp[page].hijacked) { /* page was hijacked, undo this now */		bitmap->bp[page].hijacked = 0;		bitmap->bp[page].map = NULL;	} else {		/* normal case, free the page */		ptr = bitmap->bp[page].map;		bitmap->bp[page].map = NULL;		bitmap->missing_pages++;		kfree(ptr);	}} /* * bitmap file handling - read and write the bitmap file and its superblock */ /* * basic page I/O operations */ /* IO operations when bitmap is stored near all superblocks */static int read_sb_page(struct mddev *mddev, loff_t offset,			struct page *page,			unsigned long index, int size){	/* choose a good rdev and read the page from there */ 	struct md_rdev *rdev;	sector_t target; 	rdev_for_each(rdev, mddev) {		if (! test_bit(In_sync, &rdev->flags)		    || test_bit(Faulty, &rdev->flags))			continue; 		target = offset + index * (PAGE_SIZE/512); 		if (sync_page_io(rdev, target,				 roundup(size, bdev_logical_block_size(rdev->bdev)),				 page, READ, true)) {			page->index = index;			return 0;		}	}	return -EIO;} static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mddev){	/* Iterate the disks of an mddev, using rcu to protect access to the	 * linked list, and raising the refcount of devices we return to ensure	 * they don't disappear while in use.	 * As devices are only added or removed when raid_disk is < 0 and	 * nr_pending is 0 and In_sync is clear, the entries we return will	 * still be in the same position on the list when we re-enter	 * list_for_each_entry_continue_rcu.	 *	 * Note that if entered with 'rdev == NULL' to start at the	 * beginning, we temporarily assign 'rdev' to an address which	 * isn't really an rdev, but which can be used by	 * list_for_each_entry_continue_rcu() to find the first entry.	 */	rcu_read_lock();	if (rdev == NULL)		/* start at the beginning */		rdev = list_entry(&mddev->disks, struct md_rdev, same_set);	else {		/* release the previous rdev and start from there. */		rdev_dec_pending(rdev, mddev);	}	list_for_each_entry_continue_rcu(rdev, &mddev->disks, same_set) {		if (rdev->raid_disk >= 0 &&		    !test_bit(Faulty, &rdev->flags)) {			/* this is a usable devices */			atomic_inc(&rdev->nr_pending);			rcu_read_unlock();			return rdev;		}	}	rcu_read_unlock();	return NULL;} static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait){	struct md_rdev *rdev = NULL;	struct block_device *bdev;	struct mddev *mddev = bitmap->mddev;	struct bitmap_storage *store = &bitmap->storage; 	while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {		int size = PAGE_SIZE;		loff_t offset = mddev->bitmap_info.offset; 		bdev = (rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; 		if (page->index == store->file_pages-1) {			int last_page_size = store->bytes & (PAGE_SIZE-1);			if (last_page_size == 0)				last_page_size = PAGE_SIZE;			size = roundup(last_page_size,				       bdev_logical_block_size(bdev));		}		/* Just make sure we aren't corrupting data or		 * metadata		 */		if (mddev->external) {			/* Bitmap could be anywhere. */			if (rdev->sb_start + offset + (page->index						       * (PAGE_SIZE/512))			    > rdev->data_offset			    &&			    rdev->sb_start + offset			    < (rdev->data_offset + mddev->dev_sectors			     + (PAGE_SIZE/512)))				goto bad_alignment;		} else if (offset < 0) {			/* DATA  BITMAP METADATA  */			if (offset			    + (long)(page->index * (PAGE_SIZE/512))			    + size/512 > 0)				/* bitmap runs in to metadata */				goto bad_alignment;			if (rdev->data_offset + mddev->dev_sectors			    > rdev->sb_start + offset)				/* data runs in to bitmap */				goto bad_alignment;		} else if (rdev->sb_start < rdev->data_offset) {			/* METADATA BITMAP DATA */			if (rdev->sb_start			    + offset			    + page->index*(PAGE_SIZE/512) + size/512			    > rdev->data_offset)				/* bitmap runs in to data */				goto bad_alignment;		} else {			/* DATA METADATA BITMAP - no problems */		}		md_super_write(mddev, rdev,			       rdev->sb_start + offset			       + page->index * (PAGE_SIZE/512),			       size,			       page);	} 	if (wait)		md_super_wait(mddev);	return 0;  bad_alignment:	return -EINVAL;} static void bitmap_file_kick(struct bitmap *bitmap);/* * write out a page to a file */static void write_page(struct bitmap *bitmap, struct page *page, int wait){	struct buffer_head *bh; 	if (bitmap->storage.file == NULL) {		switch (write_sb_page(bitmap, page, wait)) {		case -EINVAL:			set_bit(BITMAP_WRITE_ERROR, &bitmap->flags);		}	} else { 		bh = page_buffers(page); 		while (bh && bh->b_blocknr) {			atomic_inc(&bitmap->pending_writes);			set_buffer_locked(bh);			set_buffer_mapped(bh);			submit_bh(WRITE | REQ_SYNC, bh);			bh = bh->b_this_page;		} 		if (wait)			wait_event(bitmap->write_wait,				   atomic_read(&bitmap->pending_writes)==0);	}	if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))		bitmap_file_kick(bitmap);} static void end_bitmap_write(struct buffer_head *bh, int uptodate){	struct bitmap *bitmap = bh->b_private; 	if (!uptodate)		set_bit(BITMAP_WRITE_ERROR, &bitmap->flags);	if (atomic_dec_and_test(&bitmap->pending_writes))		wake_up(&bitmap->write_wait);} /* copied from buffer.c */static void__clear_page_buffers(struct page *page){	ClearPagePrivate(page);	set_page_private(page, 0);	page_cache_release(page);}static void free_buffers(struct page *page){	struct buffer_head *bh; 	if (!PagePrivate(page))		return; 	bh = page_buffers(page);	while (bh) {		struct buffer_head *next = bh->b_this_page;		free_buffer_head(bh);		bh = next;	}	__clear_page_buffers(page);	put_page(page);} /* read a page from a file. * We both read the page, and attach buffers to the page to record the * address of each block (using bmap).  These addresses will be used * to write the block later, completely bypassing the filesystem. * This usage is similar to how swap files are handled, and allows us * to write to a file with no concerns of memory allocation failing. */static int read_page(struct file *file, unsigned long index,		     struct bitmap *bitmap,		     unsigned long count,		     struct page *page){	int ret = 0;	struct inode *inode = file_inode(file);	struct buffer_head *bh;	sector_t block; 	pr_debug("read bitmap file (%dB @ %llu)\n", (int)PAGE_SIZE,		 (unsigned long long)index << PAGE_SHIFT); 	bh = alloc_page_buffers(page, 1<<inode->i_blkbits, 0);	if (!bh) {		ret = -ENOMEM;		goto out;	}	attach_page_buffers(page, bh);	block = index << (PAGE_SHIFT - inode->i_blkbits);	while (bh) {		if (count == 0)			bh->b_blocknr = 0;		else {			bh->b_blocknr = bmap(inode, block);			if (bh->b_blocknr == 0) {				/* Cannot use this file! */				ret = -EINVAL;				goto out;			}			bh->b_bdev = inode->i_sb->s_bdev;			if (count < (1<<inode->i_blkbits))				count = 0;			else				count -= (1<<inode->i_blkbits); 			bh->b_end_io = end_bitmap_write;			bh->b_private = bitmap;			atomic_inc(&bitmap->pending_writes);			set_buffer_locked(bh);			set_buffer_mapped(bh);			submit_bh(READ, bh);		}		block++;		bh = bh->b_this_page;	}	page->index = index; 	wait_event(bitmap->write_wait,		   atomic_read(&bitmap->pending_writes)==0);	if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))		ret = -EIO;out:	if (ret)		printk(KERN_ALERT "md: bitmap read error: (%dB @ %llu): %d\n",			(int)PAGE_SIZE,			(unsigned long long)index << PAGE_SHIFT,			ret);	return ret;} /* * bitmap file superblock operations */ /* update the event counter and sync the superblock to disk */void bitmap_update_sb(struct bitmap *bitmap){	bitmap_super_t *sb; 	if (!bitmap || !bitmap->mddev) /* no bitmap for this array */		return;	if (bitmap->mddev->bitmap_info.external)		return;	if (!bitmap->storage.sb_page) /* no superblock */		return;	sb = kmap_atomic(bitmap->storage.sb_page);	sb->events = cpu_to_le64(bitmap->mddev->events);	if (bitmap->mddev->events < bitmap->events_cleared)		/* rocking back to read-only */		bitmap->events_cleared = bitmap->mddev->events;	sb->events_cleared = cpu_to_le64(bitmap->events_cleared);	sb->state = cpu_to_le32(bitmap->flags);	/* Just in case these have been changed via sysfs: */	sb->daemon_sleep = cpu_to_le32(bitmap->mddev->bitmap_info.daemon_sleep/HZ);	sb->write_behind = cpu_to_le32(bitmap->mddev->bitmap_info.max_write_behind);	/* This might have been changed by a reshape */	sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors);	sb->chunksize = cpu_to_le32(bitmap->mddev->bitmap_info.chunksize);	sb->nodes = cpu_to_le32(bitmap->mddev->bitmap_info.nodes);	sb->sectors_reserved = cpu_to_le32(bitmap->mddev->					   bitmap_info.space);	kunmap_atomic(sb);	write_page(bitmap, bitmap->storage.sb_page, 1);} /* print out the bitmap file superblock */void bitmap_print_sb(struct bitmap *bitmap){	bitmap_super_t *sb; 	if (!bitmap || !bitmap->storage.sb_page)		return;	sb = kmap_atomic(bitmap->storage.sb_page);	printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));	printk(KERN_DEBUG "         magic: %08x\n", le32_to_cpu(sb->magic));	printk(KERN_DEBUG "       version: %d\n", le32_to_cpu(sb->version));	printk(KERN_DEBUG "          uuid: %08x.%08x.%08x.%08x\n",					*(__u32 *)(sb->uuid+0),					*(__u32 *)(sb->uuid+4),					*(__u32 *)(sb->uuid+8),					*(__u32 *)(sb->uuid+12));	printk(KERN_DEBUG "        events: %llu\n",			(unsigned long long) le64_to_cpu(sb->events));	printk(KERN_DEBUG "events cleared: %llu\n",			(unsigned long long) le64_to_cpu(sb->events_cleared));	printk(KERN_DEBUG "         state: %08x\n", le32_to_cpu(sb->state));	printk(KERN_DEBUG "     chunksize: %d B\n", le32_to_cpu(sb->chunksize));	printk(KERN_DEBUG "  daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));	printk(KERN_DEBUG "     sync size: %llu KB\n",			(unsigned long long)le64_to_cpu(sb->sync_size)/2);	printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind));	kunmap_atomic(sb);} /* * bitmap_new_disk_sb * @bitmap * * This function is somewhat the reverse of bitmap_read_sb.  bitmap_read_sb * reads and verifies the on-disk bitmap superblock and populates bitmap_info. * This function verifies 'bitmap_info' and populates the on-disk bitmap * structure, which is to be written to disk. * * Returns: 0 on success, -Exxx on error */static int bitmap_new_disk_sb(struct bitmap *bitmap){	bitmap_super_t *sb;	unsigned long chunksize, daemon_sleep, write_behind; 	bitmap->storage.sb_page = alloc_page(GFP_KERNEL | __GFP_ZERO);	if (bitmap->storage.sb_page == NULL)		return -ENOMEM;	bitmap->storage.sb_page->index = 0; 	sb = kmap_atomic(bitmap->storage.sb_page); 	sb->magic = cpu_to_le32(BITMAP_MAGIC);

Lines 1–500 of 2434.