xref: /openbmc/linux/fs/jfs/jfs_extent.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *   Copyright (C) International Business Machines Corp., 2000-2004
41da177e4SLinus Torvalds  */
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds #include <linux/fs.h>
71da177e4SLinus Torvalds #include <linux/quotaops.h>
81da177e4SLinus Torvalds #include "jfs_incore.h"
91868f4aaSDave Kleikamp #include "jfs_inode.h"
101da177e4SLinus Torvalds #include "jfs_superblock.h"
111da177e4SLinus Torvalds #include "jfs_dmap.h"
121da177e4SLinus Torvalds #include "jfs_extent.h"
131da177e4SLinus Torvalds #include "jfs_debug.h"
141da177e4SLinus Torvalds 
151da177e4SLinus Torvalds /*
161da177e4SLinus Torvalds  * forward references
171da177e4SLinus Torvalds  */
181da177e4SLinus Torvalds static int extBalloc(struct inode *, s64, s64 *, s64 *);
191da177e4SLinus Torvalds static s64 extRoundDown(s64 nb);
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds #define DPD(a)		(printk("(a): %d\n",(a)))
221da177e4SLinus Torvalds #define DPC(a)		(printk("(a): %c\n",(a)))
231da177e4SLinus Torvalds #define DPL1(a)					\
241da177e4SLinus Torvalds {						\
251da177e4SLinus Torvalds 	if ((a) >> 32)				\
261da177e4SLinus Torvalds 		printk("(a): %x%08x  ",(a));	\
271da177e4SLinus Torvalds 	else					\
281da177e4SLinus Torvalds 		printk("(a): %x  ",(a) << 32);	\
291da177e4SLinus Torvalds }
301da177e4SLinus Torvalds #define DPL(a)					\
311da177e4SLinus Torvalds {						\
321da177e4SLinus Torvalds 	if ((a) >> 32)				\
331da177e4SLinus Torvalds 		printk("(a): %x%08x\n",(a));	\
341da177e4SLinus Torvalds 	else					\
351da177e4SLinus Torvalds 		printk("(a): %x\n",(a) << 32);	\
361da177e4SLinus Torvalds }
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds #define DPD1(a)		(printk("(a): %d  ",(a)))
391da177e4SLinus Torvalds #define DPX(a)		(printk("(a): %08x\n",(a)))
401da177e4SLinus Torvalds #define DPX1(a)		(printk("(a): %08x  ",(a)))
411da177e4SLinus Torvalds #define DPS(a)		(printk("%s\n",(a)))
421da177e4SLinus Torvalds #define DPE(a)		(printk("\nENTERING: %s\n",(a)))
431da177e4SLinus Torvalds #define DPE1(a)		(printk("\nENTERING: %s",(a)))
441da177e4SLinus Torvalds #define DPS1(a)		(printk("  %s  ",(a)))
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds /*
481da177e4SLinus Torvalds  * NAME:	extAlloc()
491da177e4SLinus Torvalds  *
501da177e4SLinus Torvalds  * FUNCTION:	allocate an extent for a specified page range within a
511da177e4SLinus Torvalds  *		file.
521da177e4SLinus Torvalds  *
531da177e4SLinus Torvalds  * PARAMETERS:
541da177e4SLinus Torvalds  *	ip	- the inode of the file.
551da177e4SLinus Torvalds  *	xlen	- requested extent length.
561da177e4SLinus Torvalds  *	pno	- the starting page number with the file.
571da177e4SLinus Torvalds  *	xp	- pointer to an xad.  on entry, xad describes an
581da177e4SLinus Torvalds  *		  extent that is used as an allocation hint if the
591da177e4SLinus Torvalds  *		  xaddr of the xad is non-zero.  on successful exit,
601da177e4SLinus Torvalds  *		  the xad describes the newly allocated extent.
614d81715fSRichard Knutsson  *	abnr	- bool indicating whether the newly allocated extent
621da177e4SLinus Torvalds  *		  should be marked as allocated but not recorded.
631da177e4SLinus Torvalds  *
641da177e4SLinus Torvalds  * RETURN VALUES:
651da177e4SLinus Torvalds  *	0	- success
661da177e4SLinus Torvalds  *	-EIO	- i/o error.
671da177e4SLinus Torvalds  *	-ENOSPC	- insufficient disk resources.
681da177e4SLinus Torvalds  */
691da177e4SLinus Torvalds int
extAlloc(struct inode * ip,s64 xlen,s64 pno,xad_t * xp,bool abnr)704d81715fSRichard Knutsson extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
711da177e4SLinus Torvalds {
721da177e4SLinus Torvalds 	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
731da177e4SLinus Torvalds 	s64 nxlen, nxaddr, xoff, hint, xaddr = 0;
741da177e4SLinus Torvalds 	int rc;
751da177e4SLinus Torvalds 	int xflag;
761da177e4SLinus Torvalds 
771da177e4SLinus Torvalds 	/* This blocks if we are low on resources */
781da177e4SLinus Torvalds 	txBeginAnon(ip->i_sb);
791da177e4SLinus Torvalds 
801da177e4SLinus Torvalds 	/* Avoid race with jfs_commit_inode() */
811de87444SIngo Molnar 	mutex_lock(&JFS_IP(ip)->commit_mutex);
821da177e4SLinus Torvalds 
831da177e4SLinus Torvalds 	/* validate extent length */
841da177e4SLinus Torvalds 	if (xlen > MAXXLEN)
851da177e4SLinus Torvalds 		xlen = MAXXLEN;
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds 	/* get the page's starting extent offset */
881da177e4SLinus Torvalds 	xoff = pno << sbi->l2nbperpage;
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds 	/* check if an allocation hint was provided */
911da177e4SLinus Torvalds 	if ((hint = addressXAD(xp))) {
921da177e4SLinus Torvalds 		/* get the size of the extent described by the hint */
931da177e4SLinus Torvalds 		nxlen = lengthXAD(xp);
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds 		/* check if the hint is for the portion of the file
961da177e4SLinus Torvalds 		 * immediately previous to the current allocation
971da177e4SLinus Torvalds 		 * request and if hint extent has the same abnr
981da177e4SLinus Torvalds 		 * value as the current request.  if so, we can
991da177e4SLinus Torvalds 		 * extend the hint extent to include the current
1001da177e4SLinus Torvalds 		 * extent if we can allocate the blocks immediately
1011da177e4SLinus Torvalds 		 * following the hint extent.
1021da177e4SLinus Torvalds 		 */
1031da177e4SLinus Torvalds 		if (offsetXAD(xp) + nxlen == xoff &&
1044d81715fSRichard Knutsson 		    abnr == ((xp->flag & XAD_NOTRECORDED) ? true : false))
1051da177e4SLinus Torvalds 			xaddr = hint + nxlen;
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds 		/* adjust the hint to the last block of the extent */
1081da177e4SLinus Torvalds 		hint += (nxlen - 1);
1091da177e4SLinus Torvalds 	}
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 	/* allocate the disk blocks for the extent.  initially, extBalloc()
1121da177e4SLinus Torvalds 	 * will try to allocate disk blocks for the requested size (xlen).
11325985edcSLucas De Marchi 	 * if this fails (xlen contiguous free blocks not available), it'll
1141da177e4SLinus Torvalds 	 * try to allocate a smaller number of blocks (producing a smaller
1151da177e4SLinus Torvalds 	 * extent), with this smaller number of blocks consisting of the
1161da177e4SLinus Torvalds 	 * requested number of blocks rounded down to the next smaller
1171da177e4SLinus Torvalds 	 * power of 2 number (i.e. 16 -> 8).  it'll continue to round down
1181da177e4SLinus Torvalds 	 * and retry the allocation until the number of blocks to allocate
1191da177e4SLinus Torvalds 	 * is smaller than the number of blocks per page.
1201da177e4SLinus Torvalds 	 */
1211da177e4SLinus Torvalds 	nxlen = xlen;
1221da177e4SLinus Torvalds 	if ((rc = extBalloc(ip, hint ? hint : INOHINT(ip), &nxlen, &nxaddr))) {
1231de87444SIngo Molnar 		mutex_unlock(&JFS_IP(ip)->commit_mutex);
1241da177e4SLinus Torvalds 		return (rc);
1251da177e4SLinus Torvalds 	}
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds 	/* Allocate blocks to quota. */
1285dd4056dSChristoph Hellwig 	rc = dquot_alloc_block(ip, nxlen);
1295dd4056dSChristoph Hellwig 	if (rc) {
1301da177e4SLinus Torvalds 		dbFree(ip, nxaddr, (s64) nxlen);
1311de87444SIngo Molnar 		mutex_unlock(&JFS_IP(ip)->commit_mutex);
1325dd4056dSChristoph Hellwig 		return rc;
1331da177e4SLinus Torvalds 	}
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds 	/* determine the value of the extent flag */
1364d81715fSRichard Knutsson 	xflag = abnr ? XAD_NOTRECORDED : 0;
1371da177e4SLinus Torvalds 
1381da177e4SLinus Torvalds 	/* if we can extend the hint extent to cover the current request,
1391da177e4SLinus Torvalds 	 * extend it.  otherwise, insert a new extent to
1401da177e4SLinus Torvalds 	 * cover the current request.
1411da177e4SLinus Torvalds 	 */
1421da177e4SLinus Torvalds 	if (xaddr && xaddr == nxaddr)
1431da177e4SLinus Torvalds 		rc = xtExtend(0, ip, xoff, (int) nxlen, 0);
1441da177e4SLinus Torvalds 	else
1451da177e4SLinus Torvalds 		rc = xtInsert(0, ip, xflag, xoff, (int) nxlen, &nxaddr, 0);
1461da177e4SLinus Torvalds 
1471da177e4SLinus Torvalds 	/* if the extend or insert failed,
1481da177e4SLinus Torvalds 	 * free the newly allocated blocks and return the error.
1491da177e4SLinus Torvalds 	 */
1501da177e4SLinus Torvalds 	if (rc) {
1511da177e4SLinus Torvalds 		dbFree(ip, nxaddr, nxlen);
1525dd4056dSChristoph Hellwig 		dquot_free_block(ip, nxlen);
1531de87444SIngo Molnar 		mutex_unlock(&JFS_IP(ip)->commit_mutex);
1541da177e4SLinus Torvalds 		return (rc);
1551da177e4SLinus Torvalds 	}
1561da177e4SLinus Torvalds 
1571da177e4SLinus Torvalds 	/* set the results of the extent allocation */
1581da177e4SLinus Torvalds 	XADaddress(xp, nxaddr);
1591da177e4SLinus Torvalds 	XADlength(xp, nxlen);
1601da177e4SLinus Torvalds 	XADoffset(xp, xoff);
1611da177e4SLinus Torvalds 	xp->flag = xflag;
1621da177e4SLinus Torvalds 
1631da177e4SLinus Torvalds 	mark_inode_dirty(ip);
1641da177e4SLinus Torvalds 
1651de87444SIngo Molnar 	mutex_unlock(&JFS_IP(ip)->commit_mutex);
1661da177e4SLinus Torvalds 	/*
1671da177e4SLinus Torvalds 	 * COMMIT_SyncList flags an anonymous tlock on page that is on
1681da177e4SLinus Torvalds 	 * sync list.
169c67235d0SImmad Mir 	 * We need to commit the inode to get the page written to the disk.
1701da177e4SLinus Torvalds 	 */
1711da177e4SLinus Torvalds 	if (test_and_clear_cflag(COMMIT_Synclist,ip))
1721da177e4SLinus Torvalds 		jfs_commit_inode(ip, 0);
1731da177e4SLinus Torvalds 
1741da177e4SLinus Torvalds 	return (0);
1751da177e4SLinus Torvalds }
1761da177e4SLinus Torvalds 
1771da177e4SLinus Torvalds /*
1781da177e4SLinus Torvalds  * NAME:	extHint()
1791da177e4SLinus Torvalds  *
1801da177e4SLinus Torvalds  * FUNCTION:	produce an extent allocation hint for a file offset.
1811da177e4SLinus Torvalds  *
1821da177e4SLinus Torvalds  * PARAMETERS:
1831da177e4SLinus Torvalds  *	ip	- the inode of the file.
1841da177e4SLinus Torvalds  *	offset  - file offset for which the hint is needed.
1851da177e4SLinus Torvalds  *	xp	- pointer to the xad that is to be filled in with
1861da177e4SLinus Torvalds  *		  the hint.
1871da177e4SLinus Torvalds  *
1881da177e4SLinus Torvalds  * RETURN VALUES:
1891da177e4SLinus Torvalds  *	0	- success
1901da177e4SLinus Torvalds  *	-EIO	- i/o error.
1911da177e4SLinus Torvalds  */
extHint(struct inode * ip,s64 offset,xad_t * xp)1921da177e4SLinus Torvalds int extHint(struct inode *ip, s64 offset, xad_t * xp)
1931da177e4SLinus Torvalds {
1941da177e4SLinus Torvalds 	struct super_block *sb = ip->i_sb;
195fec1878fSDave Kleikamp 	int nbperpage = JFS_SBI(sb)->nbperpage;
1961da177e4SLinus Torvalds 	s64 prev;
197fec1878fSDave Kleikamp 	int rc = 0;
198fec1878fSDave Kleikamp 	s64 xaddr;
199fec1878fSDave Kleikamp 	int xlen;
200fec1878fSDave Kleikamp 	int xflag;
2011da177e4SLinus Torvalds 
2021da177e4SLinus Torvalds 	/* init the hint as "no hint provided" */
2031da177e4SLinus Torvalds 	XADaddress(xp, 0);
2041da177e4SLinus Torvalds 
2051da177e4SLinus Torvalds 	/* determine the starting extent offset of the page previous
2061da177e4SLinus Torvalds 	 * to the page containing the offset.
2071da177e4SLinus Torvalds 	 */
2081da177e4SLinus Torvalds 	prev = ((offset & ~POFFSET) >> JFS_SBI(sb)->l2bsize) - nbperpage;
2091da177e4SLinus Torvalds 
210fec1878fSDave Kleikamp 	/* if the offset is in the first page of the file, no hint provided.
2111da177e4SLinus Torvalds 	 */
2121da177e4SLinus Torvalds 	if (prev < 0)
213fec1878fSDave Kleikamp 		goto out;
2141da177e4SLinus Torvalds 
215fec1878fSDave Kleikamp 	rc = xtLookup(ip, prev, nbperpage, &xflag, &xaddr, &xlen, 0);
2161da177e4SLinus Torvalds 
217fec1878fSDave Kleikamp 	if ((rc == 0) && xlen) {
218fec1878fSDave Kleikamp 		if (xlen != nbperpage) {
219eb8630d7SJoe Perches 			jfs_error(ip->i_sb, "corrupt xtree\n");
220fec1878fSDave Kleikamp 			rc = -EIO;
2211da177e4SLinus Torvalds 		}
222fec1878fSDave Kleikamp 		XADaddress(xp, xaddr);
223fec1878fSDave Kleikamp 		XADlength(xp, xlen);
224f7c52fd1SDave Kleikamp 		XADoffset(xp, prev);
225fec1878fSDave Kleikamp 		/*
226fec1878fSDave Kleikamp 		 * only preserve the abnr flag within the xad flags
2271da177e4SLinus Torvalds 		 * of the returned hint.
2281da177e4SLinus Torvalds 		 */
229fec1878fSDave Kleikamp 		xp->flag  = xflag & XAD_NOTRECORDED;
230fec1878fSDave Kleikamp 	} else
231fec1878fSDave Kleikamp 		rc = 0;
2321da177e4SLinus Torvalds 
233fec1878fSDave Kleikamp out:
234fec1878fSDave Kleikamp 	return (rc);
2351da177e4SLinus Torvalds }
2361da177e4SLinus Torvalds 
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds /*
2391da177e4SLinus Torvalds  * NAME:	extRecord()
2401da177e4SLinus Torvalds  *
2411da177e4SLinus Torvalds  * FUNCTION:	change a page with a file from not recorded to recorded.
2421da177e4SLinus Torvalds  *
2431da177e4SLinus Torvalds  * PARAMETERS:
2441da177e4SLinus Torvalds  *	ip	- inode of the file.
2451da177e4SLinus Torvalds  *	cp	- cbuf of the file page.
2461da177e4SLinus Torvalds  *
2471da177e4SLinus Torvalds  * RETURN VALUES:
2481da177e4SLinus Torvalds  *	0	- success
2491da177e4SLinus Torvalds  *	-EIO	- i/o error.
2501da177e4SLinus Torvalds  *	-ENOSPC	- insufficient disk resources.
2511da177e4SLinus Torvalds  */
extRecord(struct inode * ip,xad_t * xp)2521da177e4SLinus Torvalds int extRecord(struct inode *ip, xad_t * xp)
2531da177e4SLinus Torvalds {
2541da177e4SLinus Torvalds 	int rc;
2551da177e4SLinus Torvalds 
2561da177e4SLinus Torvalds 	txBeginAnon(ip->i_sb);
2571da177e4SLinus Torvalds 
2581de87444SIngo Molnar 	mutex_lock(&JFS_IP(ip)->commit_mutex);
2591da177e4SLinus Torvalds 
2601da177e4SLinus Torvalds 	/* update the extent */
2611da177e4SLinus Torvalds 	rc = xtUpdate(0, ip, xp);
2621da177e4SLinus Torvalds 
2631de87444SIngo Molnar 	mutex_unlock(&JFS_IP(ip)->commit_mutex);
2641da177e4SLinus Torvalds 	return rc;
2651da177e4SLinus Torvalds }
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds /*
2681da177e4SLinus Torvalds  * NAME:	extBalloc()
2691da177e4SLinus Torvalds  *
2701da177e4SLinus Torvalds  * FUNCTION:	allocate disk blocks to form an extent.
2711da177e4SLinus Torvalds  *
2721da177e4SLinus Torvalds  *		initially, we will try to allocate disk blocks for the
2731da177e4SLinus Torvalds  *		requested size (nblocks).  if this fails (nblocks
27425985edcSLucas De Marchi  *		contiguous free blocks not available), we'll try to allocate
2751da177e4SLinus Torvalds  *		a smaller number of blocks (producing a smaller extent), with
2761da177e4SLinus Torvalds  *		this smaller number of blocks consisting of the requested
2771da177e4SLinus Torvalds  *		number of blocks rounded down to the next smaller power of 2
2781da177e4SLinus Torvalds  *		number (i.e. 16 -> 8).  we'll continue to round down and
2791da177e4SLinus Torvalds  *		retry the allocation until the number of blocks to allocate
2801da177e4SLinus Torvalds  *		is smaller than the number of blocks per page.
2811da177e4SLinus Torvalds  *
2821da177e4SLinus Torvalds  * PARAMETERS:
2831da177e4SLinus Torvalds  *	ip	 - the inode of the file.
2841da177e4SLinus Torvalds  *	hint	 - disk block number to be used as an allocation hint.
2851da177e4SLinus Torvalds  *	*nblocks - pointer to an s64 value.  on entry, this value specifies
2861da177e4SLinus Torvalds  *		   the desired number of block to be allocated. on successful
2871da177e4SLinus Torvalds  *		   exit, this value is set to the number of blocks actually
2881da177e4SLinus Torvalds  *		   allocated.
2891da177e4SLinus Torvalds  *	blkno	 - pointer to a block address that is filled in on successful
2901da177e4SLinus Torvalds  *		   return with the starting block number of the newly
2911da177e4SLinus Torvalds  *		   allocated block range.
2921da177e4SLinus Torvalds  *
2931da177e4SLinus Torvalds  * RETURN VALUES:
2941da177e4SLinus Torvalds  *	0	- success
2951da177e4SLinus Torvalds  *	-EIO	- i/o error.
2961da177e4SLinus Torvalds  *	-ENOSPC	- insufficient disk resources.
2971da177e4SLinus Torvalds  */
2981da177e4SLinus Torvalds static int
extBalloc(struct inode * ip,s64 hint,s64 * nblocks,s64 * blkno)2991da177e4SLinus Torvalds extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
3001da177e4SLinus Torvalds {
3011da177e4SLinus Torvalds 	struct jfs_inode_info *ji = JFS_IP(ip);
3021da177e4SLinus Torvalds 	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
3031da177e4SLinus Torvalds 	s64 nb, nblks, daddr, max;
3041da177e4SLinus Torvalds 	int rc, nbperpage = sbi->nbperpage;
3051da177e4SLinus Torvalds 	struct bmap *bmp = sbi->bmap;
3061da177e4SLinus Torvalds 	int ag;
3071da177e4SLinus Torvalds 
3081da177e4SLinus Torvalds 	/* get the number of blocks to initially attempt to allocate.
3091da177e4SLinus Torvalds 	 * we'll first try the number of blocks requested unless this
310d6e05edcSAndreas Mohr 	 * number is greater than the maximum number of contiguous free
3111da177e4SLinus Torvalds 	 * blocks in the map. in that case, we'll start off with the
3121da177e4SLinus Torvalds 	 * maximum free.
3131da177e4SLinus Torvalds 	 */
314*0225e109SAlexei Filippov 
315*0225e109SAlexei Filippov 	/* give up if no space left */
316*0225e109SAlexei Filippov 	if (bmp->db_maxfreebud == -1)
317*0225e109SAlexei Filippov 		return -ENOSPC;
318*0225e109SAlexei Filippov 
3191da177e4SLinus Torvalds 	max = (s64) 1 << bmp->db_maxfreebud;
3201da177e4SLinus Torvalds 	if (*nblocks >= max && *nblocks > nbperpage)
3211da177e4SLinus Torvalds 		nb = nblks = (max > nbperpage) ? max : nbperpage;
3221da177e4SLinus Torvalds 	else
3231da177e4SLinus Torvalds 		nb = nblks = *nblocks;
3241da177e4SLinus Torvalds 
3251da177e4SLinus Torvalds 	/* try to allocate blocks */
3261da177e4SLinus Torvalds 	while ((rc = dbAlloc(ip, hint, nb, &daddr)) != 0) {
3271da177e4SLinus Torvalds 		/* if something other than an out of space error,
3281da177e4SLinus Torvalds 		 * stop and return this error.
3291da177e4SLinus Torvalds 		 */
3301da177e4SLinus Torvalds 		if (rc != -ENOSPC)
3311da177e4SLinus Torvalds 			return (rc);
3321da177e4SLinus Torvalds 
3331da177e4SLinus Torvalds 		/* decrease the allocation request size */
3341da177e4SLinus Torvalds 		nb = min(nblks, extRoundDown(nb));
3351da177e4SLinus Torvalds 
3361da177e4SLinus Torvalds 		/* give up if we cannot cover a page */
3371da177e4SLinus Torvalds 		if (nb < nbperpage)
3381da177e4SLinus Torvalds 			return (rc);
3391da177e4SLinus Torvalds 	}
3401da177e4SLinus Torvalds 
3411da177e4SLinus Torvalds 	*nblocks = nb;
3421da177e4SLinus Torvalds 	*blkno = daddr;
3431da177e4SLinus Torvalds 
3441da177e4SLinus Torvalds 	if (S_ISREG(ip->i_mode) && (ji->fileset == FILESYSTEM_I)) {
3451da177e4SLinus Torvalds 		ag = BLKTOAG(daddr, sbi);
3461da177e4SLinus Torvalds 		spin_lock_irq(&ji->ag_lock);
3471da177e4SLinus Torvalds 		if (ji->active_ag == -1) {
3481da177e4SLinus Torvalds 			atomic_inc(&bmp->db_active[ag]);
3491da177e4SLinus Torvalds 			ji->active_ag = ag;
3501da177e4SLinus Torvalds 		} else if (ji->active_ag != ag) {
3511da177e4SLinus Torvalds 			atomic_dec(&bmp->db_active[ji->active_ag]);
3521da177e4SLinus Torvalds 			atomic_inc(&bmp->db_active[ag]);
3531da177e4SLinus Torvalds 			ji->active_ag = ag;
3541da177e4SLinus Torvalds 		}
3551da177e4SLinus Torvalds 		spin_unlock_irq(&ji->ag_lock);
3561da177e4SLinus Torvalds 	}
3571da177e4SLinus Torvalds 
3581da177e4SLinus Torvalds 	return (0);
3591da177e4SLinus Torvalds }
3601da177e4SLinus Torvalds 
3611da177e4SLinus Torvalds /*
3621da177e4SLinus Torvalds  * NAME:	extRoundDown()
3631da177e4SLinus Torvalds  *
3641da177e4SLinus Torvalds  * FUNCTION:	round down a specified number of blocks to the next
3651da177e4SLinus Torvalds  *		smallest power of 2 number.
3661da177e4SLinus Torvalds  *
3671da177e4SLinus Torvalds  * PARAMETERS:
3681da177e4SLinus Torvalds  *	nb	- the inode of the file.
3691da177e4SLinus Torvalds  *
3701da177e4SLinus Torvalds  * RETURN VALUES:
3711da177e4SLinus Torvalds  *	next smallest power of 2 number.
3721da177e4SLinus Torvalds  */
extRoundDown(s64 nb)3731da177e4SLinus Torvalds static s64 extRoundDown(s64 nb)
3741da177e4SLinus Torvalds {
3751da177e4SLinus Torvalds 	int i;
3761da177e4SLinus Torvalds 	u64 m, k;
3771da177e4SLinus Torvalds 
3781da177e4SLinus Torvalds 	for (i = 0, m = (u64) 1 << 63; i < 64; i++, m >>= 1) {
3791da177e4SLinus Torvalds 		if (m & nb)
3801da177e4SLinus Torvalds 			break;
3811da177e4SLinus Torvalds 	}
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds 	i = 63 - i;
3841da177e4SLinus Torvalds 	k = (u64) 1 << i;
3851da177e4SLinus Torvalds 	k = ((k - 1) & nb) ? k : k >> 1;
3861da177e4SLinus Torvalds 
3871da177e4SLinus Torvalds 	return (k);
3881da177e4SLinus Torvalds }
389