diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2011-05-14 12:06:36 +0200 | 
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2011-05-14 12:06:36 +0200 | 
| commit | a18f22a968de17b29f2310cdb7ba69163e65ec15 (patch) | |
| tree | a7d56d88fad5e444d7661484109758a2f436129e /fs/xfs | |
| parent | a1c57e0fec53defe745e64417eacdbd3618c3e66 (diff) | |
| parent | 798778b8653f64b7b2162ac70eca10367cff6ce8 (diff) | |
Merge branch 'consolidate-clksrc-i8253' of master.kernel.org:~rmk/linux-2.6-arm into timers/clocksource
Conflicts:
	arch/ia64/kernel/cyclone.c
	arch/mips/kernel/i8253.c
	arch/x86/kernel/i8253.c
Reason: Resolve conflicts so further cleanups do not conflict further
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/xfs')
59 files changed, 1659 insertions, 1907 deletions
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index faca44997099..284a7c89697e 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -16,14 +16,11 @@  # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  # -EXTRA_CFLAGS +=	 -I$(src) -I$(src)/linux-2.6 +ccflags-y := -I$(src) -I$(src)/linux-2.6 +ccflags-$(CONFIG_XFS_DEBUG) += -g  XFS_LINUX := linux-2.6 -ifeq ($(CONFIG_XFS_DEBUG),y) -	EXTRA_CFLAGS += -g -endif -  obj-$(CONFIG_XFS_FS)		+= xfs.o  xfs-y				+= linux-2.6/xfs_trace.o @@ -105,11 +102,10 @@ xfs-y				+= $(addprefix $(XFS_LINUX)/, \  				   xfs_globals.o \  				   xfs_ioctl.o \  				   xfs_iops.o \ +				   xfs_message.o \  				   xfs_super.o \  				   xfs_sync.o \  				   xfs_xattr.o)  # Objects in support/ -xfs-y				+= $(addprefix support/, \ -				   debug.o \ -				   uuid.o) +xfs-y				+= support/uuid.o diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index 666c9db48eb6..a907de565db3 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c @@ -23,6 +23,7 @@  #include <linux/backing-dev.h>  #include "time.h"  #include "kmem.h" +#include "xfs_message.h"  /*   * Greedy allocation.  May fail and may return vmalloced memory. @@ -56,8 +57,8 @@ kmem_alloc(size_t size, unsigned int __nocast flags)  		if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))  			return ptr;  		if (!(++retries % 100)) -			printk(KERN_ERR "XFS: possible memory allocation " -					"deadlock in %s (mode:0x%x)\n", +			xfs_err(NULL, +		"possible memory allocation deadlock in %s (mode:0x%x)",  					__func__, lflags);  		congestion_wait(BLK_RW_ASYNC, HZ/50);  	} while (1); @@ -112,8 +113,8 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)  		if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))  			return ptr;  		if (!(++retries % 100)) -			printk(KERN_ERR "XFS: possible memory allocation " -					"deadlock in %s (mode:0x%x)\n", +			xfs_err(NULL, +		"possible memory allocation deadlock in %s (mode:0x%x)",  					__func__, lflags);  		congestion_wait(BLK_RW_ASYNC, HZ/50);  	} while (1); diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index ec7bbb5645b6..79ce38be15a1 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -413,8 +413,7 @@ xfs_submit_ioend_bio(  	if (xfs_ioend_new_eof(ioend))  		xfs_mark_inode_dirty(XFS_I(ioend->io_inode)); -	submit_bio(wbc->sync_mode == WB_SYNC_ALL ? -		   WRITE_SYNC_PLUG : WRITE, bio); +	submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, bio);  }  STATIC struct bio * @@ -854,7 +853,7 @@ xfs_aops_discard_page(  	if (XFS_FORCED_SHUTDOWN(ip->i_mount))  		goto out_invalidate; -	xfs_fs_cmn_err(CE_ALERT, ip->i_mount, +	xfs_alert(ip->i_mount,  		"page discard on page %p, inode 0x%llx, offset %llu.",  			page, ip->i_ino, offset); @@ -872,7 +871,7 @@ xfs_aops_discard_page(  		if (error) {  			/* something screwed, just bail */  			if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { -				xfs_fs_cmn_err(CE_ALERT, ip->i_mount, +				xfs_alert(ip->i_mount,  			"page discard unable to remove delalloc mapping.");  			}  			break; @@ -1296,7 +1295,7 @@ xfs_get_blocks_direct(   * If the private argument is non-NULL __xfs_get_blocks signals us that we   * need to issue a transaction to convert the range from unwritten to written   * extents.  In case this is regular synchronous I/O we just call xfs_end_io - * to do this and we are done.  But in case this was a successfull AIO + * to do this and we are done.  But in case this was a successful AIO   * request this handler is called from interrupt context, from which we   * can't start transactions.  In that case offload the I/O completion to   * the workqueues we also use for buffered I/O completion. @@ -1411,7 +1410,7 @@ xfs_vm_write_failed(  		if (error) {  			/* something screwed, just bail */  			if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { -				xfs_fs_cmn_err(CE_ALERT, ip->i_mount, +				xfs_alert(ip->i_mount,  			"xfs_vm_write_failed: unable to clean up ino %lld",  						ip->i_ino);  			} @@ -1495,7 +1494,6 @@ const struct address_space_operations xfs_address_space_operations = {  	.readpages		= xfs_vm_readpages,  	.writepage		= xfs_vm_writepage,  	.writepages		= xfs_vm_writepages, -	.sync_page		= block_sync_page,  	.releasepage		= xfs_vm_releasepage,  	.invalidatepage		= xfs_vm_invalidatepage,  	.write_begin		= xfs_vm_write_begin, diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index ac1c7e8378dd..9ef9ed2cfe2e 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -94,75 +94,6 @@ xfs_buf_vmap_len(  }  /* - *	Page Region interfaces. - * - *	For pages in filesystems where the blocksize is smaller than the - *	pagesize, we use the page->private field (long) to hold a bitmap - * 	of uptodate regions within the page. - * - *	Each such region is "bytes per page / bits per long" bytes long. - * - *	NBPPR == number-of-bytes-per-page-region - *	BTOPR == bytes-to-page-region (rounded up) - *	BTOPRT == bytes-to-page-region-truncated (rounded down) - */ -#if (BITS_PER_LONG == 32) -#define PRSHIFT		(PAGE_CACHE_SHIFT - 5)	/* (32 == 1<<5) */ -#elif (BITS_PER_LONG == 64) -#define PRSHIFT		(PAGE_CACHE_SHIFT - 6)	/* (64 == 1<<6) */ -#else -#error BITS_PER_LONG must be 32 or 64 -#endif -#define NBPPR		(PAGE_CACHE_SIZE/BITS_PER_LONG) -#define BTOPR(b)	(((unsigned int)(b) + (NBPPR - 1)) >> PRSHIFT) -#define BTOPRT(b)	(((unsigned int)(b) >> PRSHIFT)) - -STATIC unsigned long -page_region_mask( -	size_t		offset, -	size_t		length) -{ -	unsigned long	mask; -	int		first, final; - -	first = BTOPR(offset); -	final = BTOPRT(offset + length - 1); -	first = min(first, final); - -	mask = ~0UL; -	mask <<= BITS_PER_LONG - (final - first); -	mask >>= BITS_PER_LONG - (final); - -	ASSERT(offset + length <= PAGE_CACHE_SIZE); -	ASSERT((final - first) < BITS_PER_LONG && (final - first) >= 0); - -	return mask; -} - -STATIC void -set_page_region( -	struct page	*page, -	size_t		offset, -	size_t		length) -{ -	set_page_private(page, -		page_private(page) | page_region_mask(offset, length)); -	if (page_private(page) == ~0UL) -		SetPageUptodate(page); -} - -STATIC int -test_page_region( -	struct page	*page, -	size_t		offset, -	size_t		length) -{ -	unsigned long	mask = page_region_mask(offset, length); - -	return (mask && (page_private(page) & mask) == mask); -} - -/*   * xfs_buf_lru_add - add a buffer to the LRU.   *   * The LRU takes a new reference to the buffer so that it will only be freed @@ -189,7 +120,7 @@ xfs_buf_lru_add(   * The unlocked check is safe here because it only occurs when there are not   * b_lru_ref counts left on the inode under the pag->pag_buf_lock. it is there   * to optimise the shrinker removing the buffer from the LRU and calling - * xfs_buf_free(). i.e. it removes an unneccessary round trip on the + * xfs_buf_free(). i.e. it removes an unnecessary round trip on the   * bt_lru_lock.   */  STATIC void @@ -332,7 +263,7 @@ xfs_buf_free(  	ASSERT(list_empty(&bp->b_lru)); -	if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) { +	if (bp->b_flags & _XBF_PAGES) {  		uint		i;  		if (xfs_buf_is_vmapped(bp)) @@ -342,56 +273,77 @@ xfs_buf_free(  		for (i = 0; i < bp->b_page_count; i++) {  			struct page	*page = bp->b_pages[i]; -			if (bp->b_flags & _XBF_PAGE_CACHE) -				ASSERT(!PagePrivate(page)); -			page_cache_release(page); +			__free_page(page);  		} -	} +	} else if (bp->b_flags & _XBF_KMEM) +		kmem_free(bp->b_addr);  	_xfs_buf_free_pages(bp);  	xfs_buf_deallocate(bp);  }  /* - *	Finds all pages for buffer in question and builds it's page list. + * Allocates all the pages for buffer in question and builds it's page list.   */  STATIC int -_xfs_buf_lookup_pages( +xfs_buf_allocate_memory(  	xfs_buf_t		*bp,  	uint			flags)  { -	struct address_space	*mapping = bp->b_target->bt_mapping; -	size_t			blocksize = bp->b_target->bt_bsize;  	size_t			size = bp->b_count_desired;  	size_t			nbytes, offset;  	gfp_t			gfp_mask = xb_to_gfp(flags);  	unsigned short		page_count, i; -	pgoff_t			first;  	xfs_off_t		end;  	int			error; +	/* +	 * for buffers that are contained within a single page, just allocate +	 * the memory from the heap - there's no need for the complexity of +	 * page arrays to keep allocation down to order 0. +	 */ +	if (bp->b_buffer_length < PAGE_SIZE) { +		bp->b_addr = kmem_alloc(bp->b_buffer_length, xb_to_km(flags)); +		if (!bp->b_addr) { +			/* low memory - use alloc_page loop instead */ +			goto use_alloc_page; +		} + +		if (((unsigned long)(bp->b_addr + bp->b_buffer_length - 1) & +								PAGE_MASK) != +		    ((unsigned long)bp->b_addr & PAGE_MASK)) { +			/* b_addr spans two pages - use alloc_page instead */ +			kmem_free(bp->b_addr); +			bp->b_addr = NULL; +			goto use_alloc_page; +		} +		bp->b_offset = offset_in_page(bp->b_addr); +		bp->b_pages = bp->b_page_array; +		bp->b_pages[0] = virt_to_page(bp->b_addr); +		bp->b_page_count = 1; +		bp->b_flags |= XBF_MAPPED | _XBF_KMEM; +		return 0; +	} + +use_alloc_page:  	end = bp->b_file_offset + bp->b_buffer_length;  	page_count = xfs_buf_btoc(end) - xfs_buf_btoct(bp->b_file_offset); -  	error = _xfs_buf_get_pages(bp, page_count, flags);  	if (unlikely(error))  		return error; -	bp->b_flags |= _XBF_PAGE_CACHE;  	offset = bp->b_offset; -	first = bp->b_file_offset >> PAGE_CACHE_SHIFT; +	bp->b_flags |= _XBF_PAGES;  	for (i = 0; i < bp->b_page_count; i++) {  		struct page	*page;  		uint		retries = 0; - -	      retry: -		page = find_or_create_page(mapping, first + i, gfp_mask); +retry: +		page = alloc_page(gfp_mask);  		if (unlikely(page == NULL)) {  			if (flags & XBF_READ_AHEAD) {  				bp->b_page_count = i; -				for (i = 0; i < bp->b_page_count; i++) -					unlock_page(bp->b_pages[i]); -				return -ENOMEM; +				error = ENOMEM; +				goto out_free_pages;  			}  			/* @@ -401,9 +353,8 @@ _xfs_buf_lookup_pages(  			 * handle buffer allocation failures we can't do much.  			 */  			if (!(++retries % 100)) -				printk(KERN_ERR -					"XFS: possible memory allocation " -					"deadlock in %s (mode:0x%x)\n", +				xfs_err(NULL, +		"possible memory allocation deadlock in %s (mode:0x%x)",  					__func__, gfp_mask);  			XFS_STATS_INC(xb_page_retries); @@ -413,52 +364,44 @@ _xfs_buf_lookup_pages(  		XFS_STATS_INC(xb_page_found); -		nbytes = min_t(size_t, size, PAGE_CACHE_SIZE - offset); +		nbytes = min_t(size_t, size, PAGE_SIZE - offset);  		size -= nbytes; - -		ASSERT(!PagePrivate(page)); -		if (!PageUptodate(page)) { -			page_count--; -			if (blocksize >= PAGE_CACHE_SIZE) { -				if (flags & XBF_READ) -					bp->b_flags |= _XBF_PAGE_LOCKED; -			} else if (!PagePrivate(page)) { -				if (test_page_region(page, offset, nbytes)) -					page_count++; -			} -		} -  		bp->b_pages[i] = page;  		offset = 0;  	} +	return 0; -	if (!(bp->b_flags & _XBF_PAGE_LOCKED)) { -		for (i = 0; i < bp->b_page_count; i++) -			unlock_page(bp->b_pages[i]); -	} - -	if (page_count == bp->b_page_count) -		bp->b_flags |= XBF_DONE; - +out_free_pages: +	for (i = 0; i < bp->b_page_count; i++) +		__free_page(bp->b_pages[i]);  	return error;  }  /* - *	Map buffer into kernel address-space if nessecary. + *	Map buffer into kernel address-space if necessary.   */  STATIC int  _xfs_buf_map_pages(  	xfs_buf_t		*bp,  	uint			flags)  { -	/* A single page buffer is always mappable */ +	ASSERT(bp->b_flags & _XBF_PAGES);  	if (bp->b_page_count == 1) { +		/* A single page buffer is always mappable */  		bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset;  		bp->b_flags |= XBF_MAPPED;  	} else if (flags & XBF_MAPPED) { -		bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count, -					-1, PAGE_KERNEL); -		if (unlikely(bp->b_addr == NULL)) +		int retried = 0; + +		do { +			bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count, +						-1, PAGE_KERNEL); +			if (bp->b_addr) +				break; +			vm_unmap_aliases(); +		} while (retried++ <= 1); + +		if (!bp->b_addr)  			return -ENOMEM;  		bp->b_addr += bp->b_offset;  		bp->b_flags |= XBF_MAPPED; @@ -569,9 +512,14 @@ found:  		}  	} +	/* +	 * if the buffer is stale, clear all the external state associated with +	 * it. We need to keep flags such as how we allocated the buffer memory +	 * intact here. +	 */  	if (bp->b_flags & XBF_STALE) {  		ASSERT((bp->b_flags & _XBF_DELWRI_Q) == 0); -		bp->b_flags &= XBF_MAPPED; +		bp->b_flags &= XBF_MAPPED | _XBF_KMEM | _XBF_PAGES;  	}  	trace_xfs_buf_find(bp, flags, _RET_IP_); @@ -592,7 +540,7 @@ xfs_buf_get(  	xfs_buf_flags_t		flags)  {  	xfs_buf_t		*bp, *new_bp; -	int			error = 0, i; +	int			error = 0;  	new_bp = xfs_buf_allocate(flags);  	if (unlikely(!new_bp)) @@ -600,7 +548,7 @@ xfs_buf_get(  	bp = _xfs_buf_find(target, ioff, isize, flags, new_bp);  	if (bp == new_bp) { -		error = _xfs_buf_lookup_pages(bp, flags); +		error = xfs_buf_allocate_memory(bp, flags);  		if (error)  			goto no_buffer;  	} else { @@ -609,14 +557,11 @@ xfs_buf_get(  			return NULL;  	} -	for (i = 0; i < bp->b_page_count; i++) -		mark_page_accessed(bp->b_pages[i]); -  	if (!(bp->b_flags & XBF_MAPPED)) {  		error = _xfs_buf_map_pages(bp, flags);  		if (unlikely(error)) { -			printk(KERN_WARNING "%s: failed to map pages\n", -					__func__); +			xfs_warn(target->bt_mount, +				"%s: failed to map pages\n", __func__);  			goto no_buffer;  		}  	} @@ -710,10 +655,7 @@ xfs_buf_readahead(  	xfs_off_t		ioff,  	size_t			isize)  { -	struct backing_dev_info *bdi; - -	bdi = target->bt_mapping->backing_dev_info; -	if (bdi_read_congested(bdi)) +	if (bdi_read_congested(target->bt_bdi))  		return;  	xfs_buf_read(target, ioff, isize, @@ -791,10 +733,10 @@ xfs_buf_associate_memory(  	size_t			buflen;  	int			page_count; -	pageaddr = (unsigned long)mem & PAGE_CACHE_MASK; +	pageaddr = (unsigned long)mem & PAGE_MASK;  	offset = (unsigned long)mem - pageaddr; -	buflen = PAGE_CACHE_ALIGN(len + offset); -	page_count = buflen >> PAGE_CACHE_SHIFT; +	buflen = PAGE_ALIGN(len + offset); +	page_count = buflen >> PAGE_SHIFT;  	/* Free any previous set of page pointers */  	if (bp->b_pages) @@ -811,13 +753,12 @@ xfs_buf_associate_memory(  	for (i = 0; i < bp->b_page_count; i++) {  		bp->b_pages[i] = mem_to_page((void *)pageaddr); -		pageaddr += PAGE_CACHE_SIZE; +		pageaddr += PAGE_SIZE;  	}  	bp->b_count_desired = len;  	bp->b_buffer_length = buflen;  	bp->b_flags |= XBF_MAPPED; -	bp->b_flags &= ~_XBF_PAGE_LOCKED;  	return 0;  } @@ -850,8 +791,8 @@ xfs_buf_get_uncached(  	error = _xfs_buf_map_pages(bp, XBF_MAPPED);  	if (unlikely(error)) { -		printk(KERN_WARNING "%s: failed to map pages\n", -				__func__); +		xfs_warn(target->bt_mount, +			"%s: failed to map pages\n", __func__);  		goto fail_free_mem;  	} @@ -924,20 +865,7 @@ xfs_buf_rele(  /* - *	Mutual exclusion on buffers.  Locking model: - * - *	Buffers associated with inodes for which buffer locking - *	is not enabled are not protected by semaphores, and are - *	assumed to be exclusively owned by the caller.  There is a - *	spinlock in the buffer, used by the caller when concurrent - *	access is possible. - */ - -/* - *	Locks a buffer object, if it is not already locked.  Note that this in - *	no way locks the underlying pages, so it is only useful for - *	synchronizing concurrent use of buffer objects, not for synchronizing - *	independent access to the underlying pages. + *	Lock a buffer object, if it is not already locked.   *   *	If we come across a stale, pinned, locked buffer, we know that we are   *	being asked to lock a buffer that has been reallocated. Because it is @@ -971,10 +899,7 @@ xfs_buf_lock_value(  }  /* - *	Locks a buffer object. - *	Note that this in no way locks the underlying pages, so it is only - *	useful for synchronizing concurrent use of buffer objects, not for - *	synchronizing independent access to the underlying pages. + *	Lock a buffer object.   *   *	If we come across a stale, pinned, locked buffer, we know that we   *	are being asked to lock a buffer that has been reallocated. Because @@ -990,8 +915,6 @@ xfs_buf_lock(  	if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE))  		xfs_log_force(bp->b_target->bt_mount, 0); -	if (atomic_read(&bp->b_io_remaining)) -		blk_run_address_space(bp->b_target->bt_mapping);  	down(&bp->b_sema);  	XB_SET_OWNER(bp); @@ -1035,9 +958,7 @@ xfs_buf_wait_unpin(  		set_current_state(TASK_UNINTERRUPTIBLE);  		if (atomic_read(&bp->b_pin_count) == 0)  			break; -		if (atomic_read(&bp->b_io_remaining)) -			blk_run_address_space(bp->b_target->bt_mapping); -		schedule(); +		io_schedule();  	}  	remove_wait_queue(&bp->b_waiters, &wait);  	set_current_state(TASK_RUNNING); @@ -1249,10 +1170,8 @@ _xfs_buf_ioend(  	xfs_buf_t		*bp,  	int			schedule)  { -	if (atomic_dec_and_test(&bp->b_io_remaining) == 1) { -		bp->b_flags &= ~_XBF_PAGE_LOCKED; +	if (atomic_dec_and_test(&bp->b_io_remaining) == 1)  		xfs_buf_ioend(bp, schedule); -	}  }  STATIC void @@ -1261,35 +1180,12 @@ xfs_buf_bio_end_io(  	int			error)  {  	xfs_buf_t		*bp = (xfs_buf_t *)bio->bi_private; -	unsigned int		blocksize = bp->b_target->bt_bsize; -	struct bio_vec		*bvec = bio->bi_io_vec + bio->bi_vcnt - 1;  	xfs_buf_ioerror(bp, -error);  	if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))  		invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); -	do { -		struct page	*page = bvec->bv_page; - -		ASSERT(!PagePrivate(page)); -		if (unlikely(bp->b_error)) { -			if (bp->b_flags & XBF_READ) -				ClearPageUptodate(page); -		} else if (blocksize >= PAGE_CACHE_SIZE) { -			SetPageUptodate(page); -		} else if (!PagePrivate(page) && -				(bp->b_flags & _XBF_PAGE_CACHE)) { -			set_page_region(page, bvec->bv_offset, bvec->bv_len); -		} - -		if (--bvec >= bio->bi_io_vec) -			prefetchw(&bvec->bv_page->flags); - -		if (bp->b_flags & _XBF_PAGE_LOCKED) -			unlock_page(page); -	} while (bvec >= bio->bi_io_vec); -  	_xfs_buf_ioend(bp, 1);  	bio_put(bio);  } @@ -1303,7 +1199,6 @@ _xfs_buf_ioapply(  	int			offset = bp->b_offset;  	int			size = bp->b_count_desired;  	sector_t		sector = bp->b_bn; -	unsigned int		blocksize = bp->b_target->bt_bsize;  	total_nr_pages = bp->b_page_count;  	map_i = 0; @@ -1324,29 +1219,6 @@ _xfs_buf_ioapply(  		     (bp->b_flags & XBF_READ_AHEAD) ? READA : READ;  	} -	/* Special code path for reading a sub page size buffer in -- -	 * we populate up the whole page, and hence the other metadata -	 * in the same page.  This optimization is only valid when the -	 * filesystem block size is not smaller than the page size. -	 */ -	if ((bp->b_buffer_length < PAGE_CACHE_SIZE) && -	    ((bp->b_flags & (XBF_READ|_XBF_PAGE_LOCKED)) == -	      (XBF_READ|_XBF_PAGE_LOCKED)) && -	    (blocksize >= PAGE_CACHE_SIZE)) { -		bio = bio_alloc(GFP_NOIO, 1); - -		bio->bi_bdev = bp->b_target->bt_bdev; -		bio->bi_sector = sector - (offset >> BBSHIFT); -		bio->bi_end_io = xfs_buf_bio_end_io; -		bio->bi_private = bp; - -		bio_add_page(bio, bp->b_pages[0], PAGE_CACHE_SIZE, 0); -		size = 0; - -		atomic_inc(&bp->b_io_remaining); - -		goto submit_io; -	}  next_chunk:  	atomic_inc(&bp->b_io_remaining); @@ -1360,8 +1232,9 @@ next_chunk:  	bio->bi_end_io = xfs_buf_bio_end_io;  	bio->bi_private = bp; +  	for (; size && nr_pages; nr_pages--, map_i++) { -		int	rbytes, nbytes = PAGE_CACHE_SIZE - offset; +		int	rbytes, nbytes = PAGE_SIZE - offset;  		if (nbytes > size)  			nbytes = size; @@ -1376,7 +1249,6 @@ next_chunk:  		total_nr_pages--;  	} -submit_io:  	if (likely(bio->bi_size)) {  		if (xfs_buf_is_vmapped(bp)) {  			flush_kernel_vmap_range(bp->b_addr, @@ -1386,18 +1258,7 @@ submit_io:  		if (size)  			goto next_chunk;  	} else { -		/* -		 * if we get here, no pages were added to the bio. However, -		 * we can't just error out here - if the pages are locked then -		 * we have to unlock them otherwise we can hang on a later -		 * access to the page. -		 */  		xfs_buf_ioerror(bp, EIO); -		if (bp->b_flags & _XBF_PAGE_LOCKED) { -			int i; -			for (i = 0; i < bp->b_page_count; i++) -				unlock_page(bp->b_pages[i]); -		}  		bio_put(bio);  	}  } @@ -1442,8 +1303,6 @@ xfs_buf_iowait(  {  	trace_xfs_buf_iowait(bp, _RET_IP_); -	if (atomic_read(&bp->b_io_remaining)) -		blk_run_address_space(bp->b_target->bt_mapping);  	wait_for_completion(&bp->b_iowait);  	trace_xfs_buf_iowait_done(bp, _RET_IP_); @@ -1461,8 +1320,8 @@ xfs_buf_offset(  		return XFS_BUF_PTR(bp) + offset;  	offset += bp->b_offset; -	page = bp->b_pages[offset >> PAGE_CACHE_SHIFT]; -	return (xfs_caddr_t)page_address(page) + (offset & (PAGE_CACHE_SIZE-1)); +	page = bp->b_pages[offset >> PAGE_SHIFT]; +	return (xfs_caddr_t)page_address(page) + (offset & (PAGE_SIZE-1));  }  /* @@ -1484,9 +1343,9 @@ xfs_buf_iomove(  		page = bp->b_pages[xfs_buf_btoct(boff + bp->b_offset)];  		cpoff = xfs_buf_poff(boff + bp->b_offset);  		csize = min_t(size_t, -			      PAGE_CACHE_SIZE-cpoff, bp->b_count_desired-boff); +			      PAGE_SIZE-cpoff, bp->b_count_desired-boff); -		ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE)); +		ASSERT(((csize + cpoff) <= PAGE_SIZE));  		switch (mode) {  		case XBRW_ZERO: @@ -1599,7 +1458,6 @@ xfs_free_buftarg(  	xfs_flush_buftarg(btp, 1);  	if (mp->m_flags & XFS_MOUNT_BARRIER)  		xfs_blkdev_issue_flush(btp); -	iput(btp->bt_mapping->host);  	kthread_stop(btp->bt_task);  	kmem_free(btp); @@ -1617,21 +1475,12 @@ xfs_setsize_buftarg_flags(  	btp->bt_smask = sectorsize - 1;  	if (set_blocksize(btp->bt_bdev, sectorsize)) { -		printk(KERN_WARNING -			"XFS: Cannot set_blocksize to %u on device %s\n", +		xfs_warn(btp->bt_mount, +			"Cannot set_blocksize to %u on device %s\n",  			sectorsize, XFS_BUFTARG_NAME(btp));  		return EINVAL;  	} -	if (verbose && -	    (PAGE_CACHE_SIZE / BITS_PER_LONG) > sectorsize) { -		printk(KERN_WARNING -			"XFS: %u byte sectors in use on device %s.  " -			"This is suboptimal; %u or greater is ideal.\n", -			sectorsize, XFS_BUFTARG_NAME(btp), -			(unsigned int)PAGE_CACHE_SIZE / BITS_PER_LONG); -	} -  	return 0;  } @@ -1646,7 +1495,7 @@ xfs_setsize_buftarg_early(  	struct block_device	*bdev)  {  	return xfs_setsize_buftarg_flags(btp, -			PAGE_CACHE_SIZE, bdev_logical_block_size(bdev), 0); +			PAGE_SIZE, bdev_logical_block_size(bdev), 0);  }  int @@ -1659,41 +1508,6 @@ xfs_setsize_buftarg(  }  STATIC int -xfs_mapping_buftarg( -	xfs_buftarg_t		*btp, -	struct block_device	*bdev) -{ -	struct backing_dev_info	*bdi; -	struct inode		*inode; -	struct address_space	*mapping; -	static const struct address_space_operations mapping_aops = { -		.sync_page = block_sync_page, -		.migratepage = fail_migrate_page, -	}; - -	inode = new_inode(bdev->bd_inode->i_sb); -	if (!inode) { -		printk(KERN_WARNING -			"XFS: Cannot allocate mapping inode for device %s\n", -			XFS_BUFTARG_NAME(btp)); -		return ENOMEM; -	} -	inode->i_ino = get_next_ino(); -	inode->i_mode = S_IFBLK; -	inode->i_bdev = bdev; -	inode->i_rdev = bdev->bd_dev; -	bdi = blk_get_backing_dev_info(bdev); -	if (!bdi) -		bdi = &default_backing_dev_info; -	mapping = &inode->i_data; -	mapping->a_ops = &mapping_aops; -	mapping->backing_dev_info = bdi; -	mapping_set_gfp_mask(mapping, GFP_NOFS); -	btp->bt_mapping = mapping; -	return 0; -} - -STATIC int  xfs_alloc_delwrite_queue(  	xfs_buftarg_t		*btp,  	const char		*fsname) @@ -1721,12 +1535,14 @@ xfs_alloc_buftarg(  	btp->bt_mount = mp;  	btp->bt_dev =  bdev->bd_dev;  	btp->bt_bdev = bdev; +	btp->bt_bdi = blk_get_backing_dev_info(bdev); +	if (!btp->bt_bdi) +		goto error; +  	INIT_LIST_HEAD(&btp->bt_lru);  	spin_lock_init(&btp->bt_lru_lock);  	if (xfs_setsize_buftarg_early(btp, bdev))  		goto error; -	if (xfs_mapping_buftarg(btp, bdev)) -		goto error;  	if (xfs_alloc_delwrite_queue(btp, fsname))  		goto error;  	btp->bt_shrinker.shrink = xfs_buftarg_shrink; @@ -1923,8 +1739,8 @@ xfsbufd(  	do {  		long	age = xfs_buf_age_centisecs * msecs_to_jiffies(10);  		long	tout = xfs_buf_timer_centisecs * msecs_to_jiffies(10); -		int	count = 0;  		struct list_head tmp; +		struct blk_plug plug;  		if (unlikely(freezing(current))) {  			set_bit(XBT_FORCE_SLEEP, &target->bt_flags); @@ -1940,16 +1756,15 @@ xfsbufd(  		xfs_buf_delwri_split(target, &tmp, age);  		list_sort(NULL, &tmp, xfs_buf_cmp); + +		blk_start_plug(&plug);  		while (!list_empty(&tmp)) {  			struct xfs_buf *bp;  			bp = list_first_entry(&tmp, struct xfs_buf, b_list);  			list_del_init(&bp->b_list);  			xfs_bdstrat_cb(bp); -			count++;  		} -		if (count) -			blk_run_address_space(target->bt_mapping); - +		blk_finish_plug(&plug);  	} while (!kthread_should_stop());  	return 0; @@ -1969,6 +1784,7 @@ xfs_flush_buftarg(  	int		pincount = 0;  	LIST_HEAD(tmp_list);  	LIST_HEAD(wait_list); +	struct blk_plug plug;  	xfs_buf_runall_queues(xfsconvertd_workqueue);  	xfs_buf_runall_queues(xfsdatad_workqueue); @@ -1983,6 +1799,8 @@ xfs_flush_buftarg(  	 * we do that after issuing all the IO.  	 */  	list_sort(NULL, &tmp_list, xfs_buf_cmp); + +	blk_start_plug(&plug);  	while (!list_empty(&tmp_list)) {  		bp = list_first_entry(&tmp_list, struct xfs_buf, b_list);  		ASSERT(target == bp->b_target); @@ -1993,10 +1811,10 @@ xfs_flush_buftarg(  		}  		xfs_bdstrat_cb(bp);  	} +	blk_finish_plug(&plug);  	if (wait) { -		/* Expedite and wait for IO to complete. */ -		blk_run_address_space(target->bt_mapping); +		/* Wait for IO to complete. */  		while (!list_empty(&wait_list)) {  			bp = list_first_entry(&wait_list, struct xfs_buf, b_list); @@ -2022,11 +1840,12 @@ xfs_buf_init(void)  	if (!xfslogd_workqueue)  		goto out_free_buf_zone; -	xfsdatad_workqueue = create_workqueue("xfsdatad"); +	xfsdatad_workqueue = alloc_workqueue("xfsdatad", WQ_MEM_RECLAIM, 1);  	if (!xfsdatad_workqueue)  		goto out_destroy_xfslogd_workqueue; -	xfsconvertd_workqueue = create_workqueue("xfsconvertd"); +	xfsconvertd_workqueue = alloc_workqueue("xfsconvertd", +						WQ_MEM_RECLAIM, 1);  	if (!xfsconvertd_workqueue)  		goto out_destroy_xfsdatad_workqueue; diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index cbe65950e524..a9a1c4512645 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h @@ -61,30 +61,11 @@ typedef enum {  #define XBF_DONT_BLOCK	(1 << 16)/* do not block in current thread */  /* flags used only internally */ -#define _XBF_PAGE_CACHE	(1 << 17)/* backed by pagecache */  #define _XBF_PAGES	(1 << 18)/* backed by refcounted pages */  #define	_XBF_RUN_QUEUES	(1 << 19)/* run block device task queue	*/ +#define	_XBF_KMEM	(1 << 20)/* backed by heap memory */  #define _XBF_DELWRI_Q	(1 << 21)/* buffer on delwri queue */ -/* - * Special flag for supporting metadata blocks smaller than a FSB. - * - * In this case we can have multiple xfs_buf_t on a single page and - * need to lock out concurrent xfs_buf_t readers as they only - * serialise access to the buffer. - * - * If the FSB size >= PAGE_CACHE_SIZE case, we have no serialisation - * between reads of the page. Hence we can have one thread read the - * page and modify it, but then race with another thread that thinks - * the page is not up-to-date and hence reads it again. - * - * The result is that the first modifcation to the page is lost. - * This sort of AGF/AGI reading race can happen when unlinking inodes - * that require truncation and results in the AGI unlinked list - * modifications being lost. - */ -#define _XBF_PAGE_LOCKED	(1 << 22) -  typedef unsigned int xfs_buf_flags_t;  #define XFS_BUF_FLAGS \ @@ -100,12 +81,10 @@ typedef unsigned int xfs_buf_flags_t;  	{ XBF_LOCK,		"LOCK" },  	/* should never be set */\  	{ XBF_TRYLOCK,		"TRYLOCK" }, 	/* ditto */\  	{ XBF_DONT_BLOCK,	"DONT_BLOCK" },	/* ditto */\ -	{ _XBF_PAGE_CACHE,	"PAGE_CACHE" }, \  	{ _XBF_PAGES,		"PAGES" }, \  	{ _XBF_RUN_QUEUES,	"RUN_QUEUES" }, \ -	{ _XBF_DELWRI_Q,	"DELWRI_Q" }, \ -	{ _XBF_PAGE_LOCKED,	"PAGE_LOCKED" } - +	{ _XBF_KMEM,		"KMEM" }, \ +	{ _XBF_DELWRI_Q,	"DELWRI_Q" }  typedef enum {  	XBT_FORCE_SLEEP = 0, @@ -120,7 +99,7 @@ typedef struct xfs_bufhash {  typedef struct xfs_buftarg {  	dev_t			bt_dev;  	struct block_device	*bt_bdev; -	struct address_space	*bt_mapping; +	struct backing_dev_info	*bt_bdi;  	struct xfs_mount	*bt_mount;  	unsigned int		bt_bsize;  	unsigned int		bt_sshift; @@ -139,17 +118,6 @@ typedef struct xfs_buftarg {  	unsigned int		bt_lru_nr;  } xfs_buftarg_t; -/* - *	xfs_buf_t:  Buffer structure for pagecache-based buffers - * - * This buffer structure is used by the pagecache buffer management routines - * to refer to an assembly of pages forming a logical buffer. - * - * The buffer structure is used on a temporary basis only, and discarded when - * released.  The real data storage is recorded in the pagecache. Buffers are - * hashed to the block device on which the file system resides. - */ -  struct xfs_buf;  typedef void (*xfs_buf_iodone_t)(struct xfs_buf *); diff --git a/fs/xfs/linux-2.6/xfs_discard.c b/fs/xfs/linux-2.6/xfs_discard.c index 05201ae719e5..d61611c88012 100644 --- a/fs/xfs/linux-2.6/xfs_discard.c +++ b/fs/xfs/linux-2.6/xfs_discard.c @@ -152,6 +152,8 @@ xfs_ioc_trim(  	if (!capable(CAP_SYS_ADMIN))  		return -XFS_ERROR(EPERM); +	if (!blk_queue_discard(q)) +		return -XFS_ERROR(EOPNOTSUPP);  	if (copy_from_user(&range, urange, sizeof(range)))  		return -XFS_ERROR(EFAULT); diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index fc0114da7fdd..f4f878fc0083 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -89,8 +89,10 @@ xfs_fs_encode_fh(  	 * seven combinations work.  The real answer is "don't use v2".  	 */  	len = xfs_fileid_length(fileid_type); -	if (*max_len < len) +	if (*max_len < len) { +		*max_len = len;  		return 255; +	}  	*max_len = len;  	switch (fileid_type) { diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index a55c1b46b219..f4213ba1ff85 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -381,7 +381,7 @@ xfs_aio_write_isize_update(  /*   * If this was a direct or synchronous I/O that failed (such as ENOSPC) then - * part of the I/O may have been written to disk before the error occured.  In + * part of the I/O may have been written to disk before the error occurred.  In   * this case the on-disk file size may have been adjusted beyond the in-memory   * file size and now needs to be truncated back.   */ @@ -896,6 +896,7 @@ xfs_file_fallocate(  	xfs_flock64_t	bf;  	xfs_inode_t	*ip = XFS_I(inode);  	int		cmd = XFS_IOC_RESVSP; +	int		attr_flags = XFS_ATTR_NOLOCK;  	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))  		return -EOPNOTSUPP; @@ -918,7 +919,10 @@ xfs_file_fallocate(  			goto out_unlock;  	} -	error = -xfs_change_file_space(ip, cmd, &bf, 0, XFS_ATTR_NOLOCK); +	if (file->f_flags & O_DSYNC) +		attr_flags |= XFS_ATTR_SYNC; + +	error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags);  	if (error)  		goto out_unlock; diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index f5e2a19e0f8e..acca2c5ca3fa 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -624,6 +624,10 @@ xfs_ioc_space(  	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))  		attr_flags |= XFS_ATTR_NONBLOCK; + +	if (filp->f_flags & O_DSYNC) +		attr_flags |= XFS_ATTR_SYNC; +  	if (ioflags & IO_INVIS)  		attr_flags |= XFS_ATTR_DMI; @@ -695,14 +699,19 @@ xfs_ioc_fsgeometry_v1(  	xfs_mount_t		*mp,  	void			__user *arg)  { -	xfs_fsop_geom_v1_t	fsgeo; +	xfs_fsop_geom_t         fsgeo;  	int			error; -	error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3); +	error = xfs_fs_geometry(mp, &fsgeo, 3);  	if (error)  		return -error; -	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo))) +	/* +	 * Caller should have passed an argument of type +	 * xfs_fsop_geom_v1_t.  This is a proper subset of the +	 * xfs_fsop_geom_t that xfs_fs_geometry() fills in. +	 */ +	if (copy_to_user(arg, &fsgeo, sizeof(xfs_fsop_geom_v1_t)))  		return -XFS_ERROR(EFAULT);  	return 0;  } diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index bd5727852fd6..dd21784525a8 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -70,7 +70,7 @@ xfs_synchronize_times(  /*   * If the linux inode is valid, mark it dirty. - * Used when commiting a dirty inode into a transaction so that + * Used when committing a dirty inode into a transaction so that   * the inode will get written back by the linux code   */  void @@ -102,7 +102,8 @@ xfs_mark_inode_dirty(  STATIC int  xfs_init_security(  	struct inode	*inode, -	struct inode	*dir) +	struct inode	*dir, +	const struct qstr *qstr)  {  	struct xfs_inode *ip = XFS_I(inode);  	size_t		length; @@ -110,7 +111,7 @@ xfs_init_security(  	unsigned char	*name;  	int		error; -	error = security_inode_init_security(inode, dir, (char **)&name, +	error = security_inode_init_security(inode, dir, qstr, (char **)&name,  					     &value, &length);  	if (error) {  		if (error == -EOPNOTSUPP) @@ -194,7 +195,7 @@ xfs_vn_mknod(  	inode = VFS_I(ip); -	error = xfs_init_security(inode, dir); +	error = xfs_init_security(inode, dir, &dentry->d_name);  	if (unlikely(error))  		goto out_cleanup_inode; @@ -367,7 +368,7 @@ xfs_vn_symlink(  	inode = VFS_I(cip); -	error = xfs_init_security(inode, dir); +	error = xfs_init_security(inode, dir, &dentry->d_name);  	if (unlikely(error))  		goto out_cleanup_inode; diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 096494997747..244be9cbfe78 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -39,7 +39,6 @@  #include <mrlock.h>  #include <time.h> -#include <support/debug.h>  #include <support/uuid.h>  #include <linux/semaphore.h> @@ -86,6 +85,7 @@  #include <xfs_aops.h>  #include <xfs_super.h>  #include <xfs_buf.h> +#include <xfs_message.h>  /*   * Feature macros (disable/enable) @@ -280,4 +280,25 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)  #define __arch_pack  #endif +#define ASSERT_ALWAYS(expr)	\ +	(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) + +#ifndef DEBUG +#define ASSERT(expr)	((void)0) + +#ifndef STATIC +# define STATIC static noinline +#endif + +#else /* DEBUG */ + +#define ASSERT(expr)	\ +	(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) + +#ifndef STATIC +# define STATIC noinline +#endif + +#endif /* DEBUG */ +  #endif /* __XFS_LINUX__ */ diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/linux-2.6/xfs_message.c new file mode 100644 index 000000000000..9f76cceb678d --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_message.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2011 Red Hat, Inc.  All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + */ + +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_types.h" +#include "xfs_log.h" +#include "xfs_inum.h" +#include "xfs_trans.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "xfs_mount.h" + +/* + * XFS logging functions + */ +static void +__xfs_printk( +	const char		*level, +	const struct xfs_mount	*mp, +	struct va_format	*vaf) +{ +	if (mp && mp->m_fsname) { +		printk("%sXFS (%s): %pV\n", level, mp->m_fsname, vaf); +		return; +	} +	printk("%sXFS: %pV\n", level, vaf); +} + +void xfs_printk( +	const char		*level, +	const struct xfs_mount	*mp, +	const char		*fmt, ...) +{ +	struct va_format	vaf; +	va_list			args; + +	va_start(args, fmt); + +	vaf.fmt = fmt; +	vaf.va = &args; + +	__xfs_printk(level, mp, &vaf); +	va_end(args); +} + +#define define_xfs_printk_level(func, kern_level)		\ +void func(const struct xfs_mount *mp, const char *fmt, ...)	\ +{								\ +	struct va_format	vaf;				\ +	va_list			args;				\ +								\ +	va_start(args, fmt);					\ +								\ +	vaf.fmt = fmt;						\ +	vaf.va = &args;						\ +								\ +	__xfs_printk(kern_level, mp, &vaf);			\ +	va_end(args);						\ +}								\ + +define_xfs_printk_level(xfs_emerg, KERN_EMERG); +define_xfs_printk_level(xfs_alert, KERN_ALERT); +define_xfs_printk_level(xfs_crit, KERN_CRIT); +define_xfs_printk_level(xfs_err, KERN_ERR); +define_xfs_printk_level(xfs_warn, KERN_WARNING); +define_xfs_printk_level(xfs_notice, KERN_NOTICE); +define_xfs_printk_level(xfs_info, KERN_INFO); +#ifdef DEBUG +define_xfs_printk_level(xfs_debug, KERN_DEBUG); +#endif + +void +xfs_alert_tag( +	const struct xfs_mount	*mp, +	int			panic_tag, +	const char		*fmt, ...) +{ +	struct va_format	vaf; +	va_list			args; +	int			do_panic = 0; + +	if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) { +		xfs_printk(KERN_ALERT, mp, +			"XFS: Transforming an alert into a BUG."); +		do_panic = 1; +	} + +	va_start(args, fmt); + +	vaf.fmt = fmt; +	vaf.va = &args; + +	__xfs_printk(KERN_ALERT, mp, &vaf); +	va_end(args); + +	BUG_ON(do_panic); +} + +void +assfail(char *expr, char *file, int line) +{ +	xfs_emerg(NULL, "Assertion failed: %s, file: %s, line: %d", +		expr, file, line); +	BUG(); +} + +void +xfs_hex_dump(void *p, int length) +{ +	print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_ADDRESS, 16, 1, p, length, 1); +} diff --git a/fs/xfs/linux-2.6/xfs_message.h b/fs/xfs/linux-2.6/xfs_message.h new file mode 100644 index 000000000000..f1b3fc1b6c4e --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_message.h @@ -0,0 +1,40 @@ +#ifndef __XFS_MESSAGE_H +#define __XFS_MESSAGE_H 1 + +struct xfs_mount; + +extern void xfs_printk(const char *level, const struct xfs_mount *mp, +                      const char *fmt, ...) +        __attribute__ ((format (printf, 3, 4))); +extern void xfs_emerg(const struct xfs_mount *mp, const char *fmt, ...) +        __attribute__ ((format (printf, 2, 3))); +extern void xfs_alert(const struct xfs_mount *mp, const char *fmt, ...) +        __attribute__ ((format (printf, 2, 3))); +extern void xfs_alert_tag(const struct xfs_mount *mp, int tag, +			 const char *fmt, ...) +        __attribute__ ((format (printf, 3, 4))); +extern void xfs_crit(const struct xfs_mount *mp, const char *fmt, ...) +        __attribute__ ((format (printf, 2, 3))); +extern void xfs_err(const struct xfs_mount *mp, const char *fmt, ...) +        __attribute__ ((format (printf, 2, 3))); +extern void xfs_warn(const struct xfs_mount *mp, const char *fmt, ...) +        __attribute__ ((format (printf, 2, 3))); +extern void xfs_notice(const struct xfs_mount *mp, const char *fmt, ...) +        __attribute__ ((format (printf, 2, 3))); +extern void xfs_info(const struct xfs_mount *mp, const char *fmt, ...) +        __attribute__ ((format (printf, 2, 3))); + +#ifdef DEBUG +extern void xfs_debug(const struct xfs_mount *mp, const char *fmt, ...) +        __attribute__ ((format (printf, 2, 3))); +#else +static inline void xfs_debug(const struct xfs_mount *mp, const char *fmt, ...) +{ +} +#endif + +extern void assfail(char *expr, char *f, int l); + +extern void xfs_hex_dump(void *p, int length); + +#endif	/* __XFS_MESSAGE_H */ diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 9731898083ae..b38e58d02299 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -173,6 +173,15 @@ xfs_parseargs(  	__uint8_t		iosizelog = 0;  	/* +	 * set up the mount name first so all the errors will refer to the +	 * correct device. +	 */ +	mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL); +	if (!mp->m_fsname) +		return ENOMEM; +	mp->m_fsname_len = strlen(mp->m_fsname) + 1; + +	/*  	 * Copy binary VFS mount flags we are interested in.  	 */  	if (sb->s_flags & MS_RDONLY) @@ -189,6 +198,7 @@ xfs_parseargs(  	mp->m_flags |= XFS_MOUNT_BARRIER;  	mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;  	mp->m_flags |= XFS_MOUNT_SMALL_INUMS; +	mp->m_flags |= XFS_MOUNT_DELAYLOG;  	/*  	 * These can be overridden by the mount option parsing. @@ -207,24 +217,21 @@ xfs_parseargs(  		if (!strcmp(this_char, MNTOPT_LOGBUFS)) {  			if (!value || !*value) { -				cmn_err(CE_WARN, -					"XFS: %s option requires an argument", +				xfs_warn(mp, "%s option requires an argument",  					this_char);  				return EINVAL;  			}  			mp->m_logbufs = simple_strtoul(value, &eov, 10);  		} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {  			if (!value || !*value) { -				cmn_err(CE_WARN, -					"XFS: %s option requires an argument", +				xfs_warn(mp, "%s option requires an argument",  					this_char);  				return EINVAL;  			}  			mp->m_logbsize = suffix_strtoul(value, &eov, 10);  		} else if (!strcmp(this_char, MNTOPT_LOGDEV)) {  			if (!value || !*value) { -				cmn_err(CE_WARN, -					"XFS: %s option requires an argument", +				xfs_warn(mp, "%s option requires an argument",  					this_char);  				return EINVAL;  			} @@ -232,14 +239,12 @@ xfs_parseargs(  			if (!mp->m_logname)  				return ENOMEM;  		} else if (!strcmp(this_char, MNTOPT_MTPT)) { -			cmn_err(CE_WARN, -				"XFS: %s option not allowed on this system", +			xfs_warn(mp, "%s option not allowed on this system",  				this_char);  			return EINVAL;  		} else if (!strcmp(this_char, MNTOPT_RTDEV)) {  			if (!value || !*value) { -				cmn_err(CE_WARN, -					"XFS: %s option requires an argument", +				xfs_warn(mp, "%s option requires an argument",  					this_char);  				return EINVAL;  			} @@ -248,8 +253,7 @@ xfs_parseargs(  				return ENOMEM;  		} else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {  			if (!value || !*value) { -				cmn_err(CE_WARN, -					"XFS: %s option requires an argument", +				xfs_warn(mp, "%s option requires an argument",  					this_char);  				return EINVAL;  			} @@ -257,8 +261,7 @@ xfs_parseargs(  			iosizelog = ffs(iosize) - 1;  		} else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {  			if (!value || !*value) { -				cmn_err(CE_WARN, -					"XFS: %s option requires an argument", +				xfs_warn(mp, "%s option requires an argument",  					this_char);  				return EINVAL;  			} @@ -280,16 +283,14 @@ xfs_parseargs(  			mp->m_flags |= XFS_MOUNT_SWALLOC;  		} else if (!strcmp(this_char, MNTOPT_SUNIT)) {  			if (!value || !*value) { -				cmn_err(CE_WARN, -					"XFS: %s option requires an argument", +				xfs_warn(mp, "%s option requires an argument",  					this_char);  				return EINVAL;  			}  			dsunit = simple_strtoul(value, &eov, 10);  		} else if (!strcmp(this_char, MNTOPT_SWIDTH)) {  			if (!value || !*value) { -				cmn_err(CE_WARN, -					"XFS: %s option requires an argument", +				xfs_warn(mp, "%s option requires an argument",  					this_char);  				return EINVAL;  			} @@ -297,8 +298,7 @@ xfs_parseargs(  		} else if (!strcmp(this_char, MNTOPT_64BITINODE)) {  			mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;  #if !XFS_BIG_INUMS -			cmn_err(CE_WARN, -				"XFS: %s option not allowed on this system", +			xfs_warn(mp, "%s option not allowed on this system",  				this_char);  			return EINVAL;  #endif @@ -356,20 +356,19 @@ xfs_parseargs(  		} else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) {  			mp->m_flags &= ~XFS_MOUNT_DELAYLOG;  		} else if (!strcmp(this_char, "ihashsize")) { -			cmn_err(CE_WARN, -	"XFS: ihashsize no longer used, option is deprecated."); +			xfs_warn(mp, +	"ihashsize no longer used, option is deprecated.");  		} else if (!strcmp(this_char, "osyncisdsync")) { -			cmn_err(CE_WARN, -	"XFS: osyncisdsync has no effect, option is deprecated."); +			xfs_warn(mp, +	"osyncisdsync has no effect, option is deprecated.");  		} else if (!strcmp(this_char, "osyncisosync")) { -			cmn_err(CE_WARN, -	"XFS: osyncisosync has no effect, option is deprecated."); +			xfs_warn(mp, +	"osyncisosync has no effect, option is deprecated.");  		} else if (!strcmp(this_char, "irixsgid")) { -			cmn_err(CE_WARN, -	"XFS: irixsgid is now a sysctl(2) variable, option is deprecated."); +			xfs_warn(mp, +	"irixsgid is now a sysctl(2) variable, option is deprecated.");  		} else { -			cmn_err(CE_WARN, -				"XFS: unknown mount option [%s].", this_char); +			xfs_warn(mp, "unknown mount option [%s].", this_char);  			return EINVAL;  		}  	} @@ -379,40 +378,37 @@ xfs_parseargs(  	 */  	if ((mp->m_flags & XFS_MOUNT_NORECOVERY) &&  	    !(mp->m_flags & XFS_MOUNT_RDONLY)) { -		cmn_err(CE_WARN, "XFS: no-recovery mounts must be read-only."); +		xfs_warn(mp, "no-recovery mounts must be read-only.");  		return EINVAL;  	}  	if ((mp->m_flags & XFS_MOUNT_NOALIGN) && (dsunit || dswidth)) { -		cmn_err(CE_WARN, -	"XFS: sunit and swidth options incompatible with the noalign option"); +		xfs_warn(mp, +	"sunit and swidth options incompatible with the noalign option");  		return EINVAL;  	}  #ifndef CONFIG_XFS_QUOTA  	if (XFS_IS_QUOTA_RUNNING(mp)) { -		cmn_err(CE_WARN, -			"XFS: quota support not available in this kernel."); +		xfs_warn(mp, "quota support not available in this kernel.");  		return EINVAL;  	}  #endif  	if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&  	    (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) { -		cmn_err(CE_WARN, -			"XFS: cannot mount with both project and group quota"); +		xfs_warn(mp, "cannot mount with both project and group quota");  		return EINVAL;  	}  	if ((dsunit && !dswidth) || (!dsunit && dswidth)) { -		cmn_err(CE_WARN, -			"XFS: sunit and swidth must be specified together"); +		xfs_warn(mp, "sunit and swidth must be specified together");  		return EINVAL;  	}  	if (dsunit && (dswidth % dsunit != 0)) { -		cmn_err(CE_WARN, -	"XFS: stripe width (%d) must be a multiple of the stripe unit (%d)", +		xfs_warn(mp, +	"stripe width (%d) must be a multiple of the stripe unit (%d)",  			dswidth, dsunit);  		return EINVAL;  	} @@ -438,8 +434,7 @@ done:  	    mp->m_logbufs != 0 &&  	    (mp->m_logbufs < XLOG_MIN_ICLOGS ||  	     mp->m_logbufs > XLOG_MAX_ICLOGS)) { -		cmn_err(CE_WARN, -			"XFS: invalid logbufs value: %d [not %d-%d]", +		xfs_warn(mp, "invalid logbufs value: %d [not %d-%d]",  			mp->m_logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);  		return XFS_ERROR(EINVAL);  	} @@ -448,22 +443,16 @@ done:  	    (mp->m_logbsize < XLOG_MIN_RECORD_BSIZE ||  	     mp->m_logbsize > XLOG_MAX_RECORD_BSIZE ||  	     !is_power_of_2(mp->m_logbsize))) { -		cmn_err(CE_WARN, -	"XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]", +		xfs_warn(mp, +			"invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",  			mp->m_logbsize);  		return XFS_ERROR(EINVAL);  	} -	mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL); -	if (!mp->m_fsname) -		return ENOMEM; -	mp->m_fsname_len = strlen(mp->m_fsname) + 1; -  	if (iosizelog) {  		if (iosizelog > XFS_MAX_IO_LOG ||  		    iosizelog < XFS_MIN_IO_LOG) { -			cmn_err(CE_WARN, -		"XFS: invalid log iosize: %d [not %d-%d]", +			xfs_warn(mp, "invalid log iosize: %d [not %d-%d]",  				iosizelog, XFS_MIN_IO_LOG,  				XFS_MAX_IO_LOG);  			return XFS_ERROR(EINVAL); @@ -610,7 +599,7 @@ xfs_blkdev_get(  				    mp);  	if (IS_ERR(*bdevp)) {  		error = PTR_ERR(*bdevp); -		printk("XFS: Invalid device [%s], error=%d\n", name, error); +		xfs_warn(mp, "Invalid device [%s], error=%d\n", name, error);  	}  	return -error; @@ -664,23 +653,23 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp)  	int error;  	if (mp->m_logdev_targp != mp->m_ddev_targp) { -		xfs_fs_cmn_err(CE_NOTE, mp, +		xfs_notice(mp,  		  "Disabling barriers, not supported with external log device");  		mp->m_flags &= ~XFS_MOUNT_BARRIER;  		return;  	}  	if (xfs_readonly_buftarg(mp->m_ddev_targp)) { -		xfs_fs_cmn_err(CE_NOTE, mp, -		  "Disabling barriers, underlying device is readonly"); +		xfs_notice(mp, +			"Disabling barriers, underlying device is readonly");  		mp->m_flags &= ~XFS_MOUNT_BARRIER;  		return;  	}  	error = xfs_barrier_test(mp);  	if (error) { -		xfs_fs_cmn_err(CE_NOTE, mp, -		  "Disabling barriers, trial barrier write failed"); +		xfs_notice(mp, +			"Disabling barriers, trial barrier write failed");  		mp->m_flags &= ~XFS_MOUNT_BARRIER;  		return;  	} @@ -743,8 +732,8 @@ xfs_open_devices(  			goto out_close_logdev;  		if (rtdev == ddev || rtdev == logdev) { -			cmn_err(CE_WARN, -	"XFS: Cannot mount filesystem with identical rtdev and ddev/logdev."); +			xfs_warn(mp, +	"Cannot mount filesystem with identical rtdev and ddev/logdev.");  			error = EINVAL;  			goto out_close_rtdev;  		} @@ -827,75 +816,6 @@ xfs_setup_devices(  	return 0;  } -/* - * XFS AIL push thread support - */ -void -xfsaild_wakeup( -	struct xfs_ail		*ailp, -	xfs_lsn_t		threshold_lsn) -{ -	/* only ever move the target forwards */ -	if (XFS_LSN_CMP(threshold_lsn, ailp->xa_target) > 0) { -		ailp->xa_target = threshold_lsn; -		wake_up_process(ailp->xa_task); -	} -} - -STATIC int -xfsaild( -	void	*data) -{ -	struct xfs_ail	*ailp = data; -	xfs_lsn_t	last_pushed_lsn = 0; -	long		tout = 0; /* milliseconds */ - -	while (!kthread_should_stop()) { -		/* -		 * for short sleeps indicating congestion, don't allow us to -		 * get woken early. Otherwise all we do is bang on the AIL lock -		 * without making progress. -		 */ -		if (tout && tout <= 20) -			__set_current_state(TASK_KILLABLE); -		else -			__set_current_state(TASK_INTERRUPTIBLE); -		schedule_timeout(tout ? -				 msecs_to_jiffies(tout) : MAX_SCHEDULE_TIMEOUT); - -		/* swsusp */ -		try_to_freeze(); - -		ASSERT(ailp->xa_mount->m_log); -		if (XFS_FORCED_SHUTDOWN(ailp->xa_mount)) -			continue; - -		tout = xfsaild_push(ailp, &last_pushed_lsn); -	} - -	return 0; -}	/* xfsaild */ - -int -xfsaild_start( -	struct xfs_ail	*ailp) -{ -	ailp->xa_target = 0; -	ailp->xa_task = kthread_run(xfsaild, ailp, "xfsaild/%s", -				    ailp->xa_mount->m_fsname); -	if (IS_ERR(ailp->xa_task)) -		return -PTR_ERR(ailp->xa_task); -	return 0; -} - -void -xfsaild_stop( -	struct xfs_ail	*ailp) -{ -	kthread_stop(ailp->xa_task); -} - -  /* Catch misguided souls that try to use this interface on XFS */  STATIC struct inode *  xfs_fs_alloc_inode( @@ -1089,7 +1009,7 @@ xfs_fs_write_inode(  			error = 0;  			goto out_unlock;  		} -		error = xfs_iflush(ip, 0); +		error = xfs_iflush(ip, SYNC_TRYLOCK);  	}   out_unlock: @@ -1202,22 +1122,12 @@ xfs_fs_sync_fs(  		return -error;  	if (laptop_mode) { -		int	prev_sync_seq = mp->m_sync_seq; -  		/*  		 * The disk must be active because we're syncing.  		 * We schedule xfssyncd now (now that the disk is  		 * active) instead of later (when it might not be).  		 */ -		wake_up_process(mp->m_sync_task); -		/* -		 * We have to wait for the sync iteration to complete. -		 * If we don't, the disk activity caused by the sync -		 * will come after the sync is completed, and that -		 * triggers another sync from laptop mode. -		 */ -		wait_event(mp->m_wait_single_sync_task, -				mp->m_sync_seq != prev_sync_seq); +		flush_delayed_work_sync(&mp->m_sync_work);  	}  	return 0; @@ -1345,8 +1255,8 @@ xfs_fs_remount(  			 * options that we can't actually change.  			 */  #if 0 -			printk(KERN_INFO -	"XFS: mount option \"%s\" not supported for remount\n", p); +			xfs_info(mp, +		"mount option \"%s\" not supported for remount\n", p);  			return -EINVAL;  #else  			break; @@ -1367,8 +1277,7 @@ xfs_fs_remount(  		if (mp->m_update_flags) {  			error = xfs_mount_log_sb(mp, mp->m_update_flags);  			if (error) { -				cmn_err(CE_WARN, -					"XFS: failed to write sb changes"); +				xfs_warn(mp, "failed to write sb changes");  				return error;  			}  			mp->m_update_flags = 0; @@ -1452,15 +1361,15 @@ xfs_finish_flags(  			mp->m_logbsize = mp->m_sb.sb_logsunit;  		} else if (mp->m_logbsize > 0 &&  			   mp->m_logbsize < mp->m_sb.sb_logsunit) { -			cmn_err(CE_WARN, -	"XFS: logbuf size must be greater than or equal to log stripe size"); +			xfs_warn(mp, +		"logbuf size must be greater than or equal to log stripe size");  			return XFS_ERROR(EINVAL);  		}  	} else {  		/* Fail a mount if the logbuf is larger than 32K */  		if (mp->m_logbsize > XLOG_BIG_RECORD_BSIZE) { -			cmn_err(CE_WARN, -	"XFS: logbuf size for version 1 logs must be 16K or 32K"); +			xfs_warn(mp, +		"logbuf size for version 1 logs must be 16K or 32K");  			return XFS_ERROR(EINVAL);  		}  	} @@ -1477,8 +1386,8 @@ xfs_finish_flags(  	 * prohibit r/w mounts of read-only filesystems  	 */  	if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) { -		cmn_err(CE_WARN, -	"XFS: cannot mount a read-only filesystem as read-write"); +		xfs_warn(mp, +			"cannot mount a read-only filesystem as read-write");  		return XFS_ERROR(EROFS);  	} @@ -1502,9 +1411,6 @@ xfs_fs_fill_super(  	spin_lock_init(&mp->m_sb_lock);  	mutex_init(&mp->m_growlock);  	atomic_set(&mp->m_active_trans, 0); -	INIT_LIST_HEAD(&mp->m_sync_list); -	spin_lock_init(&mp->m_sync_lock); -	init_waitqueue_head(&mp->m_wait_single_sync_task);  	mp->m_super = sb;  	sb->s_fs_info = mp; @@ -1551,10 +1457,14 @@ xfs_fs_fill_super(  	if (error)  		goto out_free_sb; -	error = xfs_mountfs(mp); -	if (error) -		goto out_filestream_unmount; - +	/* +	 * we must configure the block size in the superblock before we run the +	 * full mount process as the mount process can lookup and cache inodes. +	 * For the same reason we must also initialise the syncd and register +	 * the inode cache shrinker so that inodes can be reclaimed during +	 * operations like a quotacheck that iterate all inodes in the +	 * filesystem. +	 */  	sb->s_magic = XFS_SB_MAGIC;  	sb->s_blocksize = mp->m_sb.sb_blocksize;  	sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1; @@ -1562,6 +1472,16 @@ xfs_fs_fill_super(  	sb->s_time_gran = 1;  	set_posix_acl_flag(sb); +	error = xfs_syncd_init(mp); +	if (error) +		goto out_filestream_unmount; + +	xfs_inode_shrinker_register(mp); + +	error = xfs_mountfs(mp); +	if (error) +		goto out_syncd_stop; +  	root = igrab(VFS_I(mp->m_rootip));  	if (!root) {  		error = ENOENT; @@ -1577,14 +1497,11 @@ xfs_fs_fill_super(  		goto fail_vnrele;  	} -	error = xfs_syncd_init(mp); -	if (error) -		goto fail_vnrele; - -	xfs_inode_shrinker_register(mp); -  	return 0; + out_syncd_stop: +	xfs_inode_shrinker_unregister(mp); +	xfs_syncd_stop(mp);   out_filestream_unmount:  	xfs_filestream_unmount(mp);   out_free_sb: @@ -1608,6 +1525,9 @@ xfs_fs_fill_super(  	}   fail_unmount: +	xfs_inode_shrinker_unregister(mp); +	xfs_syncd_stop(mp); +  	/*  	 * Blow away any referenced inode in the filestreams cache.  	 * This can and will cause log traffic as inodes go inactive @@ -1797,6 +1717,38 @@ xfs_destroy_zones(void)  }  STATIC int __init +xfs_init_workqueues(void) +{ +	/* +	 * max_active is set to 8 to give enough concurency to allow +	 * multiple work operations on each CPU to run. This allows multiple +	 * filesystems to be running sync work concurrently, and scales with +	 * the number of CPUs in the system. +	 */ +	xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_CPU_INTENSIVE, 8); +	if (!xfs_syncd_wq) +		goto out; + +	xfs_ail_wq = alloc_workqueue("xfsail", WQ_CPU_INTENSIVE, 8); +	if (!xfs_ail_wq) +		goto out_destroy_syncd; + +	return 0; + +out_destroy_syncd: +	destroy_workqueue(xfs_syncd_wq); +out: +	return -ENOMEM; +} + +STATIC void +xfs_destroy_workqueues(void) +{ +	destroy_workqueue(xfs_ail_wq); +	destroy_workqueue(xfs_syncd_wq); +} + +STATIC int __init  init_xfs_fs(void)  {  	int			error; @@ -1811,10 +1763,14 @@ init_xfs_fs(void)  	if (error)  		goto out; -	error = xfs_mru_cache_init(); +	error = xfs_init_workqueues();  	if (error)  		goto out_destroy_zones; +	error = xfs_mru_cache_init(); +	if (error) +		goto out_destroy_wq; +  	error = xfs_filestream_init();  	if (error)  		goto out_mru_cache_uninit; @@ -1831,6 +1787,10 @@ init_xfs_fs(void)  	if (error)  		goto out_cleanup_procfs; +	error = xfs_init_workqueues(); +	if (error) +		goto out_sysctl_unregister; +  	vfs_initquota();  	error = register_filesystem(&xfs_fs_type); @@ -1848,6 +1808,8 @@ init_xfs_fs(void)  	xfs_filestream_uninit();   out_mru_cache_uninit:  	xfs_mru_cache_uninit(); + out_destroy_wq: +	xfs_destroy_workqueues();   out_destroy_zones:  	xfs_destroy_zones();   out: @@ -1864,6 +1826,7 @@ exit_xfs_fs(void)  	xfs_buf_terminate();  	xfs_filestream_uninit();  	xfs_mru_cache_uninit(); +	xfs_destroy_workqueues();  	xfs_destroy_zones();  } diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index e22f0057d21f..e4f9c1b0836c 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -22,6 +22,7 @@  #include "xfs_log.h"  #include "xfs_inum.h"  #include "xfs_trans.h" +#include "xfs_trans_priv.h"  #include "xfs_sb.h"  #include "xfs_ag.h"  #include "xfs_mount.h" @@ -39,6 +40,8 @@  #include <linux/kthread.h>  #include <linux/freezer.h> +struct workqueue_struct	*xfs_syncd_wq;	/* sync workqueue */ +  /*   * The inode lookup is done in batches to keep the amount of lock traffic and   * radix tree lookups to a minimum. The batch size is a trade off between @@ -401,7 +404,7 @@ xfs_quiesce_fs(  /*   * Second stage of a quiesce. The data is already synced, now we have to take   * care of the metadata. New transactions are already blocked, so we need to - * wait for any remaining transactions to drain out before proceding. + * wait for any remaining transactions to drain out before proceeding.   */  void  xfs_quiesce_attr( @@ -425,69 +428,18 @@ xfs_quiesce_attr(  	/* Push the superblock and write an unmount record */  	error = xfs_log_sbcount(mp, 1);  	if (error) -		xfs_fs_cmn_err(CE_WARN, mp, -				"xfs_attr_quiesce: failed to log sb changes. " +		xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "  				"Frozen image may not be consistent.");  	xfs_log_unmount_write(mp);  	xfs_unmountfs_writesb(mp);  } -/* - * Enqueue a work item to be picked up by the vfs xfssyncd thread. - * Doing this has two advantages: - * - It saves on stack space, which is tight in certain situations - * - It can be used (with care) as a mechanism to avoid deadlocks. - * Flushing while allocating in a full filesystem requires both. - */ -STATIC void -xfs_syncd_queue_work( -	struct xfs_mount *mp, -	void		*data, -	void		(*syncer)(struct xfs_mount *, void *), -	struct completion *completion) -{ -	struct xfs_sync_work *work; - -	work = kmem_alloc(sizeof(struct xfs_sync_work), KM_SLEEP); -	INIT_LIST_HEAD(&work->w_list); -	work->w_syncer = syncer; -	work->w_data = data; -	work->w_mount = mp; -	work->w_completion = completion; -	spin_lock(&mp->m_sync_lock); -	list_add_tail(&work->w_list, &mp->m_sync_list); -	spin_unlock(&mp->m_sync_lock); -	wake_up_process(mp->m_sync_task); -} - -/* - * Flush delayed allocate data, attempting to free up reserved space - * from existing allocations.  At this point a new allocation attempt - * has failed with ENOSPC and we are in the process of scratching our - * heads, looking about for more room... - */ -STATIC void -xfs_flush_inodes_work( -	struct xfs_mount *mp, -	void		*arg) -{ -	struct inode	*inode = arg; -	xfs_sync_data(mp, SYNC_TRYLOCK); -	xfs_sync_data(mp, SYNC_TRYLOCK | SYNC_WAIT); -	iput(inode); -} - -void -xfs_flush_inodes( -	xfs_inode_t	*ip) +static void +xfs_syncd_queue_sync( +	struct xfs_mount        *mp)  { -	struct inode	*inode = VFS_I(ip); -	DECLARE_COMPLETION_ONSTACK(completion); - -	igrab(inode); -	xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work, &completion); -	wait_for_completion(&completion); -	xfs_log_force(ip->i_mount, XFS_LOG_SYNC); +	queue_delayed_work(xfs_syncd_wq, &mp->m_sync_work, +				msecs_to_jiffies(xfs_syncd_centisecs * 10));  }  /* @@ -497,9 +449,10 @@ xfs_flush_inodes(   */  STATIC void  xfs_sync_worker( -	struct xfs_mount *mp, -	void		*unused) +	struct work_struct *work)  { +	struct xfs_mount *mp = container_of(to_delayed_work(work), +					struct xfs_mount, m_sync_work);  	int		error;  	if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { @@ -509,73 +462,106 @@ xfs_sync_worker(  			error = xfs_fs_log_dummy(mp);  		else  			xfs_log_force(mp, 0); -		xfs_reclaim_inodes(mp, 0);  		error = xfs_qm_sync(mp, SYNC_TRYLOCK); + +		/* start pushing all the metadata that is currently dirty */ +		xfs_ail_push_all(mp->m_ail);  	} -	mp->m_sync_seq++; -	wake_up(&mp->m_wait_single_sync_task); + +	/* queue us up again */ +	xfs_syncd_queue_sync(mp);  } -STATIC int -xfssyncd( -	void			*arg) +/* + * Queue a new inode reclaim pass if there are reclaimable inodes and there + * isn't a reclaim pass already in progress. By default it runs every 5s based + * on the xfs syncd work default of 30s. Perhaps this should have it's own + * tunable, but that can be done if this method proves to be ineffective or too + * aggressive. + */ +static void +xfs_syncd_queue_reclaim( +	struct xfs_mount        *mp)  { -	struct xfs_mount	*mp = arg; -	long			timeleft; -	xfs_sync_work_t		*work, *n; -	LIST_HEAD		(tmp); - -	set_freezable(); -	timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10); -	for (;;) { -		if (list_empty(&mp->m_sync_list)) -			timeleft = schedule_timeout_interruptible(timeleft); -		/* swsusp */ -		try_to_freeze(); -		if (kthread_should_stop() && list_empty(&mp->m_sync_list)) -			break; -		spin_lock(&mp->m_sync_lock); -		/* -		 * We can get woken by laptop mode, to do a sync - -		 * that's the (only!) case where the list would be -		 * empty with time remaining. -		 */ -		if (!timeleft || list_empty(&mp->m_sync_list)) { -			if (!timeleft) -				timeleft = xfs_syncd_centisecs * -							msecs_to_jiffies(10); -			INIT_LIST_HEAD(&mp->m_sync_work.w_list); -			list_add_tail(&mp->m_sync_work.w_list, -					&mp->m_sync_list); -		} -		list_splice_init(&mp->m_sync_list, &tmp); -		spin_unlock(&mp->m_sync_lock); +	/* +	 * We can have inodes enter reclaim after we've shut down the syncd +	 * workqueue during unmount, so don't allow reclaim work to be queued +	 * during unmount. +	 */ +	if (!(mp->m_super->s_flags & MS_ACTIVE)) +		return; -		list_for_each_entry_safe(work, n, &tmp, w_list) { -			(*work->w_syncer)(mp, work->w_data); -			list_del(&work->w_list); -			if (work == &mp->m_sync_work) -				continue; -			if (work->w_completion) -				complete(work->w_completion); -			kmem_free(work); -		} +	rcu_read_lock(); +	if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) { +		queue_delayed_work(xfs_syncd_wq, &mp->m_reclaim_work, +			msecs_to_jiffies(xfs_syncd_centisecs / 6 * 10));  	} +	rcu_read_unlock(); +} -	return 0; +/* + * This is a fast pass over the inode cache to try to get reclaim moving on as + * many inodes as possible in a short period of time. It kicks itself every few + * seconds, as well as being kicked by the inode cache shrinker when memory + * goes low. It scans as quickly as possible avoiding locked inodes or those + * already being flushed, and once done schedules a future pass. + */ +STATIC void +xfs_reclaim_worker( +	struct work_struct *work) +{ +	struct xfs_mount *mp = container_of(to_delayed_work(work), +					struct xfs_mount, m_reclaim_work); + +	xfs_reclaim_inodes(mp, SYNC_TRYLOCK); +	xfs_syncd_queue_reclaim(mp); +} + +/* + * Flush delayed allocate data, attempting to free up reserved space + * from existing allocations.  At this point a new allocation attempt + * has failed with ENOSPC and we are in the process of scratching our + * heads, looking about for more room. + * + * Queue a new data flush if there isn't one already in progress and + * wait for completion of the flush. This means that we only ever have one + * inode flush in progress no matter how many ENOSPC events are occurring and + * so will prevent the system from bogging down due to every concurrent + * ENOSPC event scanning all the active inodes in the system for writeback. + */ +void +xfs_flush_inodes( +	struct xfs_inode	*ip) +{ +	struct xfs_mount	*mp = ip->i_mount; + +	queue_work(xfs_syncd_wq, &mp->m_flush_work); +	flush_work_sync(&mp->m_flush_work); +} + +STATIC void +xfs_flush_worker( +	struct work_struct *work) +{ +	struct xfs_mount *mp = container_of(work, +					struct xfs_mount, m_flush_work); + +	xfs_sync_data(mp, SYNC_TRYLOCK); +	xfs_sync_data(mp, SYNC_TRYLOCK | SYNC_WAIT);  }  int  xfs_syncd_init(  	struct xfs_mount	*mp)  { -	mp->m_sync_work.w_syncer = xfs_sync_worker; -	mp->m_sync_work.w_mount = mp; -	mp->m_sync_work.w_completion = NULL; -	mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd/%s", mp->m_fsname); -	if (IS_ERR(mp->m_sync_task)) -		return -PTR_ERR(mp->m_sync_task); +	INIT_WORK(&mp->m_flush_work, xfs_flush_worker); +	INIT_DELAYED_WORK(&mp->m_sync_work, xfs_sync_worker); +	INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker); + +	xfs_syncd_queue_sync(mp); +	xfs_syncd_queue_reclaim(mp); +  	return 0;  } @@ -583,7 +569,9 @@ void  xfs_syncd_stop(  	struct xfs_mount	*mp)  { -	kthread_stop(mp->m_sync_task); +	cancel_delayed_work_sync(&mp->m_sync_work); +	cancel_delayed_work_sync(&mp->m_reclaim_work); +	cancel_work_sync(&mp->m_flush_work);  }  void @@ -602,6 +590,10 @@ __xfs_inode_set_reclaim_tag(  				XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),  				XFS_ICI_RECLAIM_TAG);  		spin_unlock(&ip->i_mount->m_perag_lock); + +		/* schedule periodic background inode reclaim */ +		xfs_syncd_queue_reclaim(ip->i_mount); +  		trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno,  							-1, _RET_IP_);  	} @@ -762,8 +754,10 @@ xfs_reclaim_inode(  	struct xfs_perag	*pag,  	int			sync_mode)  { -	int	error = 0; +	int	error; +restart: +	error = 0;  	xfs_ilock(ip, XFS_ILOCK_EXCL);  	if (!xfs_iflock_nowait(ip)) {  		if (!(sync_mode & SYNC_WAIT)) @@ -789,9 +783,31 @@ xfs_reclaim_inode(  	if (xfs_inode_clean(ip))  		goto reclaim; -	/* Now we have an inode that needs flushing */ -	error = xfs_iflush(ip, sync_mode); +	/* +	 * Now we have an inode that needs flushing. +	 * +	 * We do a nonblocking flush here even if we are doing a SYNC_WAIT +	 * reclaim as we can deadlock with inode cluster removal. +	 * xfs_ifree_cluster() can lock the inode buffer before it locks the +	 * ip->i_lock, and we are doing the exact opposite here. As a result, +	 * doing a blocking xfs_itobp() to get the cluster buffer will result +	 * in an ABBA deadlock with xfs_ifree_cluster(). +	 * +	 * As xfs_ifree_cluser() must gather all inodes that are active in the +	 * cache to mark them stale, if we hit this case we don't actually want +	 * to do IO here - we want the inode marked stale so we can simply +	 * reclaim it. Hence if we get an EAGAIN error on a SYNC_WAIT flush, +	 * just unlock the inode, back off and try again. Hopefully the next +	 * pass through will see the stale flag set on the inode. +	 */ +	error = xfs_iflush(ip, SYNC_TRYLOCK | sync_mode);  	if (sync_mode & SYNC_WAIT) { +		if (error == EAGAIN) { +			xfs_iunlock(ip, XFS_ILOCK_EXCL); +			/* backoff longer than in xfs_ifree_cluster */ +			delay(2); +			goto restart; +		}  		xfs_iflock(ip);  		goto reclaim;  	} @@ -806,7 +822,7 @@ xfs_reclaim_inode(  	 * pass on the error.  	 */  	if (error && error != EAGAIN && !XFS_FORCED_SHUTDOWN(ip->i_mount)) { -		xfs_fs_cmn_err(CE_WARN, ip->i_mount, +		xfs_warn(ip->i_mount,  			"inode 0x%llx background reclaim flush failed with %d",  			(long long)ip->i_ino, error);  	} @@ -994,7 +1010,13 @@ xfs_reclaim_inodes(  }  /* - * Shrinker infrastructure. + * Inode cache shrinker. + * + * When called we make sure that there is a background (fast) inode reclaim in + * progress, while we will throttle the speed of reclaim via doiing synchronous + * reclaim of inodes. That means if we come across dirty inodes, we wait for + * them to be cleaned, which we hope will not be very long due to the + * background walker having already kicked the IO off on those dirty inodes.   */  static int  xfs_reclaim_inode_shrink( @@ -1009,10 +1031,15 @@ xfs_reclaim_inode_shrink(  	mp = container_of(shrink, struct xfs_mount, m_inode_shrink);  	if (nr_to_scan) { +		/* kick background reclaimer and push the AIL */ +		xfs_syncd_queue_reclaim(mp); +		xfs_ail_push_all(mp->m_ail); +  		if (!(gfp_mask & __GFP_FS))  			return -1; -		xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK, &nr_to_scan); +		xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT, +					&nr_to_scan);  		/* terminate if we don't exhaust the scan */  		if (nr_to_scan > 0)  			return -1; diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index 32ba6628290c..e3a6ad27415f 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h @@ -32,6 +32,8 @@ typedef struct xfs_sync_work {  #define SYNC_WAIT		0x0001	/* wait for i/o to complete */  #define SYNC_TRYLOCK		0x0002  /* only try to lock inodes */ +extern struct workqueue_struct	*xfs_syncd_wq;	/* sync workqueue */ +  int xfs_syncd_init(struct xfs_mount *mp);  void xfs_syncd_stop(struct xfs_mount *mp); diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c index ee3cee097e7e..ee2d2adaa438 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c @@ -37,7 +37,7 @@ xfs_stats_clear_proc_handler(  	ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);  	if (!ret && write && *valp) { -		printk("XFS Clearing xfsstats\n"); +		xfs_notice(NULL, "Clearing xfsstats");  		for_each_possible_cpu(c) {  			preempt_disable();  			/* save vn_active, it's a universal truth! */ diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index d22aa3103106..6fa214603819 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -544,9 +544,10 @@ xfs_qm_dqtobp(  	/*  	 * A simple sanity check in case we got a corrupted dquot...  	 */ -	if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES, +	error = xfs_qm_dqcheck(mp, ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,  			   flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN), -			   "dqtobp")) { +			   "dqtobp"); +	if (error) {  		if (!(flags & XFS_QMOPT_DQREPAIR)) {  			xfs_trans_brelse(tp, bp);  			return XFS_ERROR(EIO); @@ -599,7 +600,7 @@ xfs_qm_dqread(  	/*  	 * Reservation counters are defined as reservation plus current usage -	 * to avoid having to add everytime. +	 * to avoid having to add every time.  	 */  	dqp->q_res_bcount = be64_to_cpu(ddqp->d_bcount);  	dqp->q_res_icount = be64_to_cpu(ddqp->d_icount); @@ -827,7 +828,7 @@ xfs_qm_dqget(  	if (xfs_do_dqerror) {  		if ((xfs_dqerror_target == mp->m_ddev_targp) &&  		    (xfs_dqreq_num++ % xfs_dqerror_mod) == 0) { -			cmn_err(CE_DEBUG, "Returning error in dqget"); +			xfs_debug(mp, "Returning error in dqget");  			return (EIO);  		}  	} @@ -1207,8 +1208,9 @@ xfs_qm_dqflush(  	/*  	 * A simple sanity check in case we got a corrupted dquot..  	 */ -	if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), 0, -			   XFS_QMOPT_DOWARN, "dqflush (incore copy)")) { +	error = xfs_qm_dqcheck(mp, &dqp->q_core, be32_to_cpu(ddqp->d_id), 0, +			   XFS_QMOPT_DOWARN, "dqflush (incore copy)"); +	if (error) {  		xfs_buf_relse(bp);  		xfs_dqfunlock(dqp);  		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); @@ -1391,8 +1393,8 @@ xfs_qm_dqpurge(  		 */  		error = xfs_qm_dqflush(dqp, SYNC_WAIT);  		if (error) -			xfs_fs_cmn_err(CE_WARN, mp, -				"xfs_qm_dqpurge: dquot %p flush failed", dqp); +			xfs_warn(mp, "%s: dquot %p flush failed", +				__func__, dqp);  		xfs_dqflock(dqp);  	}  	ASSERT(atomic_read(&dqp->q_pincount) == 0); @@ -1425,36 +1427,38 @@ xfs_qm_dqpurge(  void  xfs_qm_dqprint(xfs_dquot_t *dqp)  { -	cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------"); -	cmn_err(CE_DEBUG, "---- dquotID =  %d", +	struct xfs_mount	*mp = dqp->q_mount; + +	xfs_debug(mp, "-----------KERNEL DQUOT----------------"); +	xfs_debug(mp, "---- dquotID =  %d",  		(int)be32_to_cpu(dqp->q_core.d_id)); -	cmn_err(CE_DEBUG, "---- type    =  %s", DQFLAGTO_TYPESTR(dqp)); -	cmn_err(CE_DEBUG, "---- fs      =  0x%p", dqp->q_mount); -	cmn_err(CE_DEBUG, "---- blkno   =  0x%x", (int) dqp->q_blkno); -	cmn_err(CE_DEBUG, "---- boffset =  0x%x", (int) dqp->q_bufoffset); -	cmn_err(CE_DEBUG, "---- blkhlimit =  %Lu (0x%x)", +	xfs_debug(mp, "---- type    =  %s", DQFLAGTO_TYPESTR(dqp)); +	xfs_debug(mp, "---- fs      =  0x%p", dqp->q_mount); +	xfs_debug(mp, "---- blkno   =  0x%x", (int) dqp->q_blkno); +	xfs_debug(mp, "---- boffset =  0x%x", (int) dqp->q_bufoffset); +	xfs_debug(mp, "---- blkhlimit =  %Lu (0x%x)",  		be64_to_cpu(dqp->q_core.d_blk_hardlimit),  		(int)be64_to_cpu(dqp->q_core.d_blk_hardlimit)); -	cmn_err(CE_DEBUG, "---- blkslimit =  %Lu (0x%x)", +	xfs_debug(mp, "---- blkslimit =  %Lu (0x%x)",  		be64_to_cpu(dqp->q_core.d_blk_softlimit),  		(int)be64_to_cpu(dqp->q_core.d_blk_softlimit)); -	cmn_err(CE_DEBUG, "---- inohlimit =  %Lu (0x%x)", +	xfs_debug(mp, "---- inohlimit =  %Lu (0x%x)",  		be64_to_cpu(dqp->q_core.d_ino_hardlimit),  		(int)be64_to_cpu(dqp->q_core.d_ino_hardlimit)); -	cmn_err(CE_DEBUG, "---- inoslimit =  %Lu (0x%x)", +	xfs_debug(mp, "---- inoslimit =  %Lu (0x%x)",  		be64_to_cpu(dqp->q_core.d_ino_softlimit),  		(int)be64_to_cpu(dqp->q_core.d_ino_softlimit)); -	cmn_err(CE_DEBUG, "---- bcount  =  %Lu (0x%x)", +	xfs_debug(mp, "---- bcount  =  %Lu (0x%x)",  		be64_to_cpu(dqp->q_core.d_bcount),  		(int)be64_to_cpu(dqp->q_core.d_bcount)); -	cmn_err(CE_DEBUG, "---- icount  =  %Lu (0x%x)", +	xfs_debug(mp, "---- icount  =  %Lu (0x%x)",  		be64_to_cpu(dqp->q_core.d_icount),  		(int)be64_to_cpu(dqp->q_core.d_icount)); -	cmn_err(CE_DEBUG, "---- btimer  =  %d", +	xfs_debug(mp, "---- btimer  =  %d",  		(int)be32_to_cpu(dqp->q_core.d_btimer)); -	cmn_err(CE_DEBUG, "---- itimer  =  %d", +	xfs_debug(mp, "---- itimer  =  %d",  		(int)be32_to_cpu(dqp->q_core.d_itimer)); -	cmn_err(CE_DEBUG, "---------------------------"); +	xfs_debug(mp, "---------------------------");  }  #endif diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 2a1f3dc10a02..9e0e2fa3f2c8 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c @@ -136,9 +136,8 @@ xfs_qm_dquot_logitem_push(  	 */  	error = xfs_qm_dqflush(dqp, 0);  	if (error) -		xfs_fs_cmn_err(CE_WARN, dqp->q_mount, -			"xfs_qm_dquot_logitem_push: push error %d on dqp %p", -			error, dqp); +		xfs_warn(dqp->q_mount, "%s: push error %d on dqp %p", +			__func__, error, dqp);  	xfs_dqunlock(dqp);  } diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 206a2815ced6..69228aa8605a 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -80,7 +80,7 @@ xfs_qm_dquot_list_print(  	int		i = 0;  	list_for_each_entry(dqp, &mp->m_quotainfo->qi_dqlist_lock, qi_mplist) { -		cmn_err(CE_DEBUG, "   %d. \"%d (%s)\"   " +		xfs_debug(mp, "   %d. \"%d (%s)\"   "  				  "bcnt = %lld, icnt = %lld, refs = %d",  			i++, be32_to_cpu(dqp->q_core.d_id),  			DQFLAGTO_TYPESTR(dqp), @@ -205,7 +205,7 @@ xfs_qm_destroy(  	list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) {  		xfs_dqlock(dqp);  #ifdef QUOTADEBUG -		cmn_err(CE_DEBUG, "FREELIST destroy 0x%p", dqp); +		xfs_debug(dqp->q_mount, "FREELIST destroy 0x%p", dqp);  #endif  		list_del_init(&dqp->q_freelist);  		xfs_Gqm->qm_dqfrlist_cnt--; @@ -341,9 +341,7 @@ xfs_qm_mount_quotas(  	 * quotas immediately.  	 */  	if (mp->m_sb.sb_rextents) { -		cmn_err(CE_NOTE, -			"Cannot turn on quotas for realtime filesystem %s", -			mp->m_fsname); +		xfs_notice(mp, "Cannot turn on quotas for realtime filesystem");  		mp->m_qflags = 0;  		goto write_changes;  	} @@ -402,14 +400,13 @@ xfs_qm_mount_quotas(  			 * off, but the on disk superblock doesn't know that !  			 */  			ASSERT(!(XFS_IS_QUOTA_RUNNING(mp))); -			xfs_fs_cmn_err(CE_ALERT, mp, -				"XFS mount_quotas: Superblock update failed!"); +			xfs_alert(mp, "%s: Superblock update failed!", +				__func__);  		}  	}  	if (error) { -		xfs_fs_cmn_err(CE_WARN, mp, -			"Failed to initialize disk quotas."); +		xfs_warn(mp, "Failed to initialize disk quotas.");  		return;  	} @@ -464,12 +461,10 @@ xfs_qm_dqflush_all(  	struct xfs_quotainfo	*q = mp->m_quotainfo;  	int			recl;  	struct xfs_dquot	*dqp; -	int			niters;  	int			error;  	if (!q)  		return 0; -	niters = 0;  again:  	mutex_lock(&q->qi_dqlist_lock);  	list_for_each_entry(dqp, &q->qi_dqlist, q_mplist) { @@ -1230,13 +1225,6 @@ xfs_qm_qino_alloc(  	}  	/* -	 * Keep an extra reference to this quota inode. This inode is -	 * locked exclusively and joined to the transaction already. -	 */ -	ASSERT(xfs_isilocked(*ip, XFS_ILOCK_EXCL)); -	IHOLD(*ip); - -	/*  	 * Make the changes in the superblock, and log those too.  	 * sbfields arg may contain fields other than *QUOTINO;  	 * VERSIONNUM for example. @@ -1264,7 +1252,7 @@ xfs_qm_qino_alloc(  	xfs_mod_sb(tp, sbfields);  	if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES))) { -		xfs_fs_cmn_err(CE_ALERT, mp, "XFS qino_alloc failed!"); +		xfs_alert(mp, "%s failed (error %d)!", __func__, error);  		return error;  	}  	return 0; @@ -1299,7 +1287,7 @@ xfs_qm_reset_dqcounts(  		 * output any warnings because it's perfectly possible to  		 * find uninitialised dquot blks. See comment in xfs_qm_dqcheck.  		 */ -		(void) xfs_qm_dqcheck(ddq, id+j, type, XFS_QMOPT_DQREPAIR, +		(void) xfs_qm_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR,  				      "xfs_quotacheck");  		ddq->d_bcount = 0;  		ddq->d_icount = 0; @@ -1324,14 +1312,9 @@ xfs_qm_dqiter_bufs(  {  	xfs_buf_t	*bp;  	int		error; -	int		notcommitted; -	int		incr;  	int		type;  	ASSERT(blkcnt > 0); -	notcommitted = 0; -	incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ? -		XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt;  	type = flags & XFS_QMOPT_UQUOTA ? XFS_DQ_USER :  		(flags & XFS_QMOPT_PQUOTA ? XFS_DQ_PROJ : XFS_DQ_GROUP);  	error = 0; @@ -1676,7 +1659,7 @@ xfs_qm_quotacheck(  	 */  	ASSERT(list_empty(&mp->m_quotainfo->qi_dqlist)); -	cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname); +	xfs_notice(mp, "Quotacheck needed: Please wait.");  	/*  	 * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset @@ -1754,9 +1737,9 @@ xfs_qm_quotacheck(   error_return:  	if (error) { -		cmn_err(CE_WARN, "XFS quotacheck %s: Unsuccessful (Error %d): " -			"Disabling quotas.", -			mp->m_fsname, error); +		xfs_warn(mp, +	"Quotacheck: Unsuccessful (Error %d): Disabling quotas.", +			error);  		/*  		 * We must turn off quotas.  		 */ @@ -1764,12 +1747,11 @@ xfs_qm_quotacheck(  		ASSERT(xfs_Gqm != NULL);  		xfs_qm_destroy_quotainfo(mp);  		if (xfs_mount_reset_sbqflags(mp)) { -			cmn_err(CE_WARN, "XFS quotacheck %s: " -				"Failed to reset quota flags.", mp->m_fsname); +			xfs_warn(mp, +				"Quotacheck: Failed to reset quota flags.");  		} -	} else { -		cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname); -	} +	} else +		xfs_notice(mp, "Quotacheck: Done.");  	return (error);  } @@ -1937,8 +1919,8 @@ again:  			 */  			error = xfs_qm_dqflush(dqp, 0);  			if (error) { -				xfs_fs_cmn_err(CE_WARN, mp, -			"xfs_qm_dqreclaim: dquot %p flush failed", dqp); +				xfs_warn(mp, "%s: dquot %p flush failed", +					__func__, dqp);  			}  			goto dqunlock;  		} @@ -2115,7 +2097,7 @@ xfs_qm_write_sb_changes(  	int		error;  #ifdef QUOTADEBUG -	cmn_err(CE_NOTE, "Writing superblock quota changes :%s", mp->m_fsname); +	xfs_notice(mp, "Writing superblock quota changes");  #endif  	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);  	if ((error = xfs_trans_reserve(tp, 0, diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h index c9446f1c726d..567b29b9f1b3 100644 --- a/fs/xfs/quota/xfs_qm.h +++ b/fs/xfs/quota/xfs_qm.h @@ -65,11 +65,6 @@ extern kmem_zone_t	*qm_dqtrxzone;   * block in the dquot/xqm code.   */  #define XFS_DQUOT_CLUSTER_SIZE_FSB	(xfs_filblks_t)1 -/* - * When doing a quotacheck, we log dquot clusters of this many FSBs at most - * in a single transaction. We don't want to ask for too huge a log reservation. - */ -#define XFS_QM_MAX_DQCLUSTER_LOGSZ	3  typedef xfs_dqhash_t	xfs_dqlist_t; diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index 45b5cb1788ab..a0a829addca9 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -119,8 +119,7 @@ xfs_qm_newmount(  	     (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||  	    (!gquotaondisk &&  XFS_IS_OQUOTA_ON(mp)))  &&  	    xfs_dev_is_read_only(mp, "changing quota state")) { -		cmn_err(CE_WARN, -			"XFS: please mount with%s%s%s%s.", +		xfs_warn(mp, "please mount with%s%s%s%s.",  			(!quotaondisk ? "out quota" : ""),  			(uquotaondisk ? " usrquota" : ""),  			(pquotaondisk ? " prjquota" : ""), @@ -135,7 +134,7 @@ xfs_qm_newmount(  		 */  		if (quotaondisk && !XFS_QM_NEED_QUOTACHECK(mp)) {  			/* -			 * If an error occured, qm_mount_quotas code +			 * If an error occurred, qm_mount_quotas code  			 * has already disabled quotas. So, just finish  			 * mounting, and get on with the boring life  			 * without disk quotas. diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index bdebc183223e..2dadb15d5ca9 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -41,12 +41,6 @@  #include "xfs_qm.h"  #include "xfs_trace.h" -#ifdef DEBUG -# define qdprintk(s, args...)	cmn_err(CE_DEBUG, s, ## args) -#else -# define qdprintk(s, args...)	do { } while (0) -#endif -  STATIC int	xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);  STATIC int	xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,  					uint); @@ -178,7 +172,7 @@ xfs_qm_scall_quotaoff(  	/*  	 * Next we make the changes in the quota flag in the mount struct.  	 * This isn't protected by a particular lock directly, because we -	 * don't want to take a mrlock everytime we depend on quotas being on. +	 * don't want to take a mrlock every time we depend on quotas being on.  	 */  	mp->m_qflags &= ~(flags); @@ -294,7 +288,8 @@ xfs_qm_scall_trunc_qfiles(  	int		error = 0, error2 = 0;  	if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { -		qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags); +		xfs_debug(mp, "%s: flags=%x m_qflags=%x\n", +			__func__, flags, mp->m_qflags);  		return XFS_ERROR(EINVAL);  	} @@ -318,20 +313,19 @@ xfs_qm_scall_quotaon(  {  	int		error;  	uint		qf; -	uint		accflags;  	__int64_t	sbflags;  	flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);  	/*  	 * Switching on quota accounting must be done at mount time.  	 */ -	accflags = flags & XFS_ALL_QUOTA_ACCT;  	flags &= ~(XFS_ALL_QUOTA_ACCT);  	sbflags = 0;  	if (flags == 0) { -		qdprintk("quotaon: zero flags, m_qflags=%x\n", mp->m_qflags); +		xfs_debug(mp, "%s: zero flags, m_qflags=%x\n", +			__func__, mp->m_qflags);  		return XFS_ERROR(EINVAL);  	} @@ -352,12 +346,13 @@ xfs_qm_scall_quotaon(  	    (flags & XFS_GQUOTA_ACCT) == 0 &&  	    (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&  	    (flags & XFS_OQUOTA_ENFD))) { -		qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n", -			flags, mp->m_sb.sb_qflags); +		xfs_debug(mp, +			"%s: Can't enforce without acct, flags=%x sbflags=%x\n", +			__func__, flags, mp->m_sb.sb_qflags);  		return XFS_ERROR(EINVAL);  	}  	/* -	 * If everything's upto-date incore, then don't waste time. +	 * If everything's up to-date incore, then don't waste time.  	 */  	if ((mp->m_qflags & flags) == flags)  		return XFS_ERROR(EEXIST); @@ -541,7 +536,7 @@ xfs_qm_scall_setqlim(  			q->qi_bsoftlimit = soft;  		}  	} else { -		qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft); +		xfs_debug(mp, "blkhard %Ld < blksoft %Ld\n", hard, soft);  	}  	hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?  		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) : @@ -557,7 +552,7 @@ xfs_qm_scall_setqlim(  			q->qi_rtbsoftlimit = soft;  		}  	} else { -		qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft); +		xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld\n", hard, soft);  	}  	hard = (newlim->d_fieldmask & FS_DQ_IHARD) ? @@ -574,7 +569,7 @@ xfs_qm_scall_setqlim(  			q->qi_isoftlimit = soft;  		}  	} else { -		qdprintk("ihard %Ld < isoft %Ld\n", hard, soft); +		xfs_debug(mp, "ihard %Ld < isoft %Ld\n", hard, soft);  	}  	/* @@ -939,10 +934,11 @@ struct mutex  qcheck_lock;  #define DQTEST_LIST_PRINT(l, NXT, title) \  { \  	  xfs_dqtest_t	*dqp; int i = 0;\ -	  cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \ +	  xfs_debug(NULL, "%s (#%d)", title, (int) (l)->qh_nelems); \  	  for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \  	       dqp = (xfs_dqtest_t *)dqp->NXT) { \ -		cmn_err(CE_DEBUG, "  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \ +		xfs_debug(dqp->q_mount,		\ +			"  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \  			 ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp),	     \  			 dqp->d_bcount, dqp->d_icount); } \  } @@ -966,16 +962,17 @@ xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp)  }  STATIC void  xfs_qm_dqtest_print( -	xfs_dqtest_t	*d) +	struct xfs_mount	*mp, +	struct dqtest		*d)  { -	cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------"); -	cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id); -	cmn_err(CE_DEBUG, "---- fs       = 0x%p", d->q_mount); -	cmn_err(CE_DEBUG, "---- bcount   = %Lu (0x%x)", +	xfs_debug(mp, "-----------DQTEST DQUOT----------------"); +	xfs_debug(mp, "---- dquot ID = %d", d->d_id); +	xfs_debug(mp, "---- fs       = 0x%p", d->q_mount); +	xfs_debug(mp, "---- bcount   = %Lu (0x%x)",  		d->d_bcount, (int)d->d_bcount); -	cmn_err(CE_DEBUG, "---- icount   = %Lu (0x%x)", +	xfs_debug(mp, "---- icount   = %Lu (0x%x)",  		d->d_icount, (int)d->d_icount); -	cmn_err(CE_DEBUG, "---------------------------"); +	xfs_debug(mp, "---------------------------");  }  STATIC void @@ -989,12 +986,14 @@ xfs_qm_dqtest_failed(  {  	qmtest_nfails++;  	if (error) -		cmn_err(CE_DEBUG, "quotacheck failed id=%d, err=%d\nreason: %s", -		       d->d_id, error, reason); +		xfs_debug(dqp->q_mount, +			"quotacheck failed id=%d, err=%d\nreason: %s", +			d->d_id, error, reason);  	else -		cmn_err(CE_DEBUG, "quotacheck failed id=%d (%s) [%d != %d]", -		       d->d_id, reason, (int)a, (int)b); -	xfs_qm_dqtest_print(d); +		xfs_debug(dqp->q_mount, +			"quotacheck failed id=%d (%s) [%d != %d]", +			d->d_id, reason, (int)a, (int)b); +	xfs_qm_dqtest_print(dqp->q_mount, d);  	if (dqp)  		xfs_qm_dqprint(dqp);  } @@ -1021,9 +1020,9 @@ xfs_dqtest_cmp2(  	    be64_to_cpu(dqp->q_core.d_bcount) >=  	    be64_to_cpu(dqp->q_core.d_blk_softlimit)) {  		if (!dqp->q_core.d_btimer && dqp->q_core.d_id) { -			cmn_err(CE_DEBUG, -				"%d [%s] [0x%p] BLK TIMER NOT STARTED", -				d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); +			xfs_debug(dqp->q_mount, +				"%d [%s] BLK TIMER NOT STARTED", +				d->d_id, DQFLAGTO_TYPESTR(d));  			err++;  		}  	} @@ -1031,16 +1030,16 @@ xfs_dqtest_cmp2(  	    be64_to_cpu(dqp->q_core.d_icount) >=  	    be64_to_cpu(dqp->q_core.d_ino_softlimit)) {  		if (!dqp->q_core.d_itimer && dqp->q_core.d_id) { -			cmn_err(CE_DEBUG, -				"%d [%s] [0x%p] INO TIMER NOT STARTED", -				d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); +			xfs_debug(dqp->q_mount, +				"%d [%s] INO TIMER NOT STARTED", +				d->d_id, DQFLAGTO_TYPESTR(d));  			err++;  		}  	}  #ifdef QUOTADEBUG  	if (!err) { -		cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked", -			d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); +		xfs_debug(dqp->q_mount, "%d [%s] qchecked", +			d->d_id, DQFLAGTO_TYPESTR(d));  	}  #endif  	return (err); @@ -1137,8 +1136,8 @@ xfs_qm_internalqcheck_adjust(  	if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) {  		*res = BULKSTAT_RV_NOTHING; -		qdprintk("internalqcheck: ino=%llu, uqino=%llu, gqino=%llu\n", -			(unsigned long long) ino, +		xfs_debug(mp, "%s: ino=%llu, uqino=%llu, gqino=%llu\n", +			__func__, (unsigned long long) ino,  			(unsigned long long) mp->m_sb.sb_uquotino,  			(unsigned long long) mp->m_sb.sb_gquotino);  		return XFS_ERROR(EINVAL); @@ -1223,12 +1222,12 @@ xfs_qm_internalqcheck(  				 xfs_qm_internalqcheck_adjust,  				 0, NULL, &done);  		if (error) { -			cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error); +			xfs_debug(mp, "Bulkstat returned error 0x%x", error);  			break;  		}  	} while (!done); -	cmn_err(CE_DEBUG, "Checking results against system dquots"); +	xfs_debug(mp, "Checking results against system dquots");  	for (i = 0; i < qmtest_hashmask; i++) {  		xfs_dqtest_t	*d, *n;  		xfs_dqhash_t	*h; @@ -1246,10 +1245,10 @@ xfs_qm_internalqcheck(  	}  	if (qmtest_nfails) { -		cmn_err(CE_DEBUG, "******** quotacheck failed  ********"); -		cmn_err(CE_DEBUG, "failures = %d", qmtest_nfails); +		xfs_debug(mp, "******** quotacheck failed  ********"); +		xfs_debug(mp, "failures = %d", qmtest_nfails);  	} else { -		cmn_err(CE_DEBUG, "******** quotacheck successful! ********"); +		xfs_debug(mp, "******** quotacheck successful! ********");  	}  	kmem_free(qmtest_udqtab);  	kmem_free(qmtest_gdqtab); diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 7de91d1b75c0..2a3648731331 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c @@ -643,8 +643,9 @@ xfs_trans_dqresv(  	     (XFS_IS_OQUOTA_ENFORCED(dqp->q_mount) &&  	      (XFS_QM_ISPDQ(dqp) || XFS_QM_ISGDQ(dqp))))) {  #ifdef QUOTADEBUG -		cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld" -			  " > hardlimit=%Ld?", nblks, *resbcountp, hardlimit); +		xfs_debug(mp, +			"BLK Res: nblks=%ld + resbcount=%Ld > hardlimit=%Ld?", +			nblks, *resbcountp, hardlimit);  #endif  		if (nblks > 0) {  			/* diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c deleted file mode 100644 index 0df88897ef84..000000000000 --- a/fs/xfs/support/debug.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA - */ -#include <xfs.h> -#include "debug.h" - -/* xfs_mount.h drags a lot of crap in, sorry.. */ -#include "xfs_sb.h" -#include "xfs_inum.h" -#include "xfs_ag.h" -#include "xfs_mount.h" -#include "xfs_error.h" - -void -cmn_err( -	const char	*lvl, -	const char	*fmt, -	...) -{ -	struct va_format vaf; -	va_list		args; - -	va_start(args, fmt); -	vaf.fmt = fmt; -	vaf.va = &args; - -	printk("%s%pV", lvl, &vaf); -	va_end(args); - -	BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0); -} - -void -xfs_fs_cmn_err( -	const char		*lvl, -	struct xfs_mount	*mp, -	const char		*fmt, -	...) -{ -	struct va_format	vaf; -	va_list			args; - -	va_start(args, fmt); -	vaf.fmt = fmt; -	vaf.va = &args; - -	printk("%sFilesystem %s: %pV", lvl, mp->m_fsname, &vaf); -	va_end(args); - -	BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0); -} - -/* All callers to xfs_cmn_err use CE_ALERT, so don't bother testing lvl */ -void -xfs_cmn_err( -	int			panic_tag, -	const char		*lvl, -	struct xfs_mount	*mp, -	const char		*fmt, -	...) -{ -	struct va_format	vaf; -	va_list			args; -	int			do_panic = 0; - -	if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) { -		printk(KERN_ALERT "XFS: Transforming an alert into a BUG."); -		do_panic = 1; -	} - -	va_start(args, fmt); -	vaf.fmt = fmt; -	vaf.va = &args; - -	printk(KERN_ALERT "Filesystem %s: %pV", mp->m_fsname, &vaf); -	va_end(args); - -	BUG_ON(do_panic); -} - -void -assfail(char *expr, char *file, int line) -{ -	printk(KERN_CRIT "Assertion failed: %s, file: %s, line: %d\n", expr, -	       file, line); -	BUG(); -} - -void -xfs_hex_dump(void *p, int length) -{ -	print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_ADDRESS, 16, 1, p, length, 1); -} diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h deleted file mode 100644 index 05699f67d475..000000000000 --- a/fs/xfs/support/debug.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA - */ -#ifndef	__XFS_SUPPORT_DEBUG_H__ -#define	__XFS_SUPPORT_DEBUG_H__ - -#include <stdarg.h> - -struct xfs_mount; - -#define CE_DEBUG        KERN_DEBUG -#define CE_CONT         KERN_INFO -#define CE_NOTE         KERN_NOTICE -#define CE_WARN         KERN_WARNING -#define CE_ALERT        KERN_ALERT -#define CE_PANIC        KERN_EMERG - -void cmn_err(const char *lvl, const char *fmt, ...) -		__attribute__ ((format (printf, 2, 3))); -void xfs_fs_cmn_err( const char *lvl, struct xfs_mount *mp, -		const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); -void xfs_cmn_err( int panic_tag, const char *lvl, struct xfs_mount *mp, -		const char *fmt, ...) __attribute__ ((format (printf, 4, 5))); - -extern void assfail(char *expr, char *f, int l); - -#define ASSERT_ALWAYS(expr)	\ -	(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) - -#ifndef DEBUG -#define ASSERT(expr)	((void)0) - -#ifndef STATIC -# define STATIC static noinline -#endif - -#else /* DEBUG */ - -#define ASSERT(expr)	\ -	(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) - -#ifndef STATIC -# define STATIC noinline -#endif - -#endif /* DEBUG */ -#endif  /* __XFS_SUPPORT_DEBUG_H__ */ diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index f3227984a9bf..27d64d752eab 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -147,10 +147,9 @@ xfs_alloc_get_rec(   */  STATIC void  xfs_alloc_compute_aligned( +	xfs_alloc_arg_t	*args,		/* allocation argument structure */  	xfs_agblock_t	foundbno,	/* starting block in found extent */  	xfs_extlen_t	foundlen,	/* length in found extent */ -	xfs_extlen_t	alignment,	/* alignment for allocation */ -	xfs_extlen_t	minlen,		/* minimum length for allocation */  	xfs_agblock_t	*resbno,	/* result block number */  	xfs_extlen_t	*reslen)	/* result length */  { @@ -158,8 +157,8 @@ xfs_alloc_compute_aligned(  	xfs_extlen_t	diff;  	xfs_extlen_t	len; -	if (alignment > 1 && foundlen >= minlen) { -		bno = roundup(foundbno, alignment); +	if (args->alignment > 1 && foundlen >= args->minlen) { +		bno = roundup(foundbno, args->alignment);  		diff = bno - foundbno;  		len = diff >= foundlen ? 0 : foundlen - diff;  	} else { @@ -464,6 +463,27 @@ xfs_alloc_read_agfl(  	return 0;  } +STATIC int +xfs_alloc_update_counters( +	struct xfs_trans	*tp, +	struct xfs_perag	*pag, +	struct xfs_buf		*agbp, +	long			len) +{ +	struct xfs_agf		*agf = XFS_BUF_TO_AGF(agbp); + +	pag->pagf_freeblks += len; +	be32_add_cpu(&agf->agf_freeblks, len); + +	xfs_trans_agblocks_delta(tp, len); +	if (unlikely(be32_to_cpu(agf->agf_freeblks) > +		     be32_to_cpu(agf->agf_length))) +		return EFSCORRUPTED; + +	xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); +	return 0; +} +  /*   * Allocation group level functions.   */ @@ -505,49 +525,44 @@ xfs_alloc_ag_vextent(  		ASSERT(0);  		/* NOTREACHED */  	} -	if (error) + +	if (error || args->agbno == NULLAGBLOCK)  		return error; -	/* -	 * If the allocation worked, need to change the agf structure -	 * (and log it), and the superblock. -	 */ -	if (args->agbno != NULLAGBLOCK) { -		xfs_agf_t	*agf;	/* allocation group freelist header */ -		long		slen = (long)args->len; -		ASSERT(args->len >= args->minlen && args->len <= args->maxlen); -		ASSERT(!(args->wasfromfl) || !args->isfl); -		ASSERT(args->agbno % args->alignment == 0); -		if (!(args->wasfromfl)) { - -			agf = XFS_BUF_TO_AGF(args->agbp); -			be32_add_cpu(&agf->agf_freeblks, -(args->len)); -			xfs_trans_agblocks_delta(args->tp, -						 -((long)(args->len))); -			args->pag->pagf_freeblks -= args->len; -			ASSERT(be32_to_cpu(agf->agf_freeblks) <= -				be32_to_cpu(agf->agf_length)); -			xfs_alloc_log_agf(args->tp, args->agbp, -						XFS_AGF_FREEBLKS); -			/* -			 * Search the busylist for these blocks and mark the -			 * transaction as synchronous if blocks are found. This -			 * avoids the need to block due to a synchronous log -			 * force to ensure correct ordering as the synchronous -			 * transaction will guarantee that for us. -			 */ -			if (xfs_alloc_busy_search(args->mp, args->agno, -						args->agbno, args->len)) -				xfs_trans_set_sync(args->tp); -		} -		if (!args->isfl) -			xfs_trans_mod_sb(args->tp, -				args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS : -					XFS_TRANS_SB_FDBLOCKS, -slen); -		XFS_STATS_INC(xs_allocx); -		XFS_STATS_ADD(xs_allocb, args->len); +	ASSERT(args->len >= args->minlen); +	ASSERT(args->len <= args->maxlen); +	ASSERT(!args->wasfromfl || !args->isfl); +	ASSERT(args->agbno % args->alignment == 0); + +	if (!args->wasfromfl) { +		error = xfs_alloc_update_counters(args->tp, args->pag, +						  args->agbp, +						  -((long)(args->len))); +		if (error) +			return error; + +		/* +		 * Search the busylist for these blocks and mark the +		 * transaction as synchronous if blocks are found. This +		 * avoids the need to block due to a synchronous log +		 * force to ensure correct ordering as the synchronous +		 * transaction will guarantee that for us. +		 */ +		if (xfs_alloc_busy_search(args->mp, args->agno, +					args->agbno, args->len)) +			xfs_trans_set_sync(args->tp);  	} -	return 0; + +	if (!args->isfl) { +		xfs_trans_mod_sb(args->tp, args->wasdel ? +				 XFS_TRANS_SB_RES_FDBLOCKS : +				 XFS_TRANS_SB_FDBLOCKS, +				 -((long)(args->len))); +	} + +	XFS_STATS_INC(xs_allocx); +	XFS_STATS_ADD(xs_allocb, args->len); +	return error;  }  /* @@ -693,8 +708,7 @@ xfs_alloc_find_best_extent(  		if (error)  			goto error0;  		XFS_WANT_CORRUPTED_GOTO(i == 1, error0); -		xfs_alloc_compute_aligned(*sbno, *slen, args->alignment, -					  args->minlen, &bno, slena); +		xfs_alloc_compute_aligned(args, *sbno, *slen, &bno, slena);  		/*  		 * The good extent is closer than this one. @@ -866,8 +880,8 @@ xfs_alloc_ag_vextent_near(  			if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i)))  				goto error0;  			XFS_WANT_CORRUPTED_GOTO(i == 1, error0); -			xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment, -					args->minlen, <bnoa, <lena); +			xfs_alloc_compute_aligned(args, ltbno, ltlen, +						  <bnoa, <lena);  			if (ltlena < args->minlen)  				continue;  			args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); @@ -987,8 +1001,8 @@ xfs_alloc_ag_vextent_near(  			if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i)))  				goto error0;  			XFS_WANT_CORRUPTED_GOTO(i == 1, error0); -			xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment, -					args->minlen, <bnoa, <lena); +			xfs_alloc_compute_aligned(args, ltbno, ltlen, +						  <bnoa, <lena);  			if (ltlena >= args->minlen)  				break;  			if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) @@ -1003,8 +1017,8 @@ xfs_alloc_ag_vextent_near(  			if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i)))  				goto error0;  			XFS_WANT_CORRUPTED_GOTO(i == 1, error0); -			xfs_alloc_compute_aligned(gtbno, gtlen, args->alignment, -					args->minlen, >bnoa, >lena); +			xfs_alloc_compute_aligned(args, gtbno, gtlen, +						  >bnoa, >lena);  			if (gtlena >= args->minlen)  				break;  			if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) @@ -1183,8 +1197,7 @@ xfs_alloc_ag_vextent_size(  	 * once aligned; if not, we search left for something better.  	 * This can't happen in the second case above.  	 */ -	xfs_alloc_compute_aligned(fbno, flen, args->alignment, args->minlen, -		&rbno, &rlen); +	xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen);  	rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);  	XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||  			(rlen <= flen && rbno + rlen <= fbno + flen), error0); @@ -1209,8 +1222,8 @@ xfs_alloc_ag_vextent_size(  			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);  			if (flen < bestrlen)  				break; -			xfs_alloc_compute_aligned(fbno, flen, args->alignment, -				args->minlen, &rbno, &rlen); +			xfs_alloc_compute_aligned(args, fbno, flen, +						  &rbno, &rlen);  			rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);  			XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||  				(rlen <= flen && rbno + rlen <= fbno + flen), @@ -1388,6 +1401,7 @@ xfs_free_ag_extent(  	xfs_mount_t	*mp;		/* mount point struct for filesystem */  	xfs_agblock_t	nbno;		/* new starting block of freespace */  	xfs_extlen_t	nlen;		/* new length of freespace */ +	xfs_perag_t	*pag;		/* per allocation group data */  	mp = tp->t_mountp;  	/* @@ -1586,30 +1600,20 @@ xfs_free_ag_extent(  	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);  	xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);  	cnt_cur = NULL; +  	/*  	 * Update the freespace totals in the ag and superblock.  	 */ -	{ -		xfs_agf_t	*agf; -		xfs_perag_t	*pag;		/* per allocation group data */ - -		pag = xfs_perag_get(mp, agno); -		pag->pagf_freeblks += len; -		xfs_perag_put(pag); - -		agf = XFS_BUF_TO_AGF(agbp); -		be32_add_cpu(&agf->agf_freeblks, len); -		xfs_trans_agblocks_delta(tp, len); -		XFS_WANT_CORRUPTED_GOTO( -			be32_to_cpu(agf->agf_freeblks) <= -			be32_to_cpu(agf->agf_length), -			error0); -		xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); -		if (!isfl) -			xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); -		XFS_STATS_INC(xs_freex); -		XFS_STATS_ADD(xs_freeb, len); -	} +	pag = xfs_perag_get(mp, agno); +	error = xfs_alloc_update_counters(tp, pag, agbp, len); +	xfs_perag_put(pag); +	if (error) +		goto error0; + +	if (!isfl) +		xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); +	XFS_STATS_INC(xs_freex); +	XFS_STATS_ADD(xs_freeb, len);  	trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); @@ -2391,17 +2395,33 @@ xfs_free_extent(  	memset(&args, 0, sizeof(xfs_alloc_arg_t));  	args.tp = tp;  	args.mp = tp->t_mountp; + +	/* +	 * validate that the block number is legal - the enables us to detect +	 * and handle a silent filesystem corruption rather than crashing. +	 */  	args.agno = XFS_FSB_TO_AGNO(args.mp, bno); -	ASSERT(args.agno < args.mp->m_sb.sb_agcount); +	if (args.agno >= args.mp->m_sb.sb_agcount) +		return EFSCORRUPTED; +  	args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); +	if (args.agbno >= args.mp->m_sb.sb_agblocks) +		return EFSCORRUPTED; +  	args.pag = xfs_perag_get(args.mp, args.agno); -	if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) +	ASSERT(args.pag); + +	error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); +	if (error)  		goto error0; -#ifdef DEBUG -	ASSERT(args.agbp != NULL); -	ASSERT((args.agbno + len) <= -		be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)); -#endif + +	/* validate the extent size is legal now we have the agf locked */ +	if (args.agbno + len > +			be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) { +		error = EFSCORRUPTED; +		goto error0; +	} +  	error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);  error0:  	xfs_perag_put(args.pag); diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index dc3afd7739ff..fa00788de2f5 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2365,6 +2365,13 @@ xfs_bmap_rtalloc(  	 */  	if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)  		ralen = MAXEXTLEN / mp->m_sb.sb_rextsize; + +	/* +	 * Lock out other modifications to the RT bitmap inode. +	 */ +	xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); +	xfs_trans_ijoin_ref(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL); +  	/*  	 * If it's an allocation to an empty file at offset 0,  	 * pick an extent that will space things out in the rt area. @@ -3519,7 +3526,7 @@ xfs_bmap_search_extents(  	if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&  		     !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) { -		xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount, +		xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO,  				"Access to block zero in inode %llu "  				"start_block: %llx start_off: %llx "  				"blkcnt: %llx extent-state: %x lastx: %x\n", @@ -4193,12 +4200,11 @@ xfs_bmap_read_extents(  		num_recs = xfs_btree_get_numrecs(block);  		if (unlikely(i + num_recs > room)) {  			ASSERT(i + num_recs <= room); -			xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, +			xfs_warn(ip->i_mount,  				"corrupt dinode %Lu, (btree extents).",  				(unsigned long long) ip->i_ino); -			XFS_ERROR_REPORT("xfs_bmap_read_extents(1)", -					 XFS_ERRLEVEL_LOW, -					ip->i_mount); +			XFS_CORRUPTION_ERROR("xfs_bmap_read_extents(1)", +				XFS_ERRLEVEL_LOW, ip->i_mount, block);  			goto error0;  		}  		XFS_WANT_CORRUPTED_GOTO( @@ -5772,7 +5778,7 @@ xfs_check_block(  			else  				thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr);  			if (*thispa == *pp) { -				cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld", +				xfs_warn(mp, "%s: thispa(%d) == pp(%d) %Ld",  					__func__, j, i,  					(unsigned long long)be64_to_cpu(*thispa));  				panic("%s: ptrs are equal in node\n", @@ -5937,11 +5943,11 @@ xfs_bmap_check_leaf_extents(  	return;  error0: -	cmn_err(CE_WARN, "%s: at error0", __func__); +	xfs_warn(mp, "%s: at error0", __func__);  	if (bp_release)  		xfs_trans_brelse(NULL, bp);  error_norelse: -	cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents", +	xfs_warn(mp, "%s: BAD after btree leaves for %d extents",  		__func__, i);  	panic("%s: CORRUPTED BTREE OR SOMETHING", __func__);  	return; @@ -6144,7 +6150,7 @@ xfs_bmap_punch_delalloc_range(  		if (error) {  			/* something screwed, just bail */  			if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { -				xfs_fs_cmn_err(CE_ALERT, ip->i_mount, +				xfs_alert(ip->i_mount,  			"Failed delalloc mapping lookup ino %lld fsb %lld.",  						ip->i_ino, start_fsb);  			} diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 6f8c21ce0d6d..7b7e005e3dcc 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -130,10 +130,12 @@ xfs_buf_item_log_check(  	orig = bip->bli_orig;  	buffer = XFS_BUF_PTR(bp);  	for (x = 0; x < XFS_BUF_COUNT(bp); x++) { -		if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) -			cmn_err(CE_PANIC, -	"xfs_buf_item_log_check bip %x buffer %x orig %x index %d", -				bip, bp, orig, x); +		if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) { +			xfs_emerg(bp->b_mount, +				"%s: bip %x buffer %x orig %x index %d", +				__func__, bip, bp, orig, x); +			ASSERT(0); +		}  	}  }  #else @@ -983,15 +985,14 @@ xfs_buf_iodone_callbacks(  	if (XFS_BUF_TARGET(bp) != lasttarg ||  	    time_after(jiffies, (lasttime + 5*HZ))) {  		lasttime = jiffies; -		cmn_err(CE_ALERT, "Device %s, XFS metadata write error" -				" block 0x%llx in %s", +		xfs_alert(mp, "Device %s: metadata write error block 0x%llx",  			XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), -		      (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname); +		      (__uint64_t)XFS_BUF_ADDR(bp));  	}  	lasttarg = XFS_BUF_TARGET(bp);  	/* -	 * If the write was asynchronous then noone will be looking for the +	 * If the write was asynchronous then no one will be looking for the  	 * error.  Clear the error state and write the buffer out again.  	 *  	 * During sync or umount we'll write all pending buffers again diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 1c00bedb3175..6102ac6d1dff 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -1995,13 +1995,12 @@ xfs_da_do_buf(  		error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED);  		if (unlikely(error == EFSCORRUPTED)) {  			if (xfs_error_level >= XFS_ERRLEVEL_LOW) { -				cmn_err(CE_ALERT, "xfs_da_do_buf: bno %lld\n", -					(long long)bno); -				cmn_err(CE_ALERT, "dir: inode %lld\n", +				xfs_alert(mp, "%s: bno %lld dir: inode %lld", +					__func__, (long long)bno,  					(long long)dp->i_ino);  				for (i = 0; i < nmap; i++) { -					cmn_err(CE_ALERT, -						"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d\n", +					xfs_alert(mp, +"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d",  						i,  						(long long)mapp[i].br_startoff,  						(long long)mapp[i].br_startblock, diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index e60490bc00a6..be628677c288 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -270,9 +270,9 @@ xfs_swap_extents(  	/* check inode formats now that data is flushed */  	error = xfs_swap_extents_check_format(ip, tip);  	if (error) { -		xfs_fs_cmn_err(CE_NOTE, mp, +		xfs_notice(mp,  		    "%s: inode 0x%llx format is incompatible for exchanging.", -				__FILE__, ip->i_ino); +				__func__, ip->i_ino);  		goto out_unlock;  	} diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index a1321bc7f192..dba7a71cedf3 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -159,7 +159,7 @@ xfs_dir_ino_validate(  		XFS_AGINO_TO_INO(mp, agno, agino) == ino;  	if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,  			XFS_RANDOM_DIR_INO_VALIDATE))) { -		xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx", +		xfs_warn(mp, "Invalid inode number 0x%Lx",  				(unsigned long long) ino);  		XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);  		return XFS_ERROR(EFSCORRUPTED); diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index f9a0864b696a..a0aab7d3294f 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -899,10 +899,9 @@ xfs_dir2_leafn_rebalance(  	if(blk2->index < 0) {  		state->inleaf = 1;  		blk2->index = 0; -		cmn_err(CE_ALERT, -			"xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting original leaf: " -			"blk1->index %d\n", -			blk1->index); +		xfs_alert(args->dp->i_mount, +	"%s: picked the wrong leaf? reverting original leaf: blk1->index %d\n", +			__func__, blk1->index);  	}  } @@ -1641,26 +1640,22 @@ xfs_dir2_node_addname_int(  			}  			if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) { -				cmn_err(CE_ALERT, -					"xfs_dir2_node_addname_int: dir ino " -					"%llu needed freesp block %lld for\n" -					"  data block %lld, got %lld\n" -					"  ifbno %llu lastfbno %d\n", -					(unsigned long long)dp->i_ino, +				xfs_alert(mp, +			"%s: dir ino " "%llu needed freesp block %lld for\n" +			"  data block %lld, got %lld ifbno %llu lastfbno %d", +					__func__, (unsigned long long)dp->i_ino,  					(long long)xfs_dir2_db_to_fdb(mp, dbno),  					(long long)dbno, (long long)fbno,  					(unsigned long long)ifbno, lastfbno);  				if (fblk) { -					cmn_err(CE_ALERT, -						" fblk 0x%p blkno %llu " -						"index %d magic 0x%x\n", +					xfs_alert(mp, +				" fblk 0x%p blkno %llu index %d magic 0x%x",  						fblk,  						(unsigned long long)fblk->blkno,  						fblk->index,  						fblk->magic);  				} else { -					cmn_err(CE_ALERT, -						" ... fblk is NULL\n"); +					xfs_alert(mp, " ... fblk is NULL");  				}  				XFS_ERROR_REPORT("xfs_dir2_node_addname_int",  						 XFS_ERRLEVEL_LOW, mp); diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 4c7db74a05f7..39f06336b99d 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -48,7 +48,7 @@ xfs_error_trap(int e)  			break;  		if (e != xfs_etrap[i])  			continue; -		cmn_err(CE_NOTE, "xfs_error_trap: error %d", e); +		xfs_notice(NULL, "%s: error %d", __func__, e);  		BUG();  		break;  	} @@ -74,7 +74,7 @@ xfs_error_test(int error_tag, int *fsidp, char *expression,  	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {  		if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) { -			cmn_err(CE_WARN, +			xfs_warn(NULL,  	"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",  				expression, file, line, xfs_etest_fsname[i]);  			return 1; @@ -95,14 +95,14 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)  	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {  		if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) { -			cmn_err(CE_WARN, "XFS error tag #%d on", error_tag); +			xfs_warn(mp, "error tag #%d on", error_tag);  			return 0;  		}  	}  	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {  		if (xfs_etest[i] == 0) { -			cmn_err(CE_WARN, "Turned on XFS error tag #%d", +			xfs_warn(mp, "Turned on XFS error tag #%d",  				error_tag);  			xfs_etest[i] = error_tag;  			xfs_etest_fsid[i] = fsid; @@ -114,7 +114,7 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)  		}  	} -	cmn_err(CE_WARN, "error tag overflow, too many turned on"); +	xfs_warn(mp, "error tag overflow, too many turned on");  	return 1;  } @@ -133,7 +133,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud)  		if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&  		     xfs_etest[i] != 0) {  			cleared = 1; -			cmn_err(CE_WARN, "Clearing XFS error tag #%d", +			xfs_warn(mp, "Clearing XFS error tag #%d",  				xfs_etest[i]);  			xfs_etest[i] = 0;  			xfs_etest_fsid[i] = 0LL; @@ -144,9 +144,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud)  	}  	if (loud || cleared) -		cmn_err(CE_WARN, -			"Cleared all XFS error tags for filesystem \"%s\"", -			mp->m_fsname); +		xfs_warn(mp, "Cleared all XFS error tags for filesystem");  	return 0;  } @@ -162,9 +160,8 @@ xfs_error_report(  	inst_t			*ra)  {  	if (level <= xfs_error_level) { -		xfs_cmn_err(XFS_PTAG_ERROR_REPORT, -			    CE_ALERT, mp, -		"XFS internal error %s at line %d of file %s.  Caller 0x%p\n", +		xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT, +		"Internal error %s at line %d of file %s.  Caller 0x%p\n",  			    tag, linenum, filename, ra);  		xfs_stack_trace(); @@ -184,4 +181,5 @@ xfs_corruption_error(  	if (level <= xfs_error_level)  		xfs_hex_dump(p, 16);  	xfs_error_report(tag, level, mp, filename, linenum, ra); +	xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");  } diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 10dce5475f02..079a367f44ee 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -145,10 +145,8 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud);  #endif /* DEBUG */  /* - * XFS panic tags -- allow a call to xfs_cmn_err() be turned into - *			a panic by setting xfs_panic_mask in a - *			sysctl.  update xfs_max[XFS_PARAM] if - *			more are added. + * XFS panic tags -- allow a call to xfs_alert_tag() be turned into + *			a panic by setting xfs_panic_mask in a sysctl.   */  #define		XFS_NO_PTAG			0  #define		XFS_PTAG_IFLUSH			0x00000001 @@ -160,17 +158,4 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud);  #define		XFS_PTAG_SHUTDOWN_LOGERROR	0x00000040  #define		XFS_PTAG_FSBLOCK_ZERO		0x00000080 -struct xfs_mount; - -extern void xfs_hex_dump(void *p, int length); - -#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \ -	xfs_fs_cmn_err(level, mp, fmt "  Unmount and run xfs_repair.", ## args) - -#define xfs_fs_mount_cmn_err(f, fmt, args...) \ -	do { \ -		if (!(f & XFS_MFSI_QUIET)) 	\ -			cmn_err(CE_WARN, "XFS: " fmt, ## args); \ -	} while (0) -  #endif	/* __XFS_ERROR_H__ */ diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index cec89dd5d7d2..9153d2c77caf 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -53,6 +53,9 @@ xfs_fs_geometry(  	xfs_fsop_geom_t		*geo,  	int			new_version)  { + +	memset(geo, 0, sizeof(*geo)); +  	geo->blocksize = mp->m_sb.sb_blocksize;  	geo->rtextsize = mp->m_sb.sb_rextsize;  	geo->agblocks = mp->m_sb.sb_agblocks; @@ -382,8 +385,8 @@ xfs_growfs_data_private(  				  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),  				  XFS_FSS_TO_BB(mp, 1), 0, &bp);  		if (error) { -			xfs_fs_cmn_err(CE_WARN, mp, -			"error %d reading secondary superblock for ag %d", +			xfs_warn(mp, +		"error %d reading secondary superblock for ag %d",  				error, agno);  			break;  		} @@ -396,7 +399,7 @@ xfs_growfs_data_private(  		if (!(error = xfs_bwrite(mp, bp))) {  			continue;  		} else { -			xfs_fs_cmn_err(CE_WARN, mp, +			xfs_warn(mp,  		"write error %d updating secondary superblock for ag %d",  				error, agno);  			break; /* no point in continuing */ diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 0626a32c3447..84ebeec16642 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -1055,28 +1055,23 @@ xfs_difree(  	 */  	agno = XFS_INO_TO_AGNO(mp, inode);  	if (agno >= mp->m_sb.sb_agcount)  { -		cmn_err(CE_WARN, -			"xfs_difree: agno >= mp->m_sb.sb_agcount (%d >= %d) on %s.  Returning EINVAL.", -			agno, mp->m_sb.sb_agcount, mp->m_fsname); +		xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).", +			__func__, agno, mp->m_sb.sb_agcount);  		ASSERT(0);  		return XFS_ERROR(EINVAL);  	}  	agino = XFS_INO_TO_AGINO(mp, inode);  	if (inode != XFS_AGINO_TO_INO(mp, agno, agino))  { -		cmn_err(CE_WARN, -			"xfs_difree: inode != XFS_AGINO_TO_INO() " -			"(%llu != %llu) on %s.  Returning EINVAL.", -			(unsigned long long)inode, -			(unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino), -			mp->m_fsname); +		xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).", +			__func__, (unsigned long long)inode, +			(unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino));  		ASSERT(0);  		return XFS_ERROR(EINVAL);  	}  	agbno = XFS_AGINO_TO_AGBNO(mp, agino);  	if (agbno >= mp->m_sb.sb_agblocks)  { -		cmn_err(CE_WARN, -			"xfs_difree: agbno >= mp->m_sb.sb_agblocks (%d >= %d) on %s.  Returning EINVAL.", -			agbno, mp->m_sb.sb_agblocks, mp->m_fsname); +		xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).", +			__func__, agbno, mp->m_sb.sb_agblocks);  		ASSERT(0);  		return XFS_ERROR(EINVAL);  	} @@ -1085,9 +1080,8 @@ xfs_difree(  	 */  	error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);  	if (error) { -		cmn_err(CE_WARN, -			"xfs_difree: xfs_ialloc_read_agi() returned an error %d on %s.  Returning error.", -			error, mp->m_fsname); +		xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.", +			__func__, error);  		return error;  	}  	agi = XFS_BUF_TO_AGI(agbp); @@ -1106,17 +1100,15 @@ xfs_difree(  	 * Look for the entry describing this inode.  	 */  	if ((error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i))) { -		cmn_err(CE_WARN, -			"xfs_difree: xfs_inobt_lookup returned()  an error %d on %s.  Returning error.", -			error, mp->m_fsname); +		xfs_warn(mp, "%s: xfs_inobt_lookup() returned error %d.", +			__func__, error);  		goto error0;  	}  	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);  	error = xfs_inobt_get_rec(cur, &rec, &i);  	if (error) { -		cmn_err(CE_WARN, -			"xfs_difree: xfs_inobt_get_rec()  returned an error %d on %s.  Returning error.", -			error, mp->m_fsname); +		xfs_warn(mp, "%s: xfs_inobt_get_rec() returned error %d.", +			__func__, error);  		goto error0;  	}  	XFS_WANT_CORRUPTED_GOTO(i == 1, error0); @@ -1157,8 +1149,8 @@ xfs_difree(  		xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1));  		if ((error = xfs_btree_delete(cur, &i))) { -			cmn_err(CE_WARN, "xfs_difree: xfs_btree_delete returned an error %d on %s.\n", -				error, mp->m_fsname); +			xfs_warn(mp, "%s: xfs_btree_delete returned error %d.", +				__func__, error);  			goto error0;  		} @@ -1170,9 +1162,8 @@ xfs_difree(  		error = xfs_inobt_update(cur, &rec);  		if (error) { -			cmn_err(CE_WARN, -	"xfs_difree: xfs_inobt_update returned an error %d on %s.", -				error, mp->m_fsname); +			xfs_warn(mp, "%s: xfs_inobt_update returned error %d.", +				__func__, error);  			goto error0;  		} @@ -1218,10 +1209,9 @@ xfs_imap_lookup(  	error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);  	if (error) { -		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " -				"xfs_ialloc_read_agi() returned " -				"error %d, agno %d", -				error, agno); +		xfs_alert(mp, +			"%s: xfs_ialloc_read_agi() returned error %d, agno %d", +			__func__, error, agno);  		return error;  	} @@ -1299,24 +1289,21 @@ xfs_imap(  		if (flags & XFS_IGET_UNTRUSTED)  			return XFS_ERROR(EINVAL);  		if (agno >= mp->m_sb.sb_agcount) { -			xfs_fs_cmn_err(CE_ALERT, mp, -					"xfs_imap: agno (%d) >= " -					"mp->m_sb.sb_agcount (%d)", -					agno,  mp->m_sb.sb_agcount); +			xfs_alert(mp, +				"%s: agno (%d) >= mp->m_sb.sb_agcount (%d)", +				__func__, agno, mp->m_sb.sb_agcount);  		}  		if (agbno >= mp->m_sb.sb_agblocks) { -			xfs_fs_cmn_err(CE_ALERT, mp, -					"xfs_imap: agbno (0x%llx) >= " -					"mp->m_sb.sb_agblocks (0x%lx)", -					(unsigned long long) agbno, -					(unsigned long) mp->m_sb.sb_agblocks); +			xfs_alert(mp, +		"%s: agbno (0x%llx) >= mp->m_sb.sb_agblocks (0x%lx)", +				__func__, (unsigned long long)agbno, +				(unsigned long)mp->m_sb.sb_agblocks);  		}  		if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) { -			xfs_fs_cmn_err(CE_ALERT, mp, -					"xfs_imap: ino (0x%llx) != " -					"XFS_AGINO_TO_INO(mp, agno, agino) " -					"(0x%llx)", -					ino, XFS_AGINO_TO_INO(mp, agno, agino)); +			xfs_alert(mp, +		"%s: ino (0x%llx) != XFS_AGINO_TO_INO() (0x%llx)", +				__func__, ino, +				XFS_AGINO_TO_INO(mp, agno, agino));  		}  		xfs_stack_trace();  #endif /* DEBUG */ @@ -1388,10 +1375,9 @@ out_map:  	 */  	if ((imap->im_blkno + imap->im_len) >  	    XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) { -		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " -			"(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > " -			" XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)", -			(unsigned long long) imap->im_blkno, +		xfs_alert(mp, +	"%s: (im_blkno (0x%llx) + im_len (0x%llx)) > sb_dblocks (0x%llx)", +			__func__, (unsigned long long) imap->im_blkno,  			(unsigned long long) imap->im_len,  			XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));  		return XFS_ERROR(EINVAL); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index be7cf625421f..a37480a6e023 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -110,8 +110,8 @@ xfs_inobp_check(  		dip = (xfs_dinode_t *)xfs_buf_offset(bp,  					i * mp->m_sb.sb_inodesize);  		if (!dip->di_next_unlinked)  { -			xfs_fs_cmn_err(CE_ALERT, mp, -				"Detected a bogus zero next_unlinked field in incore inode buffer 0x%p.  About to pop an ASSERT.", +			xfs_alert(mp, +	"Detected bogus zero next_unlinked field in incore inode buffer 0x%p.",  				bp);  			ASSERT(dip->di_next_unlinked);  		} @@ -142,10 +142,9 @@ xfs_imap_to_bp(  				   (int)imap->im_len, buf_flags, &bp);  	if (error) {  		if (error != EAGAIN) { -			cmn_err(CE_WARN, -				"xfs_imap_to_bp: xfs_trans_read_buf()returned " -				"an error %d on %s.  Returning error.", -				error, mp->m_fsname); +			xfs_warn(mp, +				"%s: xfs_trans_read_buf() returned error %d.", +				__func__, error);  		} else {  			ASSERT(buf_flags & XBF_TRYLOCK);  		} @@ -180,12 +179,11 @@ xfs_imap_to_bp(  			XFS_CORRUPTION_ERROR("xfs_imap_to_bp",  						XFS_ERRLEVEL_HIGH, mp, dip);  #ifdef DEBUG -			cmn_err(CE_PANIC, -					"Device %s - bad inode magic/vsn " -					"daddr %lld #%d (magic=%x)", -				XFS_BUFTARG_NAME(mp->m_ddev_targp), +			xfs_emerg(mp, +				"bad inode magic/vsn daddr %lld #%d (magic=%x)",  				(unsigned long long)imap->im_blkno, i,  				be16_to_cpu(dip->di_magic)); +			ASSERT(0);  #endif  			xfs_trans_brelse(tp, bp);  			return XFS_ERROR(EFSCORRUPTED); @@ -317,7 +315,7 @@ xfs_iformat(  	if (unlikely(be32_to_cpu(dip->di_nextents) +  		     be16_to_cpu(dip->di_anextents) >  		     be64_to_cpu(dip->di_nblocks))) { -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, +		xfs_warn(ip->i_mount,  			"corrupt dinode %Lu, extent total = %d, nblocks = %Lu.",  			(unsigned long long)ip->i_ino,  			(int)(be32_to_cpu(dip->di_nextents) + @@ -330,8 +328,7 @@ xfs_iformat(  	}  	if (unlikely(dip->di_forkoff > ip->i_mount->m_sb.sb_inodesize)) { -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, -			"corrupt dinode %Lu, forkoff = 0x%x.", +		xfs_warn(ip->i_mount, "corrupt dinode %Lu, forkoff = 0x%x.",  			(unsigned long long)ip->i_ino,  			dip->di_forkoff);  		XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW, @@ -341,7 +338,7 @@ xfs_iformat(  	if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) &&  		     !ip->i_mount->m_rtdev_targp)) { -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, +		xfs_warn(ip->i_mount,  			"corrupt dinode %Lu, has realtime flag set.",  			ip->i_ino);  		XFS_CORRUPTION_ERROR("xfs_iformat(realtime)", @@ -373,9 +370,8 @@ xfs_iformat(  			 * no local regular files yet  			 */  			if (unlikely((be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFREG)) { -				xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, -					"corrupt inode %Lu " -					"(local format for regular file).", +				xfs_warn(ip->i_mount, +			"corrupt inode %Lu (local format for regular file).",  					(unsigned long long) ip->i_ino);  				XFS_CORRUPTION_ERROR("xfs_iformat(4)",  						     XFS_ERRLEVEL_LOW, @@ -385,9 +381,8 @@ xfs_iformat(  			di_size = be64_to_cpu(dip->di_size);  			if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) { -				xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, -					"corrupt inode %Lu " -					"(bad size %Ld for local inode).", +				xfs_warn(ip->i_mount, +			"corrupt inode %Lu (bad size %Ld for local inode).",  					(unsigned long long) ip->i_ino,  					(long long) di_size);  				XFS_CORRUPTION_ERROR("xfs_iformat(5)", @@ -431,9 +426,8 @@ xfs_iformat(  		size = be16_to_cpu(atp->hdr.totsize);  		if (unlikely(size < sizeof(struct xfs_attr_sf_hdr))) { -			xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, -				"corrupt inode %Lu " -				"(bad attr fork size %Ld).", +			xfs_warn(ip->i_mount, +				"corrupt inode %Lu (bad attr fork size %Ld).",  				(unsigned long long) ip->i_ino,  				(long long) size);  			XFS_CORRUPTION_ERROR("xfs_iformat(8)", @@ -488,9 +482,8 @@ xfs_iformat_local(  	 * kmem_alloc() or memcpy() below.  	 */  	if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, -			"corrupt inode %Lu " -			"(bad size %d for local fork, size = %d).", +		xfs_warn(ip->i_mount, +	"corrupt inode %Lu (bad size %d for local fork, size = %d).",  			(unsigned long long) ip->i_ino, size,  			XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));  		XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW, @@ -547,8 +540,7 @@ xfs_iformat_extents(  	 * kmem_alloc() or memcpy() below.  	 */  	if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, -			"corrupt inode %Lu ((a)extents = %d).", +		xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).",  			(unsigned long long) ip->i_ino, nex);  		XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW,  				     ip->i_mount, dip); @@ -623,11 +615,10 @@ xfs_iformat_btree(  	    || XFS_BMDR_SPACE_CALC(nrecs) >  			XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)  	    || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) { -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, -			"corrupt inode %Lu (btree).", +		xfs_warn(ip->i_mount, "corrupt inode %Lu (btree).",  			(unsigned long long) ip->i_ino); -		XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW, -				 ip->i_mount); +		XFS_CORRUPTION_ERROR("xfs_iformat_btree", XFS_ERRLEVEL_LOW, +				 ip->i_mount, dip);  		return XFS_ERROR(EFSCORRUPTED);  	} @@ -813,11 +804,9 @@ xfs_iread(  	 */  	if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC) {  #ifdef DEBUG -		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " -				"dip->di_magic (0x%x) != " -				"XFS_DINODE_MAGIC (0x%x)", -				be16_to_cpu(dip->di_magic), -				XFS_DINODE_MAGIC); +		xfs_alert(mp, +			"%s: dip->di_magic (0x%x) != XFS_DINODE_MAGIC (0x%x)", +			__func__, be16_to_cpu(dip->di_magic), XFS_DINODE_MAGIC);  #endif /* DEBUG */  		error = XFS_ERROR(EINVAL);  		goto out_brelse; @@ -835,9 +824,8 @@ xfs_iread(  		error = xfs_iformat(ip, dip);  		if (error)  {  #ifdef DEBUG -			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " -					"xfs_iformat() returned error %d", -					error); +			xfs_alert(mp, "%s: xfs_iformat() returned error %d", +				__func__, error);  #endif /* DEBUG */  			goto out_brelse;  		} @@ -1016,8 +1004,8 @@ xfs_ialloc(  	 * This is because we're setting fields here we need  	 * to prevent others from looking at until we're done.  	 */ -	error = xfs_trans_iget(tp->t_mountp, tp, ino, -				XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip); +	error = xfs_iget(tp->t_mountp, tp, ino, XFS_IGET_CREATE, +			 XFS_ILOCK_EXCL, &ip);  	if (error)  		return error;  	ASSERT(ip != NULL); @@ -1166,6 +1154,7 @@ xfs_ialloc(  	/*  	 * Log the new values stuffed into the inode.  	 */ +	xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);  	xfs_trans_log_inode(tp, ip, flags);  	/* now that we have an i_mode we can setup inode ops and unlock */ @@ -1820,9 +1809,8 @@ xfs_iunlink_remove(  		 */  		error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK);  		if (error) { -			cmn_err(CE_WARN, -				"xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.", -				error, mp->m_fsname); +			xfs_warn(mp, "%s: xfs_itobp() returned error %d.", +				__func__, error);  			return error;  		}  		next_agino = be32_to_cpu(dip->di_next_unlinked); @@ -1867,9 +1855,9 @@ xfs_iunlink_remove(  			error = xfs_inotobp(mp, tp, next_ino, &last_dip,  					    &last_ibp, &last_offset, 0);  			if (error) { -				cmn_err(CE_WARN, -			"xfs_iunlink_remove: xfs_inotobp()  returned an error %d on %s.  Returning error.", -					error, mp->m_fsname); +				xfs_warn(mp, +					"%s: xfs_inotobp() returned error %d.", +					__func__, error);  				return error;  			}  			next_agino = be32_to_cpu(last_dip->di_next_unlinked); @@ -1882,9 +1870,8 @@ xfs_iunlink_remove(  		 */  		error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK);  		if (error) { -			cmn_err(CE_WARN, -				"xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.", -				error, mp->m_fsname); +			xfs_warn(mp, "%s: xfs_itobp(2) returned error %d.", +				__func__, error);  			return error;  		}  		next_agino = be32_to_cpu(dip->di_next_unlinked); @@ -2802,7 +2789,7 @@ xfs_iflush(  	/*  	 * We can't flush the inode until it is unpinned, so wait for it if we -	 * are allowed to block.  We know noone new can pin it, because we are +	 * are allowed to block.  We know no one new can pin it, because we are  	 * holding the inode lock shared and you need to hold it exclusively to  	 * pin the inode.  	 * @@ -2848,7 +2835,7 @@ xfs_iflush(  	 * Get the buffer containing the on-disk inode.  	 */  	error = xfs_itobp(mp, NULL, ip, &dip, &bp, -				(flags & SYNC_WAIT) ? XBF_LOCK : XBF_TRYLOCK); +				(flags & SYNC_TRYLOCK) ? XBF_TRYLOCK : XBF_LOCK);  	if (error || !bp) {  		xfs_ifunlock(ip);  		return error; @@ -2939,16 +2926,16 @@ xfs_iflush_int(  	if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC,  			       mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) { -		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, -		    "xfs_iflush: Bad inode %Lu magic number 0x%x, ptr 0x%p", -			ip->i_ino, be16_to_cpu(dip->di_magic), dip); +		xfs_alert_tag(mp, XFS_PTAG_IFLUSH, +			"%s: Bad inode %Lu magic number 0x%x, ptr 0x%p", +			__func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip);  		goto corrupt_out;  	}  	if (XFS_TEST_ERROR(ip->i_d.di_magic != XFS_DINODE_MAGIC,  				mp, XFS_ERRTAG_IFLUSH_2, XFS_RANDOM_IFLUSH_2)) { -		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, -			"xfs_iflush: Bad inode %Lu, ptr 0x%p, magic number 0x%x", -			ip->i_ino, ip, ip->i_d.di_magic); +		xfs_alert_tag(mp, XFS_PTAG_IFLUSH, +			"%s: Bad inode %Lu, ptr 0x%p, magic number 0x%x", +			__func__, ip->i_ino, ip, ip->i_d.di_magic);  		goto corrupt_out;  	}  	if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) { @@ -2956,9 +2943,9 @@ xfs_iflush_int(  		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&  		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),  		    mp, XFS_ERRTAG_IFLUSH_3, XFS_RANDOM_IFLUSH_3)) { -			xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, -				"xfs_iflush: Bad regular inode %Lu, ptr 0x%p", -				ip->i_ino, ip); +			xfs_alert_tag(mp, XFS_PTAG_IFLUSH, +				"%s: Bad regular inode %Lu, ptr 0x%p", +				__func__, ip->i_ino, ip);  			goto corrupt_out;  		}  	} else if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { @@ -2967,28 +2954,28 @@ xfs_iflush_int(  		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&  		    (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL),  		    mp, XFS_ERRTAG_IFLUSH_4, XFS_RANDOM_IFLUSH_4)) { -			xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, -				"xfs_iflush: Bad directory inode %Lu, ptr 0x%p", -				ip->i_ino, ip); +			xfs_alert_tag(mp, XFS_PTAG_IFLUSH, +				"%s: Bad directory inode %Lu, ptr 0x%p", +				__func__, ip->i_ino, ip);  			goto corrupt_out;  		}  	}  	if (XFS_TEST_ERROR(ip->i_d.di_nextents + ip->i_d.di_anextents >  				ip->i_d.di_nblocks, mp, XFS_ERRTAG_IFLUSH_5,  				XFS_RANDOM_IFLUSH_5)) { -		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, -			"xfs_iflush: detected corrupt incore inode %Lu, total extents = %d, nblocks = %Ld, ptr 0x%p", -			ip->i_ino, +		xfs_alert_tag(mp, XFS_PTAG_IFLUSH, +			"%s: detected corrupt incore inode %Lu, " +			"total extents = %d, nblocks = %Ld, ptr 0x%p", +			__func__, ip->i_ino,  			ip->i_d.di_nextents + ip->i_d.di_anextents, -			ip->i_d.di_nblocks, -			ip); +			ip->i_d.di_nblocks, ip);  		goto corrupt_out;  	}  	if (XFS_TEST_ERROR(ip->i_d.di_forkoff > mp->m_sb.sb_inodesize,  				mp, XFS_ERRTAG_IFLUSH_6, XFS_RANDOM_IFLUSH_6)) { -		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, -			"xfs_iflush: bad inode %Lu, forkoff 0x%x, ptr 0x%p", -			ip->i_ino, ip->i_d.di_forkoff, ip); +		xfs_alert_tag(mp, XFS_PTAG_IFLUSH, +			"%s: bad inode %Lu, forkoff 0x%x, ptr 0x%p", +			__func__, ip->i_ino, ip->i_d.di_forkoff, ip);  		goto corrupt_out;  	}  	/* diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 5c95fa8ec11d..ff4e2a30227d 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -111,7 +111,7 @@ struct xfs_imap {   * Generally, we do not want to hold the i_rlock while holding the   * i_ilock. Hierarchy is i_iolock followed by i_rlock.   * - * xfs_iptr_t contains all the inode fields upto and including the + * xfs_iptr_t contains all the inode fields up to and including the   * i_mnext and i_mprev fields, it is used as a marker in the inode   * chain off the mount structure by xfs_sync calls.   */ @@ -336,7 +336,7 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags)  /*   * Project quota id helpers (previously projid was 16bit only - * and using two 16bit values to hold new 32bit projid was choosen + * and using two 16bit values to hold new 32bit projid was chosen   * to retain compatibility with "old" filesystems).   */  static inline prid_t @@ -409,28 +409,35 @@ static inline void xfs_ifunlock(xfs_inode_t *ip)  /*   * Flags for lockdep annotations.   * - * XFS_I[O]LOCK_PARENT - for operations that require locking two inodes - * (ie directory operations that require locking a directory inode and - * an entry inode).  The first inode gets locked with this flag so it - * gets a lockdep subclass of 1 and the second lock will have a lockdep - * subclass of 0. + * XFS_LOCK_PARENT - for directory operations that require locking a + * parent directory inode and a child entry inode.  The parent gets locked + * with this flag so it gets a lockdep subclass of 1 and the child entry + * lock will have a lockdep subclass of 0. + * + * XFS_LOCK_RTBITMAP/XFS_LOCK_RTSUM - the realtime device bitmap and summary + * inodes do not participate in the normal lock order, and thus have their + * own subclasses.   *   * XFS_LOCK_INUMORDER - for locking several inodes at the some time   * with xfs_lock_inodes().  This flag is used as the starting subclass   * and each subsequent lock acquired will increment the subclass by one. - * So the first lock acquired will have a lockdep subclass of 2, the - * second lock will have a lockdep subclass of 3, and so on. It is + * So the first lock acquired will have a lockdep subclass of 4, the + * second lock will have a lockdep subclass of 5, and so on. It is   * the responsibility of the class builder to shift this to the correct   * portion of the lock_mode lockdep mask.   */  #define XFS_LOCK_PARENT		1 -#define XFS_LOCK_INUMORDER	2 +#define XFS_LOCK_RTBITMAP	2 +#define XFS_LOCK_RTSUM		3 +#define XFS_LOCK_INUMORDER	4  #define XFS_IOLOCK_SHIFT	16  #define	XFS_IOLOCK_PARENT	(XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT)  #define XFS_ILOCK_SHIFT		24  #define	XFS_ILOCK_PARENT	(XFS_LOCK_PARENT << XFS_ILOCK_SHIFT) +#define	XFS_ILOCK_RTBITMAP	(XFS_LOCK_RTBITMAP << XFS_ILOCK_SHIFT) +#define	XFS_ILOCK_RTSUM		(XFS_LOCK_RTSUM << XFS_ILOCK_SHIFT)  #define XFS_IOLOCK_DEP_MASK	0x00ff0000  #define XFS_ILOCK_DEP_MASK	0xff000000 diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index fd4f398bd6f1..576fdfe81d60 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -198,6 +198,41 @@ xfs_inode_item_size(  }  /* + * xfs_inode_item_format_extents - convert in-core extents to on-disk form + * + * For either the data or attr fork in extent format, we need to endian convert + * the in-core extent as we place them into the on-disk inode. In this case, we + * need to do this conversion before we write the extents into the log. Because + * we don't have the disk inode to write into here, we allocate a buffer and + * format the extents into it via xfs_iextents_copy(). We free the buffer in + * the unlock routine after the copy for the log has been made. + * + * In the case of the data fork, the in-core and on-disk fork sizes can be + * different due to delayed allocation extents. We only log on-disk extents + * here, so always use the physical fork size to determine the size of the + * buffer we need to allocate. + */ +STATIC void +xfs_inode_item_format_extents( +	struct xfs_inode	*ip, +	struct xfs_log_iovec	*vecp, +	int			whichfork, +	int			type) +{ +	xfs_bmbt_rec_t		*ext_buffer; + +	ext_buffer = kmem_alloc(XFS_IFORK_SIZE(ip, whichfork), KM_SLEEP); +	if (whichfork == XFS_DATA_FORK) +		ip->i_itemp->ili_extents_buf = ext_buffer; +	else +		ip->i_itemp->ili_aextents_buf = ext_buffer; + +	vecp->i_addr = ext_buffer; +	vecp->i_len = xfs_iextents_copy(ip, ext_buffer, whichfork); +	vecp->i_type = type; +} + +/*   * This is called to fill in the vector of log iovecs for the   * given inode log item.  It fills the first item with an inode   * log format structure, the second with the on-disk inode structure, @@ -213,7 +248,6 @@ xfs_inode_item_format(  	struct xfs_inode	*ip = iip->ili_inode;  	uint			nvecs;  	size_t			data_bytes; -	xfs_bmbt_rec_t		*ext_buffer;  	xfs_mount_t		*mp;  	vecp->i_addr = &iip->ili_format; @@ -320,22 +354,8 @@ xfs_inode_item_format(  			} else  #endif  			{ -				/* -				 * There are delayed allocation extents -				 * in the inode, or we need to convert -				 * the extents to on disk format. -				 * Use xfs_iextents_copy() -				 * to copy only the real extents into -				 * a separate buffer.  We'll free the -				 * buffer in the unlock routine. -				 */ -				ext_buffer = kmem_alloc(ip->i_df.if_bytes, -					KM_SLEEP); -				iip->ili_extents_buf = ext_buffer; -				vecp->i_addr = ext_buffer; -				vecp->i_len = xfs_iextents_copy(ip, ext_buffer, -						XFS_DATA_FORK); -				vecp->i_type = XLOG_REG_TYPE_IEXT; +				xfs_inode_item_format_extents(ip, vecp, +					XFS_DATA_FORK, XLOG_REG_TYPE_IEXT);  			}  			ASSERT(vecp->i_len <= ip->i_df.if_bytes);  			iip->ili_format.ilf_dsize = vecp->i_len; @@ -445,19 +465,12 @@ xfs_inode_item_format(  			 */  			vecp->i_addr = ip->i_afp->if_u1.if_extents;  			vecp->i_len = ip->i_afp->if_bytes; +			vecp->i_type = XLOG_REG_TYPE_IATTR_EXT;  #else  			ASSERT(iip->ili_aextents_buf == NULL); -			/* -			 * Need to endian flip before logging -			 */ -			ext_buffer = kmem_alloc(ip->i_afp->if_bytes, -				KM_SLEEP); -			iip->ili_aextents_buf = ext_buffer; -			vecp->i_addr = ext_buffer; -			vecp->i_len = xfs_iextents_copy(ip, ext_buffer, -					XFS_ATTR_FORK); +			xfs_inode_item_format_extents(ip, vecp, +					XFS_ATTR_FORK, XLOG_REG_TYPE_IATTR_EXT);  #endif -			vecp->i_type = XLOG_REG_TYPE_IATTR_EXT;  			iip->ili_format.ilf_asize = vecp->i_len;  			vecp++;  			nvecs++; @@ -760,11 +773,11 @@ xfs_inode_item_push(  	 * Push the inode to it's backing buffer. This will not remove the  	 * inode from the AIL - a further push will be required to trigger a  	 * buffer push. However, this allows all the dirty inodes to be pushed -	 * to the buffer before it is pushed to disk. THe buffer IO completion -	 * will pull th einode from the AIL, mark it clean and unlock the flush +	 * to the buffer before it is pushed to disk. The buffer IO completion +	 * will pull the inode from the AIL, mark it clean and unlock the flush  	 * lock.  	 */ -	(void) xfs_iflush(ip, 0); +	(void) xfs_iflush(ip, SYNC_TRYLOCK);  	xfs_iunlock(ip, XFS_ILOCK_SHARED);  } diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 8a0f044750c3..091d82b94c4d 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -101,11 +101,11 @@ xfs_iomap_eof_align_last_fsb(  }  STATIC int -xfs_cmn_err_fsblock_zero( +xfs_alert_fsblock_zero(  	xfs_inode_t	*ip,  	xfs_bmbt_irec_t	*imap)  { -	xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount, +	xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO,  			"Access to block zero in inode %llu "  			"start_block: %llx start_off: %llx "  			"blkcnt: %llx extent-state: %x\n", @@ -246,7 +246,7 @@ xfs_iomap_write_direct(  	}  	if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) { -		error = xfs_cmn_err_fsblock_zero(ip, imap); +		error = xfs_alert_fsblock_zero(ip, imap);  		goto error_out;  	} @@ -464,7 +464,7 @@ retry:  	}  	if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip))) -		return xfs_cmn_err_fsblock_zero(ip, &imap[0]); +		return xfs_alert_fsblock_zero(ip, &imap[0]);  	*ret_imap = imap[0];  	return 0; @@ -614,7 +614,7 @@ xfs_iomap_write_allocate(  		 * covers at least part of the callers request  		 */  		if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) -			return xfs_cmn_err_fsblock_zero(ip, imap); +			return xfs_alert_fsblock_zero(ip, imap);  		if ((offset_fsb >= imap->br_startoff) &&  		    (offset_fsb < (imap->br_startoff + @@ -724,7 +724,7 @@ xfs_iomap_write_unwritten(  			return XFS_ERROR(error);  		if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip))) -			return xfs_cmn_err_fsblock_zero(ip, &imap); +			return xfs_alert_fsblock_zero(ip, &imap);  		if ((numblks_fsb = imap.br_blockcount) == 0) {  			/* diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index dc1882adaf54..751e94fe1f77 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -204,7 +204,6 @@ xfs_bulkstat(  	xfs_agi_t		*agi;	/* agi header data */  	xfs_agino_t		agino;	/* inode # in allocation group */  	xfs_agnumber_t		agno;	/* allocation group number */ -	xfs_daddr_t		bno;	/* inode cluster start daddr */  	int			chunkidx; /* current index into inode chunk */  	int			clustidx; /* current index into inode cluster */  	xfs_btree_cur_t		*cur;	/* btree cursor for ialloc btree */ @@ -463,7 +462,6 @@ xfs_bulkstat(  						 mp->m_sb.sb_inopblog);  				}  				ino = XFS_AGINO_TO_INO(mp, agno, agino); -				bno = XFS_AGB_TO_DADDR(mp, agno, agbno);  				/*  				 * Skip if this inode is free.  				 */ diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index ae6fef1ff563..b612ce4520ae 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -374,11 +374,10 @@ xfs_log_mount(  	int		error;  	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) -		cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname); +		xfs_notice(mp, "Mounting Filesystem");  	else { -		cmn_err(CE_NOTE, -			"Mounting filesystem \"%s\" in no-recovery mode.  Filesystem will be inconsistent.", -			mp->m_fsname); +		xfs_notice(mp, +"Mounting filesystem in no-recovery mode.  Filesystem will be inconsistent.");  		ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);  	} @@ -393,7 +392,7 @@ xfs_log_mount(  	 */  	error = xfs_trans_ail_init(mp);  	if (error) { -		cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error); +		xfs_warn(mp, "AIL initialisation failed: error %d", error);  		goto out_free_log;  	}  	mp->m_log->l_ailp = mp->m_ail; @@ -413,7 +412,8 @@ xfs_log_mount(  		if (readonly)  			mp->m_flags |= XFS_MOUNT_RDONLY;  		if (error) { -			cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error); +			xfs_warn(mp, "log mount/recovery failed: error %d", +				error);  			goto out_destroy_ail;  		}  	} @@ -542,10 +542,8 @@ xfs_log_unmount_write(xfs_mount_t *mp)  			 */  		} -		if (error) { -			xfs_fs_cmn_err(CE_ALERT, mp, -				"xfs_log_unmount: unmount record failed"); -		} +		if (error) +			xfs_alert(mp, "%s: unmount record failed", __func__);  		spin_lock(&log->l_icloglock); @@ -763,7 +761,7 @@ xfs_log_need_covered(xfs_mount_t *mp)  		break;  	case XLOG_STATE_COVER_NEED:  	case XLOG_STATE_COVER_NEED2: -		if (!xfs_trans_ail_tail(log->l_ailp) && +		if (!xfs_ail_min_lsn(log->l_ailp) &&  		    xlog_iclogs_empty(log)) {  			if (log->l_covered_state == XLOG_STATE_COVER_NEED)  				log->l_covered_state = XLOG_STATE_COVER_DONE; @@ -803,7 +801,7 @@ xlog_assign_tail_lsn(  	xfs_lsn_t		tail_lsn;  	struct log		*log = mp->m_log; -	tail_lsn = xfs_trans_ail_tail(mp->m_ail); +	tail_lsn = xfs_ail_min_lsn(mp->m_ail);  	if (!tail_lsn)  		tail_lsn = atomic64_read(&log->l_last_sync_lsn); @@ -852,7 +850,7 @@ xlog_space_left(  		 * In this case we just want to return the size of the  		 * log as the amount of space left.  		 */ -		xfs_fs_cmn_err(CE_ALERT, log->l_mp, +		xfs_alert(log->l_mp,  			"xlog_space_left: head behind tail\n"  			"  tail_cycle = %d, tail_bytes = %d\n"  			"  GH   cycle = %d, GH   bytes = %d", @@ -1001,7 +999,7 @@ xlog_alloc_log(xfs_mount_t	*mp,  	log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL);  	if (!log) { -		xlog_warn("XFS: Log allocation failed: No memory!"); +		xfs_warn(mp, "Log allocation failed: No memory!");  		goto out;  	} @@ -1029,24 +1027,24 @@ xlog_alloc_log(xfs_mount_t	*mp,  	if (xfs_sb_version_hassector(&mp->m_sb)) {  	        log2_size = mp->m_sb.sb_logsectlog;  		if (log2_size < BBSHIFT) { -			xlog_warn("XFS: Log sector size too small " -				"(0x%x < 0x%x)", log2_size, BBSHIFT); +			xfs_warn(mp, "Log sector size too small (0x%x < 0x%x)", +				log2_size, BBSHIFT);  			goto out_free_log;  		}  	        log2_size -= BBSHIFT;  		if (log2_size > mp->m_sectbb_log) { -			xlog_warn("XFS: Log sector size too large " -				"(0x%x > 0x%x)", log2_size, mp->m_sectbb_log); +			xfs_warn(mp, "Log sector size too large (0x%x > 0x%x)", +				log2_size, mp->m_sectbb_log);  			goto out_free_log;  		}  		/* for larger sector sizes, must have v2 or external log */  		if (log2_size && log->l_logBBstart > 0 &&  			    !xfs_sb_version_haslogv2(&mp->m_sb)) { - -			xlog_warn("XFS: log sector size (0x%x) invalid " -				  "for configuration.", log2_size); +			xfs_warn(mp, +		"log sector size (0x%x) invalid for configuration.", +				log2_size);  			goto out_free_log;  		}  	} @@ -1241,7 +1239,7 @@ xlog_grant_push_ail(  	 * the filesystem is shutting down.  	 */  	if (!XLOG_FORCED_SHUTDOWN(log)) -		xfs_trans_ail_push(log->l_ailp, threshold_lsn); +		xfs_ail_push(log->l_ailp, threshold_lsn);  }  /* @@ -1563,38 +1561,36 @@ xlog_print_tic_res(  	    "SWAPEXT"  	}; -	xfs_fs_cmn_err(CE_WARN, mp, -			"xfs_log_write: reservation summary:\n" -			"  trans type  = %s (%u)\n" -			"  unit res    = %d bytes\n" -			"  current res = %d bytes\n" -			"  total reg   = %u bytes (o/flow = %u bytes)\n" -			"  ophdrs      = %u (ophdr space = %u bytes)\n" -			"  ophdr + reg = %u bytes\n" -			"  num regions = %u\n", -			((ticket->t_trans_type <= 0 || -			  ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ? -			  "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]), -			ticket->t_trans_type, -			ticket->t_unit_res, -			ticket->t_curr_res, -			ticket->t_res_arr_sum, ticket->t_res_o_flow, -			ticket->t_res_num_ophdrs, ophdr_spc, -			ticket->t_res_arr_sum +  -			ticket->t_res_o_flow + ophdr_spc, -			ticket->t_res_num); +	xfs_warn(mp, +		"xfs_log_write: reservation summary:\n" +		"  trans type  = %s (%u)\n" +		"  unit res    = %d bytes\n" +		"  current res = %d bytes\n" +		"  total reg   = %u bytes (o/flow = %u bytes)\n" +		"  ophdrs      = %u (ophdr space = %u bytes)\n" +		"  ophdr + reg = %u bytes\n" +		"  num regions = %u\n", +		((ticket->t_trans_type <= 0 || +		  ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ? +		  "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]), +		ticket->t_trans_type, +		ticket->t_unit_res, +		ticket->t_curr_res, +		ticket->t_res_arr_sum, ticket->t_res_o_flow, +		ticket->t_res_num_ophdrs, ophdr_spc, +		ticket->t_res_arr_sum + +		ticket->t_res_o_flow + ophdr_spc, +		ticket->t_res_num);  	for (i = 0; i < ticket->t_res_num; i++) { -		uint r_type = ticket->t_res_arr[i].r_type;  -		cmn_err(CE_WARN, -			    "region[%u]: %s - %u bytes\n", -			    i,  +		uint r_type = ticket->t_res_arr[i].r_type; +		xfs_warn(mp, "region[%u]: %s - %u bytes\n", i,  			    ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ?  			    "bad-rtype" : res_type_str[r_type-1]),  			    ticket->t_res_arr[i].r_len);  	} -	xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, +	xfs_alert_tag(mp, XFS_PTAG_LOGRES,  		"xfs_log_write: reservation ran out. Need to up reservation");  	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);  } @@ -1682,7 +1678,7 @@ xlog_write_setup_ophdr(  	case XFS_LOG:  		break;  	default: -		xfs_fs_cmn_err(CE_WARN, log->l_mp, +		xfs_warn(log->l_mp,  			"Bad XFS transaction clientid 0x%x in ticket 0x%p",  			ophdr->oh_clientid, ticket);  		return NULL; @@ -2264,7 +2260,7 @@ xlog_state_do_callback(  		if (repeats > 5000) {  			flushcnt += repeats;  			repeats = 0; -			xfs_fs_cmn_err(CE_WARN, log->l_mp, +			xfs_warn(log->l_mp,  				"%s: possible infinite loop (%d iterations)",  				__func__, flushcnt);  		} @@ -3052,10 +3048,8 @@ xfs_log_force(  	int	error;  	error = _xfs_log_force(mp, flags, NULL); -	if (error) { -		xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: " -			"error %d returned.", error); -	} +	if (error) +		xfs_warn(mp, "%s: error %d returned.", __func__, error);  }  /* @@ -3204,10 +3198,8 @@ xfs_log_force_lsn(  	int	error;  	error = _xfs_log_force_lsn(mp, lsn, flags, NULL); -	if (error) { -		xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: " -			"error %d returned.", error); -	} +	if (error) +		xfs_warn(mp, "%s: error %d returned.", __func__, error);  }  /* @@ -3412,9 +3404,20 @@ xlog_verify_dest_ptr(  	}  	if (!good_ptr) -		xlog_panic("xlog_verify_dest_ptr: invalid ptr"); +		xfs_emerg(log->l_mp, "%s: invalid ptr", __func__);  } +/* + * Check to make sure the grant write head didn't just over lap the tail.  If + * the cycles are the same, we can't be overlapping.  Otherwise, make sure that + * the cycles differ by exactly one and check the byte count. + * + * This check is run unlocked, so can give false positives. Rather than assert + * on failures, use a warn-once flag and a panic tag to allow the admin to + * determine if they want to panic the machine when such an error occurs. For + * debug kernels this will have the same effect as using an assert but, unlinke + * an assert, it can be turned off at runtime. + */  STATIC void  xlog_verify_grant_tail(  	struct log	*log) @@ -3422,17 +3425,22 @@ xlog_verify_grant_tail(  	int		tail_cycle, tail_blocks;  	int		cycle, space; -	/* -	 * Check to make sure the grant write head didn't just over lap the -	 * tail.  If the cycles are the same, we can't be overlapping. -	 * Otherwise, make sure that the cycles differ by exactly one and -	 * check the byte count. -	 */  	xlog_crack_grant_head(&log->l_grant_write_head, &cycle, &space);  	xlog_crack_atomic_lsn(&log->l_tail_lsn, &tail_cycle, &tail_blocks);  	if (tail_cycle != cycle) { -		ASSERT(cycle - 1 == tail_cycle); -		ASSERT(space <= BBTOB(tail_blocks)); +		if (cycle - 1 != tail_cycle && +		    !(log->l_flags & XLOG_TAIL_WARN)) { +			xfs_alert_tag(log->l_mp, XFS_PTAG_LOGRES, +				"%s: cycle - 1 != tail_cycle", __func__); +			log->l_flags |= XLOG_TAIL_WARN; +		} + +		if (space > BBTOB(tail_blocks) && +		    !(log->l_flags & XLOG_TAIL_WARN)) { +			xfs_alert_tag(log->l_mp, XFS_PTAG_LOGRES, +				"%s: space > BBTOB(tail_blocks)", __func__); +			log->l_flags |= XLOG_TAIL_WARN; +		}  	}  } @@ -3448,16 +3456,16 @@ xlog_verify_tail_lsn(xlog_t	    *log,  	blocks =  	    log->l_logBBsize - (log->l_prev_block - BLOCK_LSN(tail_lsn));  	if (blocks < BTOBB(iclog->ic_offset)+BTOBB(log->l_iclog_hsize)) -	    xlog_panic("xlog_verify_tail_lsn: ran out of log space"); +		xfs_emerg(log->l_mp, "%s: ran out of log space", __func__);      } else {  	ASSERT(CYCLE_LSN(tail_lsn)+1 == log->l_prev_cycle);  	if (BLOCK_LSN(tail_lsn) == log->l_prev_block) -	    xlog_panic("xlog_verify_tail_lsn: tail wrapped"); +		xfs_emerg(log->l_mp, "%s: tail wrapped", __func__);  	blocks = BLOCK_LSN(tail_lsn) - log->l_prev_block;  	if (blocks < BTOBB(iclog->ic_offset) + 1) -	    xlog_panic("xlog_verify_tail_lsn: ran out of log space"); +		xfs_emerg(log->l_mp, "%s: ran out of log space", __func__);      }  }	/* xlog_verify_tail_lsn */ @@ -3497,22 +3505,23 @@ xlog_verify_iclog(xlog_t	 *log,  	icptr = log->l_iclog;  	for (i=0; i < log->l_iclog_bufs; i++) {  		if (icptr == NULL) -			xlog_panic("xlog_verify_iclog: invalid ptr"); +			xfs_emerg(log->l_mp, "%s: invalid ptr", __func__);  		icptr = icptr->ic_next;  	}  	if (icptr != log->l_iclog) -		xlog_panic("xlog_verify_iclog: corrupt iclog ring"); +		xfs_emerg(log->l_mp, "%s: corrupt iclog ring", __func__);  	spin_unlock(&log->l_icloglock);  	/* check log magic numbers */  	if (be32_to_cpu(iclog->ic_header.h_magicno) != XLOG_HEADER_MAGIC_NUM) -		xlog_panic("xlog_verify_iclog: invalid magic num"); +		xfs_emerg(log->l_mp, "%s: invalid magic num", __func__);  	ptr = (xfs_caddr_t) &iclog->ic_header;  	for (ptr += BBSIZE; ptr < ((xfs_caddr_t)&iclog->ic_header) + count;  	     ptr += BBSIZE) {  		if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM) -			xlog_panic("xlog_verify_iclog: unexpected magic num"); +			xfs_emerg(log->l_mp, "%s: unexpected magic num", +				__func__);  	}  	/* check fields */ @@ -3542,9 +3551,10 @@ xlog_verify_iclog(xlog_t	 *log,  			}  		}  		if (clientid != XFS_TRANSACTION && clientid != XFS_LOG) -			cmn_err(CE_WARN, "xlog_verify_iclog: " -				"invalid clientid %d op 0x%p offset 0x%lx", -				clientid, ophead, (unsigned long)field_offset); +			xfs_warn(log->l_mp, +				"%s: invalid clientid %d op 0x%p offset 0x%lx", +				__func__, clientid, ophead, +				(unsigned long)field_offset);  		/* check length */  		field_offset = (__psint_t) diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index d5f8be8f4bf6..5864850e9e34 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -87,10 +87,6 @@ static inline uint xlog_get_client_id(__be32 i)  	return be32_to_cpu(i) >> 24;  } -#define xlog_panic(args...)	cmn_err(CE_PANIC, ## args) -#define xlog_exit(args...)	cmn_err(CE_PANIC, ## args) -#define xlog_warn(args...)	cmn_err(CE_WARN, ## args) -  /*   * In core log state   */ @@ -148,6 +144,7 @@ static inline uint xlog_get_client_id(__be32 i)  #define	XLOG_RECOVERY_NEEDED	0x4	/* log was recovered */  #define XLOG_IO_ERROR		0x8	/* log hit an I/O error, and being  					   shutdown */ +#define XLOG_TAIL_WARN		0x10	/* log tail verify warning issued */  #ifdef __KERNEL__  /* @@ -574,7 +571,7 @@ int	xlog_write(struct log *log, struct xfs_log_vec *log_vector,   * When we crack an atomic LSN, we sample it first so that the value will not   * change while we are cracking it into the component values. This means we   * will always get consistent component values to work from. This should always - * be used to smaple and crack LSNs taht are stored and updated in atomic + * be used to sample and crack LSNs that are stored and updated in atomic   * variables.   */  static inline void diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index aa0ebb776903..5cc464a17c93 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -92,7 +92,7 @@ xlog_get_bp(  	int		nbblks)  {  	if (!xlog_buf_bbcount_valid(log, nbblks)) { -		xlog_warn("XFS: Invalid block length (0x%x) given for buffer", +		xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",  			nbblks);  		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);  		return NULL; @@ -101,7 +101,7 @@ xlog_get_bp(  	/*  	 * We do log I/O in units of log sectors (a power-of-2  	 * multiple of the basic block size), so we round up the -	 * requested size to acommodate the basic blocks required +	 * requested size to accommodate the basic blocks required  	 * for complete log sectors.  	 *  	 * In addition, the buffer may be used for a non-sector- @@ -112,7 +112,7 @@ xlog_get_bp(  	 * an issue.  Nor will this be a problem if the log I/O is  	 * done in basic blocks (sector size 1).  But otherwise we  	 * extend the buffer by one extra log sector to ensure -	 * there's space to accomodate this possiblility. +	 * there's space to accommodate this possibility.  	 */  	if (nbblks > 1 && log->l_sectBBsize > 1)  		nbblks += log->l_sectBBsize; @@ -160,7 +160,7 @@ xlog_bread_noalign(  	int		error;  	if (!xlog_buf_bbcount_valid(log, nbblks)) { -		xlog_warn("XFS: Invalid block length (0x%x) given for buffer", +		xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",  			nbblks);  		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);  		return EFSCORRUPTED; @@ -219,7 +219,7 @@ xlog_bwrite(  	int		error;  	if (!xlog_buf_bbcount_valid(log, nbblks)) { -		xlog_warn("XFS: Invalid block length (0x%x) given for buffer", +		xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",  			nbblks);  		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);  		return EFSCORRUPTED; @@ -254,9 +254,9 @@ xlog_header_check_dump(  	xfs_mount_t		*mp,  	xlog_rec_header_t	*head)  { -	cmn_err(CE_DEBUG, "%s:  SB : uuid = %pU, fmt = %d\n", +	xfs_debug(mp, "%s:  SB : uuid = %pU, fmt = %d\n",  		__func__, &mp->m_sb.sb_uuid, XLOG_FMT); -	cmn_err(CE_DEBUG, "    log : uuid = %pU, fmt = %d\n", +	xfs_debug(mp, "    log : uuid = %pU, fmt = %d\n",  		&head->h_fs_uuid, be32_to_cpu(head->h_fmt));  }  #else @@ -279,15 +279,15 @@ xlog_header_check_recover(  	 * a dirty log created in IRIX.  	 */  	if (unlikely(be32_to_cpu(head->h_fmt) != XLOG_FMT)) { -		xlog_warn( -	"XFS: dirty log written in incompatible format - can't recover"); +		xfs_warn(mp, +	"dirty log written in incompatible format - can't recover");  		xlog_header_check_dump(mp, head);  		XFS_ERROR_REPORT("xlog_header_check_recover(1)",  				 XFS_ERRLEVEL_HIGH, mp);  		return XFS_ERROR(EFSCORRUPTED);  	} else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) { -		xlog_warn( -	"XFS: dirty log entry has mismatched uuid - can't recover"); +		xfs_warn(mp, +	"dirty log entry has mismatched uuid - can't recover");  		xlog_header_check_dump(mp, head);  		XFS_ERROR_REPORT("xlog_header_check_recover(2)",  				 XFS_ERRLEVEL_HIGH, mp); @@ -312,9 +312,9 @@ xlog_header_check_mount(  		 * h_fs_uuid is nil, we assume this log was last mounted  		 * by IRIX and continue.  		 */ -		xlog_warn("XFS: nil uuid in log - IRIX style log"); +		xfs_warn(mp, "nil uuid in log - IRIX style log");  	} else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) { -		xlog_warn("XFS: log has mismatched uuid - can't recover"); +		xfs_warn(mp, "log has mismatched uuid - can't recover");  		xlog_header_check_dump(mp, head);  		XFS_ERROR_REPORT("xlog_header_check_mount",  				 XFS_ERRLEVEL_HIGH, mp); @@ -490,8 +490,8 @@ xlog_find_verify_log_record(  	for (i = (*last_blk) - 1; i >= 0; i--) {  		if (i < start_blk) {  			/* valid log record not found */ -			xlog_warn( -		"XFS: Log inconsistent (didn't find previous header)"); +			xfs_warn(log->l_mp, +		"Log inconsistent (didn't find previous header)");  			ASSERT(0);  			error = XFS_ERROR(EIO);  			goto out; @@ -591,12 +591,12 @@ xlog_find_head(  			 * mkfs etc write a dummy unmount record to a fresh  			 * log so we can store the uuid in there  			 */ -			xlog_warn("XFS: totally zeroed log"); +			xfs_warn(log->l_mp, "totally zeroed log");  		}  		return 0;  	} else if (error) { -		xlog_warn("XFS: empty log check failed"); +		xfs_warn(log->l_mp, "empty log check failed");  		return error;  	} @@ -819,7 +819,7 @@ validate_head:  	xlog_put_bp(bp);  	if (error) -	    xlog_warn("XFS: failed to find log head"); +		xfs_warn(log->l_mp, "failed to find log head");  	return error;  } @@ -912,7 +912,7 @@ xlog_find_tail(  		}  	}  	if (!found) { -		xlog_warn("XFS: xlog_find_tail: couldn't find sync record"); +		xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__);  		ASSERT(0);  		return XFS_ERROR(EIO);  	} @@ -1028,7 +1028,7 @@ done:  	xlog_put_bp(bp);  	if (error) -		xlog_warn("XFS: failed to locate log tail"); +		xfs_warn(log->l_mp, "failed to locate log tail");  	return error;  } @@ -1092,7 +1092,8 @@ xlog_find_zeroed(  		 * the first block must be 1. If it's not, maybe we're  		 * not looking at a log... Bail out.  		 */ -		xlog_warn("XFS: Log inconsistent or not a log (last==0, first!=1)"); +		xfs_warn(log->l_mp, +			"Log inconsistent or not a log (last==0, first!=1)");  		return XFS_ERROR(EINVAL);  	} @@ -1506,8 +1507,8 @@ xlog_recover_add_to_trans(  	if (list_empty(&trans->r_itemq)) {  		/* we need to catch log corruptions here */  		if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) { -			xlog_warn("XFS: xlog_recover_add_to_trans: " -				  "bad header magic number"); +			xfs_warn(log->l_mp, "%s: bad header magic number", +				__func__);  			ASSERT(0);  			return XFS_ERROR(EIO);  		} @@ -1534,8 +1535,8 @@ xlog_recover_add_to_trans(  	if (item->ri_total == 0) {		/* first region to be added */  		if (in_f->ilf_size == 0 ||  		    in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) { -			xlog_warn( -	"XFS: bad number of regions (%d) in inode log format", +			xfs_warn(log->l_mp, +		"bad number of regions (%d) in inode log format",  				  in_f->ilf_size);  			ASSERT(0);  			return XFS_ERROR(EIO); @@ -1592,8 +1593,9 @@ xlog_recover_reorder_trans(  			list_move_tail(&item->ri_list, &trans->r_itemq);  			break;  		default: -			xlog_warn( -	"XFS: xlog_recover_reorder_trans: unrecognized type of log operation"); +			xfs_warn(log->l_mp, +				"%s: unrecognized type of log operation", +				__func__);  			ASSERT(0);  			return XFS_ERROR(EIO);  		} @@ -1803,8 +1805,9 @@ xlog_recover_do_inode_buffer(  		logged_nextp = item->ri_buf[item_index].i_addr +  				next_unlinked_offset - reg_buf_offset;  		if (unlikely(*logged_nextp == 0)) { -			xfs_fs_cmn_err(CE_ALERT, mp, -				"bad inode buffer log record (ptr = 0x%p, bp = 0x%p).  XFS trying to replay bad (0) inode di_next_unlinked field", +			xfs_alert(mp, +		"Bad inode buffer log record (ptr = 0x%p, bp = 0x%p). " +		"Trying to replay bad (0) inode di_next_unlinked field.",  				item, bp);  			XFS_ERROR_REPORT("xlog_recover_do_inode_buf",  					 XFS_ERRLEVEL_LOW, mp); @@ -1863,17 +1866,17 @@ xlog_recover_do_reg_buffer(  		if (buf_f->blf_flags &  		   (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) {  			if (item->ri_buf[i].i_addr == NULL) { -				cmn_err(CE_ALERT, +				xfs_alert(mp,  					"XFS: NULL dquot in %s.", __func__);  				goto next;  			}  			if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) { -				cmn_err(CE_ALERT, +				xfs_alert(mp,  					"XFS: dquot too small (%d) in %s.",  					item->ri_buf[i].i_len, __func__);  				goto next;  			} -			error = xfs_qm_dqcheck(item->ri_buf[i].i_addr, +			error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr,  					       -1, 0, XFS_QMOPT_DOWARN,  					       "dquot_buf_recover");  			if (error) @@ -1898,6 +1901,7 @@ xlog_recover_do_reg_buffer(   */  int  xfs_qm_dqcheck( +	struct xfs_mount *mp,  	xfs_disk_dquot_t *ddq,  	xfs_dqid_t	 id,  	uint		 type,	  /* used only when IO_dorepair is true */ @@ -1924,14 +1928,14 @@ xfs_qm_dqcheck(  	 */  	if (be16_to_cpu(ddq->d_magic) != XFS_DQUOT_MAGIC) {  		if (flags & XFS_QMOPT_DOWARN) -			cmn_err(CE_ALERT, +			xfs_alert(mp,  			"%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x",  			str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC);  		errs++;  	}  	if (ddq->d_version != XFS_DQUOT_VERSION) {  		if (flags & XFS_QMOPT_DOWARN) -			cmn_err(CE_ALERT, +			xfs_alert(mp,  			"%s : XFS dquot ID 0x%x, version 0x%x != 0x%x",  			str, id, ddq->d_version, XFS_DQUOT_VERSION);  		errs++; @@ -1941,7 +1945,7 @@ xfs_qm_dqcheck(  	    ddq->d_flags != XFS_DQ_PROJ &&  	    ddq->d_flags != XFS_DQ_GROUP) {  		if (flags & XFS_QMOPT_DOWARN) -			cmn_err(CE_ALERT, +			xfs_alert(mp,  			"%s : XFS dquot ID 0x%x, unknown flags 0x%x",  			str, id, ddq->d_flags);  		errs++; @@ -1949,7 +1953,7 @@ xfs_qm_dqcheck(  	if (id != -1 && id != be32_to_cpu(ddq->d_id)) {  		if (flags & XFS_QMOPT_DOWARN) -			cmn_err(CE_ALERT, +			xfs_alert(mp,  			"%s : ondisk-dquot 0x%p, ID mismatch: "  			"0x%x expected, found id 0x%x",  			str, ddq, id, be32_to_cpu(ddq->d_id)); @@ -1962,9 +1966,8 @@ xfs_qm_dqcheck(  				be64_to_cpu(ddq->d_blk_softlimit)) {  			if (!ddq->d_btimer) {  				if (flags & XFS_QMOPT_DOWARN) -					cmn_err(CE_ALERT, -					"%s : Dquot ID 0x%x (0x%p) " -					"BLK TIMER NOT STARTED", +					xfs_alert(mp, +			"%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED",  					str, (int)be32_to_cpu(ddq->d_id), ddq);  				errs++;  			} @@ -1974,9 +1977,8 @@ xfs_qm_dqcheck(  				be64_to_cpu(ddq->d_ino_softlimit)) {  			if (!ddq->d_itimer) {  				if (flags & XFS_QMOPT_DOWARN) -					cmn_err(CE_ALERT, -					"%s : Dquot ID 0x%x (0x%p) " -					"INODE TIMER NOT STARTED", +					xfs_alert(mp, +			"%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED",  					str, (int)be32_to_cpu(ddq->d_id), ddq);  				errs++;  			} @@ -1986,9 +1988,8 @@ xfs_qm_dqcheck(  				be64_to_cpu(ddq->d_rtb_softlimit)) {  			if (!ddq->d_rtbtimer) {  				if (flags & XFS_QMOPT_DOWARN) -					cmn_err(CE_ALERT, -					"%s : Dquot ID 0x%x (0x%p) " -					"RTBLK TIMER NOT STARTED", +					xfs_alert(mp, +			"%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED",  					str, (int)be32_to_cpu(ddq->d_id), ddq);  				errs++;  			} @@ -1999,7 +2000,7 @@ xfs_qm_dqcheck(  		return errs;  	if (flags & XFS_QMOPT_DOWARN) -		cmn_err(CE_NOTE, "Re-initializing dquot ID 0x%x", id); +		xfs_notice(mp, "Re-initializing dquot ID 0x%x", id);  	/*  	 * Typically, a repair is only requested by quotacheck. @@ -2218,9 +2219,9 @@ xlog_recover_inode_pass2(  	 */  	if (unlikely(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)) {  		xfs_buf_relse(bp); -		xfs_fs_cmn_err(CE_ALERT, mp, -			"xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld", -			dip, bp, in_f->ilf_ino); +		xfs_alert(mp, +	"%s: Bad inode magic number, dip = 0x%p, dino bp = 0x%p, ino = %Ld", +			__func__, dip, bp, in_f->ilf_ino);  		XFS_ERROR_REPORT("xlog_recover_inode_pass2(1)",  				 XFS_ERRLEVEL_LOW, mp);  		error = EFSCORRUPTED; @@ -2229,9 +2230,9 @@ xlog_recover_inode_pass2(  	dicp = item->ri_buf[1].i_addr;  	if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {  		xfs_buf_relse(bp); -		xfs_fs_cmn_err(CE_ALERT, mp, -			"xfs_inode_recover: Bad inode log record, rec ptr 0x%p, ino %Ld", -			item, in_f->ilf_ino); +		xfs_alert(mp, +			"%s: Bad inode log record, rec ptr 0x%p, ino %Ld", +			__func__, item, in_f->ilf_ino);  		XFS_ERROR_REPORT("xlog_recover_inode_pass2(2)",  				 XFS_ERRLEVEL_LOW, mp);  		error = EFSCORRUPTED; @@ -2263,9 +2264,10 @@ xlog_recover_inode_pass2(  			XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",  					 XFS_ERRLEVEL_LOW, mp, dicp);  			xfs_buf_relse(bp); -			xfs_fs_cmn_err(CE_ALERT, mp, -				"xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", -				item, dip, bp, in_f->ilf_ino); +			xfs_alert(mp, +		"%s: Bad regular inode log record, rec ptr 0x%p, " +		"ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", +				__func__, item, dip, bp, in_f->ilf_ino);  			error = EFSCORRUPTED;  			goto error;  		} @@ -2276,9 +2278,10 @@ xlog_recover_inode_pass2(  			XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)",  					     XFS_ERRLEVEL_LOW, mp, dicp);  			xfs_buf_relse(bp); -			xfs_fs_cmn_err(CE_ALERT, mp, -				"xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", -				item, dip, bp, in_f->ilf_ino); +			xfs_alert(mp, +		"%s: Bad dir inode log record, rec ptr 0x%p, " +		"ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", +				__func__, item, dip, bp, in_f->ilf_ino);  			error = EFSCORRUPTED;  			goto error;  		} @@ -2287,9 +2290,10 @@ xlog_recover_inode_pass2(  		XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)",  				     XFS_ERRLEVEL_LOW, mp, dicp);  		xfs_buf_relse(bp); -		xfs_fs_cmn_err(CE_ALERT, mp, -			"xfs_inode_recover: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", -			item, dip, bp, in_f->ilf_ino, +		xfs_alert(mp, +	"%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " +	"dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", +			__func__, item, dip, bp, in_f->ilf_ino,  			dicp->di_nextents + dicp->di_anextents,  			dicp->di_nblocks);  		error = EFSCORRUPTED; @@ -2299,8 +2303,9 @@ xlog_recover_inode_pass2(  		XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)",  				     XFS_ERRLEVEL_LOW, mp, dicp);  		xfs_buf_relse(bp); -		xfs_fs_cmn_err(CE_ALERT, mp, -			"xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", +		xfs_alert(mp, +	"%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " +	"dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__,  			item, dip, bp, in_f->ilf_ino, dicp->di_forkoff);  		error = EFSCORRUPTED;  		goto error; @@ -2309,9 +2314,9 @@ xlog_recover_inode_pass2(  		XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",  				     XFS_ERRLEVEL_LOW, mp, dicp);  		xfs_buf_relse(bp); -		xfs_fs_cmn_err(CE_ALERT, mp, -			"xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", -			item->ri_buf[1].i_len, item); +		xfs_alert(mp, +			"%s: Bad inode log record length %d, rec ptr 0x%p", +			__func__, item->ri_buf[1].i_len, item);  		error = EFSCORRUPTED;  		goto error;  	} @@ -2398,7 +2403,7 @@ xlog_recover_inode_pass2(  			break;  		default: -			xlog_warn("XFS: xlog_recover_inode_pass2: Invalid flag"); +			xfs_warn(log->l_mp, "%s: Invalid flag", __func__);  			ASSERT(0);  			xfs_buf_relse(bp);  			error = EIO; @@ -2467,13 +2472,11 @@ xlog_recover_dquot_pass2(  	recddq = item->ri_buf[1].i_addr;  	if (recddq == NULL) { -		cmn_err(CE_ALERT, -			"XFS: NULL dquot in %s.", __func__); +		xfs_alert(log->l_mp, "NULL dquot in %s.", __func__);  		return XFS_ERROR(EIO);  	}  	if (item->ri_buf[1].i_len < sizeof(xfs_disk_dquot_t)) { -		cmn_err(CE_ALERT, -			"XFS: dquot too small (%d) in %s.", +		xfs_alert(log->l_mp, "dquot too small (%d) in %s.",  			item->ri_buf[1].i_len, __func__);  		return XFS_ERROR(EIO);  	} @@ -2498,12 +2501,10 @@ xlog_recover_dquot_pass2(  	 */  	dq_f = item->ri_buf[0].i_addr;  	ASSERT(dq_f); -	if ((error = xfs_qm_dqcheck(recddq, -			   dq_f->qlf_id, -			   0, XFS_QMOPT_DOWARN, -			   "xlog_recover_dquot_pass2 (log copy)"))) { +	error = xfs_qm_dqcheck(mp, recddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, +			   "xlog_recover_dquot_pass2 (log copy)"); +	if (error)  		return XFS_ERROR(EIO); -	}  	ASSERT(dq_f->qlf_len == 1);  	error = xfs_read_buf(mp, mp->m_ddev_targp, @@ -2523,8 +2524,9 @@ xlog_recover_dquot_pass2(  	 * was among a chunk of dquots created earlier, and we did some  	 * minimal initialization then.  	 */ -	if (xfs_qm_dqcheck(ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, -			   "xlog_recover_dquot_pass2")) { +	error = xfs_qm_dqcheck(mp, ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, +			   "xlog_recover_dquot_pass2"); +	if (error) {  		xfs_buf_relse(bp);  		return XFS_ERROR(EIO);  	} @@ -2676,9 +2678,8 @@ xlog_recover_commit_pass1(  		/* nothing to do in pass 1 */  		return 0;  	default: -		xlog_warn( -	"XFS: invalid item type (%d) xlog_recover_commit_pass1", -			ITEM_TYPE(item)); +		xfs_warn(log->l_mp, "%s: invalid item type (%d)", +			__func__, ITEM_TYPE(item));  		ASSERT(0);  		return XFS_ERROR(EIO);  	} @@ -2707,9 +2708,8 @@ xlog_recover_commit_pass2(  		/* nothing to do in pass2 */  		return 0;  	default: -		xlog_warn( -	"XFS: invalid item type (%d) xlog_recover_commit_pass2", -			ITEM_TYPE(item)); +		xfs_warn(log->l_mp, "%s: invalid item type (%d)", +			__func__, ITEM_TYPE(item));  		ASSERT(0);  		return XFS_ERROR(EIO);  	} @@ -2751,10 +2751,11 @@ xlog_recover_commit_trans(  STATIC int  xlog_recover_unmount_trans( +	struct log		*log,  	xlog_recover_t		*trans)  {  	/* Do nothing now */ -	xlog_warn("XFS: xlog_recover_unmount_trans: Unmount LR"); +	xfs_warn(log->l_mp, "%s: Unmount LR", __func__);  	return 0;  } @@ -2797,8 +2798,8 @@ xlog_recover_process_data(  		dp += sizeof(xlog_op_header_t);  		if (ohead->oh_clientid != XFS_TRANSACTION &&  		    ohead->oh_clientid != XFS_LOG) { -			xlog_warn( -		"XFS: xlog_recover_process_data: bad clientid"); +			xfs_warn(log->l_mp, "%s: bad clientid 0x%x", +					__func__, ohead->oh_clientid);  			ASSERT(0);  			return (XFS_ERROR(EIO));  		} @@ -2811,8 +2812,8 @@ xlog_recover_process_data(  					be64_to_cpu(rhead->h_lsn));  		} else {  			if (dp + be32_to_cpu(ohead->oh_len) > lp) { -				xlog_warn( -			"XFS: xlog_recover_process_data: bad length"); +				xfs_warn(log->l_mp, "%s: bad length 0x%x", +					__func__, be32_to_cpu(ohead->oh_len));  				WARN_ON(1);  				return (XFS_ERROR(EIO));  			} @@ -2825,7 +2826,7 @@ xlog_recover_process_data(  								trans, pass);  				break;  			case XLOG_UNMOUNT_TRANS: -				error = xlog_recover_unmount_trans(trans); +				error = xlog_recover_unmount_trans(log, trans);  				break;  			case XLOG_WAS_CONT_TRANS:  				error = xlog_recover_add_to_cont_trans(log, @@ -2833,8 +2834,8 @@ xlog_recover_process_data(  						be32_to_cpu(ohead->oh_len));  				break;  			case XLOG_START_TRANS: -				xlog_warn( -			"XFS: xlog_recover_process_data: bad transaction"); +				xfs_warn(log->l_mp, "%s: bad transaction", +					__func__);  				ASSERT(0);  				error = XFS_ERROR(EIO);  				break; @@ -2844,8 +2845,8 @@ xlog_recover_process_data(  						dp, be32_to_cpu(ohead->oh_len));  				break;  			default: -				xlog_warn( -			"XFS: xlog_recover_process_data: bad flag"); +				xfs_warn(log->l_mp, "%s: bad flag 0x%x", +					__func__, flags);  				ASSERT(0);  				error = XFS_ERROR(EIO);  				break; @@ -3030,8 +3031,7 @@ xlog_recover_clear_agi_bucket(  out_abort:  	xfs_trans_cancel(tp, XFS_TRANS_ABORT);  out_error: -	xfs_fs_cmn_err(CE_WARN, mp, "xlog_recover_clear_agi_bucket: " -			"failed to clear agi %d. Continuing.", agno); +	xfs_warn(mp, "%s: failed to clear agi %d. Continuing.", __func__, agno);  	return;  } @@ -3282,7 +3282,7 @@ xlog_valid_rec_header(  	if (unlikely(  	    (!rhead->h_version ||  	    (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) { -		xlog_warn("XFS: %s: unrecognised log version (%d).", +		xfs_warn(log->l_mp, "%s: unrecognised log version (%d).",  			__func__, be32_to_cpu(rhead->h_version));  		return XFS_ERROR(EIO);  	} @@ -3740,10 +3740,9 @@ xlog_recover(  			return error;  		} -		cmn_err(CE_NOTE, -			"Starting XFS recovery on filesystem: %s (logdev: %s)", -			log->l_mp->m_fsname, log->l_mp->m_logname ? -			log->l_mp->m_logname : "internal"); +		xfs_notice(log->l_mp, "Starting recovery (logdev: %s)", +				log->l_mp->m_logname ? log->l_mp->m_logname +						     : "internal");  		error = xlog_do_recover(log, head_blk, tail_blk);  		log->l_flags |= XLOG_RECOVERY_NEEDED; @@ -3776,9 +3775,7 @@ xlog_recover_finish(  		int	error;  		error = xlog_recover_process_efis(log);  		if (error) { -			cmn_err(CE_ALERT, -				"Failed to recover EFIs on filesystem: %s", -				log->l_mp->m_fsname); +			xfs_alert(log->l_mp, "Failed to recover EFIs");  			return error;  		}  		/* @@ -3793,15 +3790,12 @@ xlog_recover_finish(  		xlog_recover_check_summary(log); -		cmn_err(CE_NOTE, -			"Ending XFS recovery on filesystem: %s (logdev: %s)", -			log->l_mp->m_fsname, log->l_mp->m_logname ? -			log->l_mp->m_logname : "internal"); +		xfs_notice(log->l_mp, "Ending recovery (logdev: %s)", +				log->l_mp->m_logname ? log->l_mp->m_logname +						     : "internal");  		log->l_flags &= ~XLOG_RECOVERY_NEEDED;  	} else { -		cmn_err(CE_DEBUG, -			"Ending clean XFS mount for filesystem: %s\n", -			log->l_mp->m_fsname); +		xfs_info(log->l_mp, "Ending clean mount");  	}  	return 0;  } @@ -3834,10 +3828,8 @@ xlog_recover_check_summary(  	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {  		error = xfs_read_agf(mp, NULL, agno, 0, &agfbp);  		if (error) { -			xfs_fs_cmn_err(CE_ALERT, mp, -					"xlog_recover_check_summary(agf)" -					"agf read failed agno %d error %d", -							agno, error); +			xfs_alert(mp, "%s agf read failed agno %d error %d", +						__func__, agno, error);  		} else {  			agfp = XFS_BUF_TO_AGF(agfbp);  			freeblks += be32_to_cpu(agfp->agf_freeblks) + @@ -3846,7 +3838,10 @@ xlog_recover_check_summary(  		}  		error = xfs_read_agi(mp, NULL, agno, &agibp); -		if (!error) { +		if (error) { +			xfs_alert(mp, "%s agi read failed agno %d error %d", +						__func__, agno, error); +		} else {  			struct xfs_agi	*agi = XFS_BUF_TO_AGI(agibp);  			itotal += be32_to_cpu(agi->agi_count); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index d447aef84bc3..bb3f9a7b24ed 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -133,9 +133,7 @@ xfs_uuid_mount(  		return 0;  	if (uuid_is_nil(uuid)) { -		cmn_err(CE_WARN, -			"XFS: Filesystem %s has nil UUID - can't mount", -			mp->m_fsname); +		xfs_warn(mp, "Filesystem has nil UUID - can't mount");  		return XFS_ERROR(EINVAL);  	} @@ -163,8 +161,7 @@ xfs_uuid_mount(   out_duplicate:  	mutex_unlock(&xfs_uuid_table_mutex); -	cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount", -			 mp->m_fsname); +	xfs_warn(mp, "Filesystem has duplicate UUID - can't mount");  	return XFS_ERROR(EINVAL);  } @@ -311,6 +308,8 @@ xfs_mount_validate_sb(  	xfs_sb_t	*sbp,  	int		flags)  { +	int		loud = !(flags & XFS_MFSI_QUIET); +  	/*  	 * If the log device and data device have the  	 * same device number, the log is internal. @@ -319,28 +318,32 @@ xfs_mount_validate_sb(  	 * a volume filesystem in a non-volume manner.  	 */  	if (sbp->sb_magicnum != XFS_SB_MAGIC) { -		xfs_fs_mount_cmn_err(flags, "bad magic number"); +		if (loud) +			xfs_warn(mp, "bad magic number");  		return XFS_ERROR(EWRONGFS);  	}  	if (!xfs_sb_good_version(sbp)) { -		xfs_fs_mount_cmn_err(flags, "bad version"); +		if (loud) +			xfs_warn(mp, "bad version");  		return XFS_ERROR(EWRONGFS);  	}  	if (unlikely(  	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { -		xfs_fs_mount_cmn_err(flags, -			"filesystem is marked as having an external log; " -			"specify logdev on the\nmount command line."); +		if (loud) +			xfs_warn(mp, +		"filesystem is marked as having an external log; " +		"specify logdev on the mount command line.");  		return XFS_ERROR(EINVAL);  	}  	if (unlikely(  	    sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { -		xfs_fs_mount_cmn_err(flags, -			"filesystem is marked as having an internal log; " -			"do not specify logdev on\nthe mount command line."); +		if (loud) +			xfs_warn(mp, +		"filesystem is marked as having an internal log; " +		"do not specify logdev on the mount command line.");  		return XFS_ERROR(EINVAL);  	} @@ -369,7 +372,8 @@ xfs_mount_validate_sb(  	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||  	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||  	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) { -		xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed"); +		if (loud) +			xfs_warn(mp, "SB sanity check 1 failed");  		return XFS_ERROR(EFSCORRUPTED);  	} @@ -382,7 +386,8 @@ xfs_mount_validate_sb(  	     (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||  	    sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *  			      sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) { -		xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed"); +		if (loud) +			xfs_warn(mp, "SB sanity check 2 failed");  		return XFS_ERROR(EFSCORRUPTED);  	} @@ -390,12 +395,12 @@ xfs_mount_validate_sb(  	 * Until this is fixed only page-sized or smaller data blocks work.  	 */  	if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { -		xfs_fs_mount_cmn_err(flags, -			"file system with blocksize %d bytes", -			sbp->sb_blocksize); -		xfs_fs_mount_cmn_err(flags, -			"only pagesize (%ld) or less will currently work.", -			PAGE_SIZE); +		if (loud) { +			xfs_warn(mp, +		"File system with blocksize %d bytes. " +		"Only pagesize (%ld) or less will currently work.", +				sbp->sb_blocksize, PAGE_SIZE); +		}  		return XFS_ERROR(ENOSYS);  	} @@ -409,21 +414,23 @@ xfs_mount_validate_sb(  	case 2048:  		break;  	default: -		xfs_fs_mount_cmn_err(flags, -			"inode size of %d bytes not supported", -			sbp->sb_inodesize); +		if (loud) +			xfs_warn(mp, "inode size of %d bytes not supported", +				sbp->sb_inodesize);  		return XFS_ERROR(ENOSYS);  	}  	if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||  	    xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { -		xfs_fs_mount_cmn_err(flags, -			"file system too large to be mounted on this system."); +		if (loud) +			xfs_warn(mp, +		"file system too large to be mounted on this system.");  		return XFS_ERROR(EFBIG);  	}  	if (unlikely(sbp->sb_inprogress)) { -		xfs_fs_mount_cmn_err(flags, "file system busy"); +		if (loud) +			xfs_warn(mp, "file system busy");  		return XFS_ERROR(EFSCORRUPTED);  	} @@ -431,8 +438,9 @@ xfs_mount_validate_sb(  	 * Version 1 directory format has never worked on Linux.  	 */  	if (unlikely(!xfs_sb_version_hasdirv2(sbp))) { -		xfs_fs_mount_cmn_err(flags, -			"file system using version 1 directory format"); +		if (loud) +			xfs_warn(mp, +				"file system using version 1 directory format");  		return XFS_ERROR(ENOSYS);  	} @@ -673,6 +681,7 @@ xfs_readsb(xfs_mount_t *mp, int flags)  	unsigned int	sector_size;  	xfs_buf_t	*bp;  	int		error; +	int		loud = !(flags & XFS_MFSI_QUIET);  	ASSERT(mp->m_sb_bp == NULL);  	ASSERT(mp->m_ddev_targp != NULL); @@ -688,7 +697,8 @@ reread:  	bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,  					XFS_SB_DADDR, sector_size, 0);  	if (!bp) { -		xfs_fs_mount_cmn_err(flags, "SB buffer read failed"); +		if (loud) +			xfs_warn(mp, "SB buffer read failed");  		return EIO;  	} @@ -699,7 +709,8 @@ reread:  	xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));  	error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);  	if (error) { -		xfs_fs_mount_cmn_err(flags, "SB validate failed"); +		if (loud) +			xfs_warn(mp, "SB validate failed");  		goto release_buf;  	} @@ -707,9 +718,9 @@ reread:  	 * We must be able to do sector-sized and sector-aligned IO.  	 */  	if (sector_size > mp->m_sb.sb_sectsize) { -		xfs_fs_mount_cmn_err(flags, -			"device supports only %u byte sectors (not %u)", -			sector_size, mp->m_sb.sb_sectsize); +		if (loud) +			xfs_warn(mp, "device supports %u byte sectors (not %u)", +				sector_size, mp->m_sb.sb_sectsize);  		error = ENOSYS;  		goto release_buf;  	} @@ -853,8 +864,7 @@ xfs_update_alignment(xfs_mount_t *mp)  		if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||  		    (BBTOB(mp->m_swidth) & mp->m_blockmask)) {  			if (mp->m_flags & XFS_MOUNT_RETERR) { -				cmn_err(CE_WARN, -					"XFS: alignment check 1 failed"); +				xfs_warn(mp, "alignment check 1 failed");  				return XFS_ERROR(EINVAL);  			}  			mp->m_dalign = mp->m_swidth = 0; @@ -867,8 +877,9 @@ xfs_update_alignment(xfs_mount_t *mp)  				if (mp->m_flags & XFS_MOUNT_RETERR) {  					return XFS_ERROR(EINVAL);  				} -				xfs_fs_cmn_err(CE_WARN, mp, -"stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)", +				xfs_warn(mp, +		"stripe alignment turned off: sunit(%d)/swidth(%d) " +		"incompatible with agsize(%d)",  					mp->m_dalign, mp->m_swidth,  					sbp->sb_agblocks); @@ -878,9 +889,9 @@ xfs_update_alignment(xfs_mount_t *mp)  				mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);  			} else {  				if (mp->m_flags & XFS_MOUNT_RETERR) { -					xfs_fs_cmn_err(CE_WARN, mp, -"stripe alignment turned off: sunit(%d) less than bsize(%d)", -                                        	mp->m_dalign, +					xfs_warn(mp, +		"stripe alignment turned off: sunit(%d) less than bsize(%d)", +						mp->m_dalign,  						mp->m_blockmask +1);  					return XFS_ERROR(EINVAL);  				} @@ -1026,14 +1037,14 @@ xfs_check_sizes(xfs_mount_t *mp)  	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);  	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { -		cmn_err(CE_WARN, "XFS: filesystem size mismatch detected"); +		xfs_warn(mp, "filesystem size mismatch detected");  		return XFS_ERROR(EFBIG);  	}  	bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,  					d - XFS_FSS_TO_BB(mp, 1),  					BBTOB(XFS_FSS_TO_BB(mp, 1)), 0);  	if (!bp) { -		cmn_err(CE_WARN, "XFS: last sector read failed"); +		xfs_warn(mp, "last sector read failed");  		return EIO;  	}  	xfs_buf_relse(bp); @@ -1041,14 +1052,14 @@ xfs_check_sizes(xfs_mount_t *mp)  	if (mp->m_logdev_targp != mp->m_ddev_targp) {  		d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);  		if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { -			cmn_err(CE_WARN, "XFS: log size mismatch detected"); +			xfs_warn(mp, "log size mismatch detected");  			return XFS_ERROR(EFBIG);  		}  		bp = xfs_buf_read_uncached(mp, mp->m_logdev_targp,  					d - XFS_FSB_TO_BB(mp, 1),  					XFS_FSB_TO_B(mp, 1), 0);  		if (!bp) { -			cmn_err(CE_WARN, "XFS: log device read failed"); +			xfs_warn(mp, "log device read failed");  			return EIO;  		}  		xfs_buf_relse(bp); @@ -1086,7 +1097,7 @@ xfs_mount_reset_sbqflags(  		return 0;  #ifdef QUOTADEBUG -	xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes"); +	xfs_notice(mp, "Writing superblock quota changes");  #endif  	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); @@ -1094,8 +1105,7 @@ xfs_mount_reset_sbqflags(  				      XFS_DEFAULT_LOG_COUNT);  	if (error) {  		xfs_trans_cancel(tp, 0); -		xfs_fs_cmn_err(CE_ALERT, mp, -			"xfs_mount_reset_sbqflags: Superblock update failed!"); +		xfs_alert(mp, "%s: Superblock update failed!", __func__);  		return error;  	} @@ -1161,8 +1171,7 @@ xfs_mountfs(  	 * transaction subsystem is online.  	 */  	if (xfs_sb_has_mismatched_features2(sbp)) { -		cmn_err(CE_WARN, -			"XFS: correcting sb_features alignment problem"); +		xfs_warn(mp, "correcting sb_features alignment problem");  		sbp->sb_features2 |= sbp->sb_bad_features2;  		sbp->sb_bad_features2 = sbp->sb_features2;  		mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2; @@ -1241,7 +1250,7 @@ xfs_mountfs(  	 */  	error = xfs_rtmount_init(mp);  	if (error) { -		cmn_err(CE_WARN, "XFS: RT mount failed"); +		xfs_warn(mp, "RT mount failed");  		goto out_remove_uuid;  	} @@ -1272,12 +1281,12 @@ xfs_mountfs(  	INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);  	error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);  	if (error) { -		cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error); +		xfs_warn(mp, "Failed per-ag init: %d", error);  		goto out_remove_uuid;  	}  	if (!sbp->sb_logblocks) { -		cmn_err(CE_WARN, "XFS: no log defined"); +		xfs_warn(mp, "no log defined");  		XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp);  		error = XFS_ERROR(EFSCORRUPTED);  		goto out_free_perag; @@ -1290,7 +1299,7 @@ xfs_mountfs(  			      XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),  			      XFS_FSB_TO_BB(mp, sbp->sb_logblocks));  	if (error) { -		cmn_err(CE_WARN, "XFS: log mount failed"); +		xfs_warn(mp, "log mount failed");  		goto out_free_perag;  	} @@ -1327,16 +1336,14 @@ xfs_mountfs(  	 */  	error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);  	if (error) { -		cmn_err(CE_WARN, "XFS: failed to read root inode"); +		xfs_warn(mp, "failed to read root inode");  		goto out_log_dealloc;  	}  	ASSERT(rip != NULL);  	if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { -		cmn_err(CE_WARN, "XFS: corrupted root inode"); -		cmn_err(CE_WARN, "Device %s - root %llu is not a directory", -			XFS_BUFTARG_NAME(mp->m_ddev_targp), +		xfs_warn(mp, "corrupted root inode %llu: not a directory",  			(unsigned long long)rip->i_ino);  		xfs_iunlock(rip, XFS_ILOCK_EXCL);  		XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, @@ -1356,7 +1363,7 @@ xfs_mountfs(  		/*  		 * Free up the root inode.  		 */ -		cmn_err(CE_WARN, "XFS: failed to read RT inodes"); +		xfs_warn(mp, "failed to read RT inodes");  		goto out_rele_rip;  	} @@ -1368,7 +1375,7 @@ xfs_mountfs(  	if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {  		error = xfs_mount_log_sb(mp, mp->m_update_flags);  		if (error) { -			cmn_err(CE_WARN, "XFS: failed to write sb changes"); +			xfs_warn(mp, "failed to write sb changes");  			goto out_rtunmount;  		}  	} @@ -1389,10 +1396,7 @@ xfs_mountfs(  		 * quotachecked license.  		 */  		if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) { -			cmn_err(CE_NOTE, -				"XFS: resetting qflags for filesystem %s", -				mp->m_fsname); - +			xfs_notice(mp, "resetting quota flags");  			error = xfs_mount_reset_sbqflags(mp);  			if (error)  				return error; @@ -1406,7 +1410,7 @@ xfs_mountfs(  	 */  	error = xfs_log_mount_finish(mp);  	if (error) { -		cmn_err(CE_WARN, "XFS: log mount finish failed"); +		xfs_warn(mp, "log mount finish failed");  		goto out_rtunmount;  	} @@ -1435,8 +1439,8 @@ xfs_mountfs(  		resblks = xfs_default_resblks(mp);  		error = xfs_reserve_blocks(mp, &resblks, NULL);  		if (error) -			cmn_err(CE_WARN, "XFS: Unable to allocate reserve " -				"blocks. Continuing without a reserve pool."); +			xfs_warn(mp, +	"Unable to allocate reserve blocks. Continuing without reserve pool.");  	}  	return 0; @@ -1525,12 +1529,12 @@ xfs_unmountfs(  	resblks = 0;  	error = xfs_reserve_blocks(mp, &resblks, NULL);  	if (error) -		cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. " +		xfs_warn(mp, "Unable to free reserved block pool. "  				"Freespace may not be correct on next mount.");  	error = xfs_log_sbcount(mp, 1);  	if (error) -		cmn_err(CE_WARN, "XFS: Unable to update superblock counters. " +		xfs_warn(mp, "Unable to update superblock counters. "  				"Freespace may not be correct on next mount.");  	xfs_unmountfs_writesb(mp);  	xfs_unmountfs_wait(mp); 		/* wait for async bufs */ @@ -2013,10 +2017,8 @@ xfs_dev_is_read_only(  	if (xfs_readonly_buftarg(mp->m_ddev_targp) ||  	    xfs_readonly_buftarg(mp->m_logdev_targp) ||  	    (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) { -		cmn_err(CE_NOTE, -			"XFS: %s required on read-only device.", message); -		cmn_err(CE_NOTE, -			"XFS: write access unavailable, cannot proceed."); +		xfs_notice(mp, "%s required on read-only device.", message); +		xfs_notice(mp, "write access unavailable, cannot proceed.");  		return EROFS;  	}  	return 0; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index a62e8971539d..19af0ab0d0c6 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -203,12 +203,9 @@ typedef struct xfs_mount {  	struct mutex		m_icsb_mutex;	/* balancer sync lock */  #endif  	struct xfs_mru_cache	*m_filestream;  /* per-mount filestream data */ -	struct task_struct	*m_sync_task;	/* generalised sync thread */ -	xfs_sync_work_t		m_sync_work;	/* work item for VFS_SYNC */ -	struct list_head	m_sync_list;	/* sync thread work item list */ -	spinlock_t		m_sync_lock;	/* work item list lock */ -	int			m_sync_seq;	/* sync thread generation no. */ -	wait_queue_head_t	m_wait_single_sync_task; +	struct delayed_work	m_sync_work;	/* background sync work */ +	struct delayed_work	m_reclaim_work;	/* background inode reclaim */ +	struct work_struct	m_flush_work;	/* background inode flush */  	__int64_t		m_update_flags;	/* sb flags we need to update  						   on the next remount,rw */  	struct shrinker		m_inode_shrink;	/* inode reclaim shrinker */ diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c index edfa178bafb6..4aff56395732 100644 --- a/fs/xfs/xfs_mru_cache.c +++ b/fs/xfs/xfs_mru_cache.c @@ -309,7 +309,7 @@ xfs_mru_cache_init(void)  	if (!xfs_mru_elem_zone)  		goto out; -	xfs_mru_reap_wq = create_singlethread_workqueue("xfs_mru_cache"); +	xfs_mru_reap_wq = alloc_workqueue("xfs_mru_cache", WQ_MEM_RECLAIM, 1);  	if (!xfs_mru_reap_wq)  		goto out_destroy_mru_elem_zone; diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 9bb6eda4cd21..a595f29567fe 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -382,7 +382,8 @@ static inline int xfs_qm_sync(struct xfs_mount *mp, int flags)  	xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, nb, ni, \  				f | XFS_QMOPT_RES_REGBLKS) -extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *); +extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *, +				xfs_dqid_t, uint, uint, char *);  extern int xfs_mount_reset_sbqflags(struct xfs_mount *);  #endif	/* __KERNEL__ */ diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 12a191385310..8f76fdff4f46 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -76,7 +76,7 @@ xfs_growfs_rt_alloc(  	xfs_mount_t	*mp,		/* file system mount point */  	xfs_extlen_t	oblocks,	/* old count of blocks */  	xfs_extlen_t	nblocks,	/* new count of blocks */ -	xfs_ino_t	ino)		/* inode number (bitmap/summary) */ +	xfs_inode_t	*ip)		/* inode (bitmap/summary) */  {  	xfs_fileoff_t	bno;		/* block number in file */  	xfs_buf_t	*bp;		/* temporary buffer for zeroing */ @@ -86,7 +86,6 @@ xfs_growfs_rt_alloc(  	xfs_fsblock_t	firstblock;	/* first block allocated in xaction */  	xfs_bmap_free_t	flist;		/* list of freed blocks */  	xfs_fsblock_t	fsbno;		/* filesystem block for bno */ -	xfs_inode_t	*ip;		/* pointer to incore inode */  	xfs_bmbt_irec_t	map;		/* block map output */  	int		nmap;		/* number of block maps */  	int		resblks;	/* space reservation */ @@ -112,9 +111,9 @@ xfs_growfs_rt_alloc(  		/*  		 * Lock the inode.  		 */ -		if ((error = xfs_trans_iget(mp, tp, ino, 0, -						XFS_ILOCK_EXCL, &ip))) -			goto error_cancel; +		xfs_ilock(ip, XFS_ILOCK_EXCL); +		xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); +  		xfs_bmap_init(&flist, &firstblock);  		/*  		 * Allocate blocks to the bitmap file. @@ -155,9 +154,8 @@ xfs_growfs_rt_alloc(  			/*  			 * Lock the bitmap inode.  			 */ -			if ((error = xfs_trans_iget(mp, tp, ino, 0, -							XFS_ILOCK_EXCL, &ip))) -				goto error_cancel; +			xfs_ilock(ip, XFS_ILOCK_EXCL); +			xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);  			/*  			 * Get a buffer for the block.  			 */ @@ -1854,7 +1852,6 @@ xfs_growfs_rt(  	xfs_rtblock_t	bmbno;		/* bitmap block number */  	xfs_buf_t	*bp;		/* temporary buffer */  	int		error;		/* error return value */ -	xfs_inode_t	*ip;		/* bitmap inode, used as lock */  	xfs_mount_t	*nmp;		/* new (fake) mount structure */  	xfs_drfsbno_t	nrblocks;	/* new number of realtime blocks */  	xfs_extlen_t	nrbmblocks;	/* new number of rt bitmap blocks */ @@ -1918,11 +1915,11 @@ xfs_growfs_rt(  	/*  	 * Allocate space to the bitmap and summary files, as necessary.  	 */ -	if ((error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, -			mp->m_sb.sb_rbmino))) +	error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip); +	if (error)  		return error; -	if ((error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, -			mp->m_sb.sb_rsumino))) +	error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip); +	if (error)  		return error;  	/*  	 * Allocate a new (fake) mount/sb. @@ -1972,10 +1969,8 @@ xfs_growfs_rt(  		/*  		 * Lock out other callers by grabbing the bitmap inode lock.  		 */ -		if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, -						XFS_ILOCK_EXCL, &ip))) -			goto error_cancel; -		ASSERT(ip == mp->m_rbmip); +		xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); +		xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL);  		/*  		 * Update the bitmap inode's size.  		 */ @@ -1986,10 +1981,8 @@ xfs_growfs_rt(  		/*  		 * Get the summary inode into the transaction.  		 */ -		if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, -						XFS_ILOCK_EXCL, &ip))) -			goto error_cancel; -		ASSERT(ip == mp->m_rsumip); +		xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL); +		xfs_trans_ijoin_ref(tp, mp->m_rsumip, XFS_ILOCK_EXCL);  		/*  		 * Update the summary inode's size.  		 */ @@ -2075,15 +2068,15 @@ xfs_rtallocate_extent(  	xfs_extlen_t	prod,		/* extent product factor */  	xfs_rtblock_t	*rtblock)	/* out: start block allocated */  { +	xfs_mount_t	*mp = tp->t_mountp;  	int		error;		/* error value */ -	xfs_inode_t	*ip;		/* inode for bitmap file */ -	xfs_mount_t	*mp;		/* file system mount structure */  	xfs_rtblock_t	r;		/* result allocated block */  	xfs_fsblock_t	sb;		/* summary file block number */  	xfs_buf_t	*sumbp;		/* summary file block buffer */ +	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));  	ASSERT(minlen > 0 && minlen <= maxlen); -	mp = tp->t_mountp; +  	/*  	 * If prod is set then figure out what to do to minlen and maxlen.  	 */ @@ -2099,12 +2092,7 @@ xfs_rtallocate_extent(  			return 0;  		}  	} -	/* -	 * Lock out other callers by grabbing the bitmap inode lock. -	 */ -	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, -					XFS_ILOCK_EXCL, &ip))) -		return error; +  	sumbp = NULL;  	/*  	 * Allocate by size, or near another block, or exactly at some block. @@ -2123,11 +2111,12 @@ xfs_rtallocate_extent(  				len, &sumbp, &sb, prod, &r);  		break;  	default: +		error = EIO;  		ASSERT(0);  	} -	if (error) { +	if (error)  		return error; -	} +  	/*  	 * If it worked, update the superblock.  	 */ @@ -2155,7 +2144,6 @@ xfs_rtfree_extent(  	xfs_extlen_t	len)		/* length of extent freed */  {  	int		error;		/* error value */ -	xfs_inode_t	*ip;		/* bitmap file inode */  	xfs_mount_t	*mp;		/* file system mount structure */  	xfs_fsblock_t	sb;		/* summary file block number */  	xfs_buf_t	*sumbp;		/* summary file block buffer */ @@ -2164,9 +2152,9 @@ xfs_rtfree_extent(  	/*  	 * Synchronize by locking the bitmap inode.  	 */ -	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, -					XFS_ILOCK_EXCL, &ip))) -		return error; +	xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); +	xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL); +  #if defined(__KERNEL__) && defined(DEBUG)  	/*  	 * Check to see that this whole range is currently allocated. @@ -2199,10 +2187,10 @@ xfs_rtfree_extent(  	 */  	if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==  	    mp->m_sb.sb_rextents) { -		if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) -			ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; -		*(__uint64_t *)&ip->i_d.di_atime = 0; -		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); +		if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) +			mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; +		*(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0; +		xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);  	}  	return 0;  } @@ -2222,8 +2210,8 @@ xfs_rtmount_init(  	if (sbp->sb_rblocks == 0)  		return 0;  	if (mp->m_rtdev_targp == NULL) { -		cmn_err(CE_WARN, -	"XFS: This filesystem has a realtime volume, use rtdev=device option"); +		xfs_warn(mp, +	"Filesystem has a realtime volume, use rtdev=device option");  		return XFS_ERROR(ENODEV);  	}  	mp->m_rsumlevels = sbp->sb_rextslog + 1; @@ -2237,7 +2225,7 @@ xfs_rtmount_init(  	 */  	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);  	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) { -		cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu", +		xfs_warn(mp, "realtime mount -- %llu != %llu",  			(unsigned long long) XFS_BB_TO_FSB(mp, d),  			(unsigned long long) mp->m_sb.sb_rblocks);  		return XFS_ERROR(EFBIG); @@ -2246,7 +2234,7 @@ xfs_rtmount_init(  					d - XFS_FSB_TO_BB(mp, 1),  					XFS_FSB_TO_B(mp, 1), 0);  	if (!bp) { -		cmn_err(CE_WARN, "XFS: realtime device size check failed"); +		xfs_warn(mp, "realtime device size check failed");  		return EIO;  	}  	xfs_buf_relse(bp); @@ -2306,20 +2294,16 @@ xfs_rtpick_extent(  	xfs_rtblock_t	*pick)		/* result rt extent */  {  	xfs_rtblock_t	b;		/* result block */ -	int		error;		/* error return value */ -	xfs_inode_t	*ip;		/* bitmap incore inode */  	int		log2;		/* log of sequence number */  	__uint64_t	resid;		/* residual after log removed */  	__uint64_t	seq;		/* sequence number of file creation */  	__uint64_t	*seqp;		/* pointer to seqno in inode */ -	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, -					XFS_ILOCK_EXCL, &ip))) -		return error; -	ASSERT(ip == mp->m_rbmip); -	seqp = (__uint64_t *)&ip->i_d.di_atime; -	if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) { -		ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; +	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); + +	seqp = (__uint64_t *)&mp->m_rbmip->i_d.di_atime; +	if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) { +		mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;  		*seqp = 0;  	}  	seq = *seqp; @@ -2335,7 +2319,7 @@ xfs_rtpick_extent(  			b = mp->m_sb.sb_rextents - len;  	}  	*seqp = seq + 1; -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); +	xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);  	*pick = b;  	return 0;  } diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h index ff614c29b441..09e1f4f35e97 100644 --- a/fs/xfs/xfs_rtalloc.h +++ b/fs/xfs/xfs_rtalloc.h @@ -154,7 +154,7 @@ xfs_rtmount_init(  	if (mp->m_sb.sb_rblocks == 0)  		return 0; -	cmn_err(CE_WARN, "XFS: Not built with CONFIG_XFS_RT"); +	xfs_warn(mp, "Not built with CONFIG_XFS_RT");  	return ENOSYS;  }  # define xfs_rtmount_inodes(m)  (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index 56861d5daaef..d6d6fdfe9422 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -49,9 +49,9 @@ xfs_do_force_shutdown(  	logerror = flags & SHUTDOWN_LOG_IO_ERROR;  	if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { -		cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from " -				 "line %d of file %s.  Return address = 0x%p", -			mp->m_fsname, flags, lnnum, fname, __return_address); +		xfs_notice(mp, +	"%s(0x%x) called from line %d of file %s.  Return address = 0x%p", +			__func__, flags, lnnum, fname, __return_address);  	}  	/*  	 * No need to duplicate efforts. @@ -69,30 +69,25 @@ xfs_do_force_shutdown(  		return;  	if (flags & SHUTDOWN_CORRUPT_INCORE) { -		xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, -    "Corruption of in-memory data detected.  Shutting down filesystem: %s", -			mp->m_fsname); -		if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { +		xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_CORRUPT, +    "Corruption of in-memory data detected.  Shutting down filesystem"); +		if (XFS_ERRLEVEL_HIGH <= xfs_error_level)  			xfs_stack_trace(); -		}  	} else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {  		if (logerror) { -			xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, -		"Log I/O Error Detected.  Shutting down filesystem: %s", -				mp->m_fsname); +			xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_LOGERROR, +		"Log I/O Error Detected.  Shutting down filesystem");  		} else if (flags & SHUTDOWN_DEVICE_REQ) { -			xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, -		"All device paths lost.  Shutting down filesystem: %s", -				mp->m_fsname); +			xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR, +		"All device paths lost.  Shutting down filesystem");  		} else if (!(flags & SHUTDOWN_REMOTE_REQ)) { -			xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, -		"I/O Error Detected.  Shutting down filesystem: %s", -				mp->m_fsname); +			xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR, +		"I/O Error Detected. Shutting down filesystem");  		}  	}  	if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { -		cmn_err(CE_ALERT, "Please umount the filesystem, " -				  "and rectify the problem(s)"); +		xfs_alert(mp, +	"Please umount the filesystem and rectify the problem(s)");  	}  } @@ -106,10 +101,9 @@ xfs_ioerror_alert(  	xfs_buf_t		*bp,  	xfs_daddr_t		blkno)  { -	cmn_err(CE_ALERT, - "I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx" - "       (\"%s\") error %d buf count %zd", -		(!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname, +	xfs_alert(mp, +		 "I/O error occurred: meta-data dev %s block 0x%llx" +		 "       (\"%s\") error %d buf count %zd",  		XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),  		(__uint64_t)blkno, func,  		XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp)); @@ -173,17 +167,9 @@ xfs_extlen_t  xfs_get_extsz_hint(  	struct xfs_inode	*ip)  { -	xfs_extlen_t		extsz; - -	if (unlikely(XFS_IS_REALTIME_INODE(ip))) { -		extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) -				? ip->i_d.di_extsize -				: ip->i_mount->m_sb.sb_rextsize; -		ASSERT(extsz); -	} else { -		extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) -				? ip->i_d.di_extsize : 0; -	} - -	return extsz; +	if ((ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) && ip->i_d.di_extsize) +		return ip->i_d.di_extsize; +	if (XFS_IS_REALTIME_INODE(ip)) +		return ip->i_mount->m_sb.sb_rextsize; +	return 0;  } diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index c2042b736b81..06a9759b6352 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -469,8 +469,6 @@ void		xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *);  void		xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *);  void		xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);  void		xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); -int		xfs_trans_iget(struct xfs_mount *, xfs_trans_t *, -			       xfs_ino_t , uint, uint, struct xfs_inode **);  void		xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);  void		xfs_trans_ijoin_ref(struct xfs_trans *, struct xfs_inode *, uint);  void		xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *); diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index c5bbbc45db91..acdb92f14d51 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -28,74 +28,138 @@  #include "xfs_trans_priv.h"  #include "xfs_error.h" -STATIC void xfs_ail_splice(struct xfs_ail *, struct list_head *, xfs_lsn_t); -STATIC void xfs_ail_delete(struct xfs_ail *, xfs_log_item_t *); -STATIC xfs_log_item_t * xfs_ail_min(struct xfs_ail *); -STATIC xfs_log_item_t * xfs_ail_next(struct xfs_ail *, xfs_log_item_t *); +struct workqueue_struct	*xfs_ail_wq;	/* AIL workqueue */  #ifdef DEBUG -STATIC void xfs_ail_check(struct xfs_ail *, xfs_log_item_t *); -#else +/* + * Check that the list is sorted as it should be. + */ +STATIC void +xfs_ail_check( +	struct xfs_ail	*ailp, +	xfs_log_item_t	*lip) +{ +	xfs_log_item_t	*prev_lip; + +	if (list_empty(&ailp->xa_ail)) +		return; + +	/* +	 * Check the next and previous entries are valid. +	 */ +	ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0); +	prev_lip = list_entry(lip->li_ail.prev, xfs_log_item_t, li_ail); +	if (&prev_lip->li_ail != &ailp->xa_ail) +		ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0); + +	prev_lip = list_entry(lip->li_ail.next, xfs_log_item_t, li_ail); +	if (&prev_lip->li_ail != &ailp->xa_ail) +		ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0); + + +#ifdef XFS_TRANS_DEBUG +	/* +	 * Walk the list checking lsn ordering, and that every entry has the +	 * XFS_LI_IN_AIL flag set. This is really expensive, so only do it +	 * when specifically debugging the transaction subsystem. +	 */ +	prev_lip = list_entry(&ailp->xa_ail, xfs_log_item_t, li_ail); +	list_for_each_entry(lip, &ailp->xa_ail, li_ail) { +		if (&prev_lip->li_ail != &ailp->xa_ail) +			ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0); +		ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0); +		prev_lip = lip; +	} +#endif /* XFS_TRANS_DEBUG */ +} +#else /* !DEBUG */  #define	xfs_ail_check(a,l)  #endif /* DEBUG */ +/* + * Return a pointer to the first item in the AIL.  If the AIL is empty, then + * return NULL. + */ +static xfs_log_item_t * +xfs_ail_min( +	struct xfs_ail  *ailp) +{ +	if (list_empty(&ailp->xa_ail)) +		return NULL; + +	return list_first_entry(&ailp->xa_ail, xfs_log_item_t, li_ail); +} + + /* + * Return a pointer to the last item in the AIL.  If the AIL is empty, then + * return NULL. + */ +static xfs_log_item_t * +xfs_ail_max( +	struct xfs_ail  *ailp) +{ +	if (list_empty(&ailp->xa_ail)) +		return NULL; + +	return list_entry(ailp->xa_ail.prev, xfs_log_item_t, li_ail); +} + +/* + * Return a pointer to the item which follows the given item in the AIL.  If + * the given item is the last item in the list, then return NULL. + */ +static xfs_log_item_t * +xfs_ail_next( +	struct xfs_ail  *ailp, +	xfs_log_item_t  *lip) +{ +	if (lip->li_ail.next == &ailp->xa_ail) +		return NULL; + +	return list_first_entry(&lip->li_ail, xfs_log_item_t, li_ail); +}  /* - * This is called by the log manager code to determine the LSN - * of the tail of the log.  This is exactly the LSN of the first - * item in the AIL.  If the AIL is empty, then this function - * returns 0. + * This is called by the log manager code to determine the LSN of the tail of + * the log.  This is exactly the LSN of the first item in the AIL.  If the AIL + * is empty, then this function returns 0.   * - * We need the AIL lock in order to get a coherent read of the - * lsn of the last item in the AIL. + * We need the AIL lock in order to get a coherent read of the lsn of the last + * item in the AIL.   */  xfs_lsn_t -xfs_trans_ail_tail( +xfs_ail_min_lsn(  	struct xfs_ail	*ailp)  { -	xfs_lsn_t	lsn; +	xfs_lsn_t	lsn = 0;  	xfs_log_item_t	*lip;  	spin_lock(&ailp->xa_lock);  	lip = xfs_ail_min(ailp); -	if (lip == NULL) { -		lsn = (xfs_lsn_t)0; -	} else { +	if (lip)  		lsn = lip->li_lsn; -	}  	spin_unlock(&ailp->xa_lock);  	return lsn;  }  /* - * xfs_trans_push_ail - * - * This routine is called to move the tail of the AIL forward.  It does this by - * trying to flush items in the AIL whose lsns are below the given - * threshold_lsn. - * - * the push is run asynchronously in a separate thread, so we return the tail - * of the log right now instead of the tail after the push. This means we will - * either continue right away, or we will sleep waiting on the async thread to - * do its work. - * - * We do this unlocked - we only need to know whether there is anything in the - * AIL at the time we are called. We don't need to access the contents of - * any of the objects, so the lock is not needed. + * Return the maximum lsn held in the AIL, or zero if the AIL is empty.   */ -void -xfs_trans_ail_push( -	struct xfs_ail	*ailp, -	xfs_lsn_t	threshold_lsn) +static xfs_lsn_t +xfs_ail_max_lsn( +	struct xfs_ail  *ailp)  { -	xfs_log_item_t	*lip; +	xfs_lsn_t       lsn = 0; +	xfs_log_item_t  *lip; -	lip = xfs_ail_min(ailp); -	if (lip && !XFS_FORCED_SHUTDOWN(ailp->xa_mount)) { -		if (XFS_LSN_CMP(threshold_lsn, ailp->xa_target) > 0) -			xfsaild_wakeup(ailp, threshold_lsn); -	} +	spin_lock(&ailp->xa_lock); +	lip = xfs_ail_max(ailp); +	if (lip) +		lsn = lip->li_lsn; +	spin_unlock(&ailp->xa_lock); + +	return lsn;  }  /* @@ -236,16 +300,57 @@ out:  }  /* - * xfsaild_push does the work of pushing on the AIL.  Returning a timeout of - * zero indicates that the caller should sleep until woken. + * splice the log item list into the AIL at the given LSN.   */ -long -xfsaild_push( -	struct xfs_ail	*ailp, -	xfs_lsn_t	*last_lsn) +static void +xfs_ail_splice( +	struct xfs_ail  *ailp, +	struct list_head *list, +	xfs_lsn_t       lsn)  { -	long		tout = 0; -	xfs_lsn_t	last_pushed_lsn = *last_lsn; +	xfs_log_item_t  *next_lip; + +	/* If the list is empty, just insert the item.  */ +	if (list_empty(&ailp->xa_ail)) { +		list_splice(list, &ailp->xa_ail); +		return; +	} + +	list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) { +		if (XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0) +			break; +	} + +	ASSERT(&next_lip->li_ail == &ailp->xa_ail || +	       XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0); + +	list_splice_init(list, &next_lip->li_ail); +} + +/* + * Delete the given item from the AIL.  Return a pointer to the item. + */ +static void +xfs_ail_delete( +	struct xfs_ail  *ailp, +	xfs_log_item_t  *lip) +{ +	xfs_ail_check(ailp, lip); +	list_del(&lip->li_ail); +	xfs_trans_ail_cursor_clear(ailp, lip); +} + +/* + * xfs_ail_worker does the work of pushing on the AIL. It will requeue itself + * to run at a later time if there is more work to do to complete the push. + */ +STATIC void +xfs_ail_worker( +	struct work_struct *work) +{ +	struct xfs_ail	*ailp = container_of(to_delayed_work(work), +					struct xfs_ail, xa_work); +	long		tout;  	xfs_lsn_t	target =  ailp->xa_target;  	xfs_lsn_t	lsn;  	xfs_log_item_t	*lip; @@ -256,15 +361,15 @@ xfsaild_push(  	spin_lock(&ailp->xa_lock);  	xfs_trans_ail_cursor_init(ailp, cur); -	lip = xfs_trans_ail_cursor_first(ailp, cur, *last_lsn); +	lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn);  	if (!lip || XFS_FORCED_SHUTDOWN(mp)) {  		/*  		 * AIL is empty or our push has reached the end.  		 */  		xfs_trans_ail_cursor_done(ailp, cur);  		spin_unlock(&ailp->xa_lock); -		*last_lsn = 0; -		return tout; +		ailp->xa_last_pushed_lsn = 0; +		return;  	}  	XFS_STATS_INC(xs_push_ail); @@ -301,13 +406,13 @@ xfsaild_push(  		case XFS_ITEM_SUCCESS:  			XFS_STATS_INC(xs_push_ail_success);  			IOP_PUSH(lip); -			last_pushed_lsn = lsn; +			ailp->xa_last_pushed_lsn = lsn;  			break;  		case XFS_ITEM_PUSHBUF:  			XFS_STATS_INC(xs_push_ail_pushbuf);  			IOP_PUSHBUF(lip); -			last_pushed_lsn = lsn; +			ailp->xa_last_pushed_lsn = lsn;  			push_xfsbufd = 1;  			break; @@ -319,7 +424,7 @@ xfsaild_push(  		case XFS_ITEM_LOCKED:  			XFS_STATS_INC(xs_push_ail_locked); -			last_pushed_lsn = lsn; +			ailp->xa_last_pushed_lsn = lsn;  			stuck++;  			break; @@ -374,9 +479,23 @@ xfsaild_push(  		wake_up_process(mp->m_ddev_targp->bt_task);  	} +	/* assume we have more work to do in a short while */ +	tout = 10;  	if (!count) {  		/* We're past our target or empty, so idle */ -		last_pushed_lsn = 0; +		ailp->xa_last_pushed_lsn = 0; + +		/* +		 * Check for an updated push target before clearing the +		 * XFS_AIL_PUSHING_BIT. If the target changed, we've got more +		 * work to do. Wait a bit longer before starting that work. +		 */ +		smp_rmb(); +		if (ailp->xa_target == target) { +			clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags); +			return; +		} +		tout = 50;  	} else if (XFS_LSN_CMP(lsn, target) >= 0) {  		/*  		 * We reached the target so wait a bit longer for I/O to @@ -384,7 +503,7 @@ xfsaild_push(  		 * start the next scan from the start of the AIL.  		 */  		tout = 50; -		last_pushed_lsn = 0; +		ailp->xa_last_pushed_lsn = 0;  	} else if ((stuck * 100) / count > 90) {  		/*  		 * Either there is a lot of contention on the AIL or we @@ -396,14 +515,61 @@ xfsaild_push(  		 * continuing from where we were.  		 */  		tout = 20; -	} else { -		/* more to do, but wait a short while before continuing */ -		tout = 10;  	} -	*last_lsn = last_pushed_lsn; -	return tout; + +	/* There is more to do, requeue us.  */ +	queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, +					msecs_to_jiffies(tout)); +} + +/* + * This routine is called to move the tail of the AIL forward.  It does this by + * trying to flush items in the AIL whose lsns are below the given + * threshold_lsn. + * + * The push is run asynchronously in a workqueue, which means the caller needs + * to handle waiting on the async flush for space to become available. + * We don't want to interrupt any push that is in progress, hence we only queue + * work if we set the pushing bit approriately. + * + * We do this unlocked - we only need to know whether there is anything in the + * AIL at the time we are called. We don't need to access the contents of + * any of the objects, so the lock is not needed. + */ +void +xfs_ail_push( +	struct xfs_ail	*ailp, +	xfs_lsn_t	threshold_lsn) +{ +	xfs_log_item_t	*lip; + +	lip = xfs_ail_min(ailp); +	if (!lip || XFS_FORCED_SHUTDOWN(ailp->xa_mount) || +	    XFS_LSN_CMP(threshold_lsn, ailp->xa_target) <= 0) +		return; + +	/* +	 * Ensure that the new target is noticed in push code before it clears +	 * the XFS_AIL_PUSHING_BIT. +	 */ +	smp_wmb(); +	ailp->xa_target = threshold_lsn; +	if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) +		queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0);  } +/* + * Push out all items in the AIL immediately + */ +void +xfs_ail_push_all( +	struct xfs_ail  *ailp) +{ +	xfs_lsn_t       threshold_lsn = xfs_ail_max_lsn(ailp); + +	if (threshold_lsn) +		xfs_ail_push(ailp, threshold_lsn); +}  /*   * This is to be called when an item is unlocked that may have @@ -563,7 +729,7 @@ xfs_trans_ail_delete_bulk(  			spin_unlock(&ailp->xa_lock);  			if (!XFS_FORCED_SHUTDOWN(mp)) { -				xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp, +				xfs_alert_tag(mp, XFS_PTAG_AILDELETE,  		"%s: attempting to delete a log item that is not in the AIL",  						__func__);  				xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); @@ -615,7 +781,6 @@ xfs_trans_ail_init(  	xfs_mount_t	*mp)  {  	struct xfs_ail	*ailp; -	int		error;  	ailp = kmem_zalloc(sizeof(struct xfs_ail), KM_MAYFAIL);  	if (!ailp) @@ -624,15 +789,9 @@ xfs_trans_ail_init(  	ailp->xa_mount = mp;  	INIT_LIST_HEAD(&ailp->xa_ail);  	spin_lock_init(&ailp->xa_lock); -	error = xfsaild_start(ailp); -	if (error) -		goto out_free_ailp; +	INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker);  	mp->m_ail = ailp;  	return 0; - -out_free_ailp: -	kmem_free(ailp); -	return error;  }  void @@ -641,124 +800,6 @@ xfs_trans_ail_destroy(  {  	struct xfs_ail	*ailp = mp->m_ail; -	xfsaild_stop(ailp); +	cancel_delayed_work_sync(&ailp->xa_work);  	kmem_free(ailp);  } - -/* - * splice the log item list into the AIL at the given LSN. - */ -STATIC void -xfs_ail_splice( -	struct xfs_ail	*ailp, -	struct list_head *list, -	xfs_lsn_t	lsn) -{ -	xfs_log_item_t	*next_lip; - -	/* -	 * If the list is empty, just insert the item. -	 */ -	if (list_empty(&ailp->xa_ail)) { -		list_splice(list, &ailp->xa_ail); -		return; -	} - -	list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) { -		if (XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0) -			break; -	} - -	ASSERT((&next_lip->li_ail == &ailp->xa_ail) || -	       (XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0)); - -	list_splice_init(list, &next_lip->li_ail); -	return; -} - -/* - * Delete the given item from the AIL.  Return a pointer to the item. - */ -STATIC void -xfs_ail_delete( -	struct xfs_ail	*ailp, -	xfs_log_item_t	*lip) -{ -	xfs_ail_check(ailp, lip); -	list_del(&lip->li_ail); -	xfs_trans_ail_cursor_clear(ailp, lip); -} - -/* - * Return a pointer to the first item in the AIL. - * If the AIL is empty, then return NULL. - */ -STATIC xfs_log_item_t * -xfs_ail_min( -	struct xfs_ail	*ailp) -{ -	if (list_empty(&ailp->xa_ail)) -		return NULL; - -	return list_first_entry(&ailp->xa_ail, xfs_log_item_t, li_ail); -} - -/* - * Return a pointer to the item which follows - * the given item in the AIL.  If the given item - * is the last item in the list, then return NULL. - */ -STATIC xfs_log_item_t * -xfs_ail_next( -	struct xfs_ail	*ailp, -	xfs_log_item_t	*lip) -{ -	if (lip->li_ail.next == &ailp->xa_ail) -		return NULL; - -	return list_first_entry(&lip->li_ail, xfs_log_item_t, li_ail); -} - -#ifdef DEBUG -/* - * Check that the list is sorted as it should be. - */ -STATIC void -xfs_ail_check( -	struct xfs_ail	*ailp, -	xfs_log_item_t	*lip) -{ -	xfs_log_item_t	*prev_lip; - -	if (list_empty(&ailp->xa_ail)) -		return; - -	/* -	 * Check the next and previous entries are valid. -	 */ -	ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0); -	prev_lip = list_entry(lip->li_ail.prev, xfs_log_item_t, li_ail); -	if (&prev_lip->li_ail != &ailp->xa_ail) -		ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0); - -	prev_lip = list_entry(lip->li_ail.next, xfs_log_item_t, li_ail); -	if (&prev_lip->li_ail != &ailp->xa_ail) -		ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0); - - -#ifdef XFS_TRANS_DEBUG -	/* -	 * Walk the list checking lsn ordering, and that every entry has the -	 * XFS_LI_IN_AIL flag set. This is really expensive, so only do it -	 * when specifically debugging the transaction subsystem. -	 */ -	prev_lip = list_entry(&ailp->xa_ail, xfs_log_item_t, li_ail); -	list_for_each_entry(lip, &ailp->xa_ail, li_ail) { -		if (&prev_lip->li_ail != &ailp->xa_ail) -			ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0); -		ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0); -		prev_lip = lip; -	} -#endif /* XFS_TRANS_DEBUG */ -} -#endif /* DEBUG */ diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index c47918c302a5..03b3b7f85a3b 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -305,7 +305,7 @@ xfs_trans_read_buf(  			if (xfs_error_target == target) {  				if (((xfs_req_num++) % xfs_error_mod) == 0) {  					xfs_buf_relse(bp); -					cmn_err(CE_DEBUG, "Returning error!\n"); +					xfs_debug(mp, "Returning error!");  					return XFS_ERROR(EIO);  				}  			} @@ -383,7 +383,8 @@ xfs_trans_read_buf(  	bp = xfs_buf_read(target, blkno, len, flags | XBF_DONT_BLOCK);  	if (bp == NULL) {  		*bpp = NULL; -		return 0; +		return (flags & XBF_TRYLOCK) ? +					0 : XFS_ERROR(ENOMEM);  	}  	if (XFS_BUF_GETERROR(bp) != 0) {  	    XFS_BUF_SUPER_STALE(bp); @@ -403,7 +404,7 @@ xfs_trans_read_buf(  				xfs_force_shutdown(tp->t_mountp,  						   SHUTDOWN_META_IO_ERROR);  				xfs_buf_relse(bp); -				cmn_err(CE_DEBUG, "Returning trans error!\n"); +				xfs_debug(mp, "Returning trans error!");  				return XFS_ERROR(EIO);  			}  		} @@ -427,7 +428,7 @@ shutdown_abort:  	 */  #if defined(DEBUG)  	if (XFS_BUF_ISSTALE(bp) && XFS_BUF_ISDELAYWRITE(bp)) -		cmn_err(CE_NOTE, "about to pop assert, bp == 0x%p", bp); +		xfs_notice(mp, "about to pop assert, bp == 0x%p", bp);  #endif  	ASSERT((XFS_BUF_BFLAGS(bp) & (XBF_STALE|XBF_DELWRI)) !=  				     (XBF_STALE|XBF_DELWRI)); diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index ccb34532768b..048b0c689d3e 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c @@ -44,28 +44,6 @@ xfs_trans_inode_broot_debug(  #endif  /* - * Get an inode and join it to the transaction. - */ -int -xfs_trans_iget( -	xfs_mount_t	*mp, -	xfs_trans_t	*tp, -	xfs_ino_t	ino, -	uint		flags, -	uint		lock_flags, -	xfs_inode_t	**ipp) -{ -	int			error; - -	error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp); -	if (!error && tp) { -		xfs_trans_ijoin(tp, *ipp); -		(*ipp)->i_itemp->ili_lock_flags = lock_flags; -	} -	return error; -} - -/*   * Add a locked inode to the transaction.   *   * The inode must be locked, and it cannot be associated with any transaction. @@ -103,7 +81,7 @@ xfs_trans_ijoin(   *   *   * Grabs a reference to the inode which will be dropped when the transaction - * is commited.  The inode will also be unlocked at that point.  The inode + * is committed.  The inode will also be unlocked at that point.  The inode   * must be locked, and it cannot be associated with any transaction.   */  void diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h index 35162c238fa3..6b164e9e9a1f 100644 --- a/fs/xfs/xfs_trans_priv.h +++ b/fs/xfs/xfs_trans_priv.h @@ -65,16 +65,22 @@ struct xfs_ail_cursor {  struct xfs_ail {  	struct xfs_mount	*xa_mount;  	struct list_head	xa_ail; -	uint			xa_gen; -	struct task_struct	*xa_task;  	xfs_lsn_t		xa_target;  	struct xfs_ail_cursor	xa_cursors;  	spinlock_t		xa_lock; +	struct delayed_work	xa_work; +	xfs_lsn_t		xa_last_pushed_lsn; +	unsigned long		xa_flags;  }; +#define XFS_AIL_PUSHING_BIT	0 +  /*   * From xfs_trans_ail.c   */ + +extern struct workqueue_struct	*xfs_ail_wq;	/* AIL workqueue */ +  void	xfs_trans_ail_update_bulk(struct xfs_ail *ailp,  				struct xfs_log_item **log_items, int nr_items,  				xfs_lsn_t lsn) __releases(ailp->xa_lock); @@ -98,12 +104,13 @@ xfs_trans_ail_delete(  	xfs_trans_ail_delete_bulk(ailp, &lip, 1);  } -void			xfs_trans_ail_push(struct xfs_ail *, xfs_lsn_t); +void			xfs_ail_push(struct xfs_ail *, xfs_lsn_t); +void			xfs_ail_push_all(struct xfs_ail *); +xfs_lsn_t		xfs_ail_min_lsn(struct xfs_ail *ailp); +  void			xfs_trans_unlocked_item(struct xfs_ail *,  					xfs_log_item_t *); -xfs_lsn_t		xfs_trans_ail_tail(struct xfs_ail *ailp); -  struct xfs_log_item	*xfs_trans_ail_cursor_first(struct xfs_ail *ailp,  					struct xfs_ail_cursor *cur,  					xfs_lsn_t lsn); @@ -112,11 +119,6 @@ struct xfs_log_item	*xfs_trans_ail_cursor_next(struct xfs_ail *ailp,  void			xfs_trans_ail_cursor_done(struct xfs_ail *ailp,  					struct xfs_ail_cursor *cur); -long	xfsaild_push(struct xfs_ail *, xfs_lsn_t *); -void	xfsaild_wakeup(struct xfs_ail *, xfs_lsn_t); -int	xfsaild_start(struct xfs_ail *); -void	xfsaild_stop(struct xfs_ail *); -  #if BITS_PER_LONG != 64  static inline void  xfs_trans_ail_copy_lsn( diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index d8e6f8cd6f0c..b7a5fe7c52c8 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -953,7 +953,7 @@ xfs_release(  		 * If we previously truncated this file and removed old data  		 * in the process, we want to initiate "early" writeout on  		 * the last close.  This is an attempt to combat the notorious -		 * NULL files problem which is particularly noticable from a +		 * NULL files problem which is particularly noticeable from a  		 * truncate down, buffered (re-)write (delalloc), followed by  		 * a crash.  What we are effectively doing here is  		 * significantly reducing the time window where we'd otherwise @@ -982,7 +982,7 @@ xfs_release(  		 *  		 * Further, check if the inode is being opened, written and  		 * closed frequently and we have delayed allocation blocks -		 * oustanding (e.g. streaming writes from the NFS server), +		 * outstanding (e.g. streaming writes from the NFS server),  		 * truncating the blocks past EOF will cause fragmentation to  		 * occur.  		 * @@ -1189,9 +1189,8 @@ xfs_inactive(  		 * inode might be lost for a long time or forever.  		 */  		if (!XFS_FORCED_SHUTDOWN(mp)) { -			cmn_err(CE_NOTE, -		"xfs_inactive:	xfs_ifree() returned an error = %d on %s", -				error, mp->m_fsname); +			xfs_notice(mp, "%s: xfs_ifree returned error %d", +				__func__, error);  			xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);  		}  		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); @@ -1208,12 +1207,12 @@ xfs_inactive(  		 */  		error = xfs_bmap_finish(&tp,  &free_list, &committed);  		if (error) -			xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: " -				"xfs_bmap_finish() returned error %d", error); +			xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", +				__func__, error);  		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);  		if (error) -			xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: " -				"xfs_trans_commit() returned error %d", error); +			xfs_notice(mp, "%s: xfs_trans_commit returned error %d", +				__func__, error);  	}  	/* @@ -1310,7 +1309,7 @@ xfs_create(  	error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,  			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);  	if (error) -		goto std_return; +		return error;  	if (is_dir) {  		rdev = 0; @@ -1390,12 +1389,6 @@ xfs_create(  	}  	/* -	 * At this point, we've gotten a newly allocated inode. -	 * It is locked (and joined to the transaction). -	 */ -	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); - -	/*  	 * Now we join the directory inode to the transaction.  We do not do it  	 * earlier because xfs_dir_ialloc might commit the previous transaction  	 * (and release all the locks).  An error from here on will result in @@ -1440,22 +1433,13 @@ xfs_create(  	 */  	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); -	/* -	 * xfs_trans_commit normally decrements the vnode ref count -	 * when it unlocks the inode. Since we want to return the -	 * vnode to the caller, we bump the vnode ref count now. -	 */ -	IHOLD(ip); -  	error = xfs_bmap_finish(&tp, &free_list, &committed);  	if (error) -		goto out_abort_rele; +		goto out_bmap_cancel;  	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); -	if (error) { -		IRELE(ip); -		goto out_dqrele; -	} +	if (error) +		goto out_release_inode;  	xfs_qm_dqrele(udqp);  	xfs_qm_dqrele(gdqp); @@ -1469,27 +1453,21 @@ xfs_create(  	cancel_flags |= XFS_TRANS_ABORT;   out_trans_cancel:  	xfs_trans_cancel(tp, cancel_flags); - out_dqrele: + out_release_inode: +	/* +	 * Wait until after the current transaction is aborted to +	 * release the inode.  This prevents recursive transactions +	 * and deadlocks from xfs_inactive. +	 */ +	if (ip) +		IRELE(ip); +  	xfs_qm_dqrele(udqp);  	xfs_qm_dqrele(gdqp);  	if (unlock_dp_on_error)  		xfs_iunlock(dp, XFS_ILOCK_EXCL); - std_return:  	return error; - - out_abort_rele: -	/* -	 * Wait until after the current transaction is aborted to -	 * release the inode.  This prevents recursive transactions -	 * and deadlocks from xfs_inactive. -	 */ -	xfs_bmap_cancel(&free_list); -	cancel_flags |= XFS_TRANS_ABORT; -	xfs_trans_cancel(tp, cancel_flags); -	IRELE(ip); -	unlock_dp_on_error = B_FALSE; -	goto out_dqrele;  }  #ifdef DEBUG @@ -2114,9 +2092,8 @@ xfs_symlink(  				  XFS_BMAPI_WRITE | XFS_BMAPI_METADATA,  				  &first_block, resblks, mval, &nmaps,  				  &free_list); -		if (error) { -			goto error1; -		} +		if (error) +			goto error2;  		if (resblks)  			resblks -= fs_blocks; @@ -2148,7 +2125,7 @@ xfs_symlink(  	error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,  					&first_block, &free_list, resblks);  	if (error) -		goto error1; +		goto error2;  	xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);  	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); @@ -2161,13 +2138,6 @@ xfs_symlink(  		xfs_trans_set_sync(tp);  	} -	/* -	 * xfs_trans_commit normally decrements the vnode ref count -	 * when it unlocks the inode. Since we want to return the -	 * vnode to the caller, we bump the vnode ref count now. -	 */ -	IHOLD(ip); -  	error = xfs_bmap_finish(&tp, &free_list, &committed);  	if (error) {  		goto error2; @@ -2861,7 +2831,8 @@ xfs_change_file_space(  		ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); -	xfs_trans_set_sync(tp); +	if (attr_flags & XFS_ATTR_SYNC) +		xfs_trans_set_sync(tp);  	error = xfs_trans_commit(tp, 0); diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h index f6702927eee4..3bcd23353d6c 100644 --- a/fs/xfs/xfs_vnodeops.h +++ b/fs/xfs/xfs_vnodeops.h @@ -18,6 +18,7 @@ int xfs_setattr(struct xfs_inode *ip, struct iattr *vap, int flags);  #define	XFS_ATTR_NONBLOCK	0x02	/* return EAGAIN if operation would block */  #define XFS_ATTR_NOLOCK		0x04	/* Don't grab any conflicting locks */  #define XFS_ATTR_NOACL		0x08	/* Don't call xfs_acl_chmod */ +#define XFS_ATTR_SYNC		0x10	/* synchronous operation required */  int xfs_readlink(struct xfs_inode *ip, char *link);  int xfs_release(struct xfs_inode *ip);  | 
