| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  *   Copyright (C) International Business Machines Corp., 2000-2004 | 
 | 3 |  * | 
 | 4 |  *   This program is free software;  you can redistribute it and/or modify | 
 | 5 |  *   it under the terms of the GNU General Public License as published by | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 6 |  *   the Free Software Foundation; either version 2 of the License, or | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7 |  *   (at your option) any later version. | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 8 |  * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9 |  *   This program is distributed in the hope that it will be useful, | 
 | 10 |  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of | 
 | 11 |  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See | 
 | 12 |  *   the GNU General Public License for more details. | 
 | 13 |  * | 
 | 14 |  *   You should have received a copy of the GNU General Public License | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 15 |  *   along with this program;  if not, write to the Free Software | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 16 |  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 
 | 17 |  */ | 
 | 18 |  | 
 | 19 | #include <linux/fs.h> | 
 | 20 | #include <linux/quotaops.h> | 
 | 21 | #include "jfs_incore.h" | 
| Dave Kleikamp | 1868f4a | 2005-05-04 15:29:35 -0500 | [diff] [blame] | 22 | #include "jfs_inode.h" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 23 | #include "jfs_superblock.h" | 
 | 24 | #include "jfs_dmap.h" | 
 | 25 | #include "jfs_extent.h" | 
 | 26 | #include "jfs_debug.h" | 
 | 27 |  | 
 | 28 | /* | 
 | 29 |  * forward references | 
 | 30 |  */ | 
 | 31 | static int extBalloc(struct inode *, s64, s64 *, s64 *); | 
 | 32 | #ifdef _NOTYET | 
 | 33 | static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *); | 
 | 34 | #endif | 
 | 35 | static s64 extRoundDown(s64 nb); | 
 | 36 |  | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 37 | #define DPD(a)		(printk("(a): %d\n",(a))) | 
 | 38 | #define DPC(a)		(printk("(a): %c\n",(a))) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 39 | #define DPL1(a)					\ | 
 | 40 | {						\ | 
 | 41 | 	if ((a) >> 32)				\ | 
 | 42 | 		printk("(a): %x%08x  ",(a));	\ | 
 | 43 | 	else					\ | 
 | 44 | 		printk("(a): %x  ",(a) << 32);	\ | 
 | 45 | } | 
 | 46 | #define DPL(a)					\ | 
 | 47 | {						\ | 
 | 48 | 	if ((a) >> 32)				\ | 
 | 49 | 		printk("(a): %x%08x\n",(a));	\ | 
 | 50 | 	else					\ | 
 | 51 | 		printk("(a): %x\n",(a) << 32);	\ | 
 | 52 | } | 
 | 53 |  | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 54 | #define DPD1(a)		(printk("(a): %d  ",(a))) | 
 | 55 | #define DPX(a)		(printk("(a): %08x\n",(a))) | 
 | 56 | #define DPX1(a)		(printk("(a): %08x  ",(a))) | 
 | 57 | #define DPS(a)		(printk("%s\n",(a))) | 
 | 58 | #define DPE(a)		(printk("\nENTERING: %s\n",(a))) | 
 | 59 | #define DPE1(a)		(printk("\nENTERING: %s",(a))) | 
 | 60 | #define DPS1(a)		(printk("  %s  ",(a))) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 61 |  | 
 | 62 |  | 
 | 63 | /* | 
 | 64 |  * NAME:	extAlloc() | 
 | 65 |  * | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 66 |  * FUNCTION:	allocate an extent for a specified page range within a | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 67 |  *		file. | 
 | 68 |  * | 
 | 69 |  * PARAMETERS: | 
 | 70 |  *	ip	- the inode of the file. | 
 | 71 |  *	xlen	- requested extent length. | 
 | 72 |  *	pno	- the starting page number with the file. | 
 | 73 |  *	xp	- pointer to an xad.  on entry, xad describes an | 
 | 74 |  *		  extent that is used as an allocation hint if the | 
 | 75 |  *		  xaddr of the xad is non-zero.  on successful exit, | 
 | 76 |  *		  the xad describes the newly allocated extent. | 
| Richard Knutsson | 4d81715 | 2006-09-30 23:27:14 -0700 | [diff] [blame] | 77 |  *	abnr	- bool indicating whether the newly allocated extent | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 78 |  *		  should be marked as allocated but not recorded. | 
 | 79 |  * | 
 | 80 |  * RETURN VALUES: | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 81 |  *	0	- success | 
 | 82 |  *	-EIO	- i/o error. | 
 | 83 |  *	-ENOSPC	- insufficient disk resources. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 84 |  */ | 
 | 85 | int | 
| Richard Knutsson | 4d81715 | 2006-09-30 23:27:14 -0700 | [diff] [blame] | 86 | extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 87 | { | 
 | 88 | 	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); | 
 | 89 | 	s64 nxlen, nxaddr, xoff, hint, xaddr = 0; | 
 | 90 | 	int rc; | 
 | 91 | 	int xflag; | 
 | 92 |  | 
 | 93 | 	/* This blocks if we are low on resources */ | 
 | 94 | 	txBeginAnon(ip->i_sb); | 
 | 95 |  | 
 | 96 | 	/* Avoid race with jfs_commit_inode() */ | 
| Ingo Molnar | 1de8744 | 2006-01-24 15:22:50 -0600 | [diff] [blame] | 97 | 	mutex_lock(&JFS_IP(ip)->commit_mutex); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 |  | 
 | 99 | 	/* validate extent length */ | 
 | 100 | 	if (xlen > MAXXLEN) | 
 | 101 | 		xlen = MAXXLEN; | 
 | 102 |  | 
 | 103 | 	/* get the page's starting extent offset */ | 
 | 104 | 	xoff = pno << sbi->l2nbperpage; | 
 | 105 |  | 
 | 106 | 	/* check if an allocation hint was provided */ | 
 | 107 | 	if ((hint = addressXAD(xp))) { | 
 | 108 | 		/* get the size of the extent described by the hint */ | 
 | 109 | 		nxlen = lengthXAD(xp); | 
 | 110 |  | 
 | 111 | 		/* check if the hint is for the portion of the file | 
 | 112 | 		 * immediately previous to the current allocation | 
 | 113 | 		 * request and if hint extent has the same abnr | 
 | 114 | 		 * value as the current request.  if so, we can | 
 | 115 | 		 * extend the hint extent to include the current | 
 | 116 | 		 * extent if we can allocate the blocks immediately | 
 | 117 | 		 * following the hint extent. | 
 | 118 | 		 */ | 
 | 119 | 		if (offsetXAD(xp) + nxlen == xoff && | 
| Richard Knutsson | 4d81715 | 2006-09-30 23:27:14 -0700 | [diff] [blame] | 120 | 		    abnr == ((xp->flag & XAD_NOTRECORDED) ? true : false)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 121 | 			xaddr = hint + nxlen; | 
 | 122 |  | 
 | 123 | 		/* adjust the hint to the last block of the extent */ | 
 | 124 | 		hint += (nxlen - 1); | 
 | 125 | 	} | 
 | 126 |  | 
 | 127 | 	/* allocate the disk blocks for the extent.  initially, extBalloc() | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 128 | 	 * will try to allocate disk blocks for the requested size (xlen). | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 129 | 	 * if this fails (xlen contiguous free blocks not available), it'll | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 130 | 	 * try to allocate a smaller number of blocks (producing a smaller | 
 | 131 | 	 * extent), with this smaller number of blocks consisting of the | 
 | 132 | 	 * requested number of blocks rounded down to the next smaller | 
 | 133 | 	 * power of 2 number (i.e. 16 -> 8).  it'll continue to round down | 
 | 134 | 	 * and retry the allocation until the number of blocks to allocate | 
 | 135 | 	 * is smaller than the number of blocks per page. | 
 | 136 | 	 */ | 
 | 137 | 	nxlen = xlen; | 
 | 138 | 	if ((rc = extBalloc(ip, hint ? hint : INOHINT(ip), &nxlen, &nxaddr))) { | 
| Ingo Molnar | 1de8744 | 2006-01-24 15:22:50 -0600 | [diff] [blame] | 139 | 		mutex_unlock(&JFS_IP(ip)->commit_mutex); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 140 | 		return (rc); | 
 | 141 | 	} | 
 | 142 |  | 
 | 143 | 	/* Allocate blocks to quota. */ | 
| Christoph Hellwig | 5dd4056 | 2010-03-03 09:05:00 -0500 | [diff] [blame] | 144 | 	rc = dquot_alloc_block(ip, nxlen); | 
 | 145 | 	if (rc) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 146 | 		dbFree(ip, nxaddr, (s64) nxlen); | 
| Ingo Molnar | 1de8744 | 2006-01-24 15:22:50 -0600 | [diff] [blame] | 147 | 		mutex_unlock(&JFS_IP(ip)->commit_mutex); | 
| Christoph Hellwig | 5dd4056 | 2010-03-03 09:05:00 -0500 | [diff] [blame] | 148 | 		return rc; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 149 | 	} | 
 | 150 |  | 
 | 151 | 	/* determine the value of the extent flag */ | 
| Richard Knutsson | 4d81715 | 2006-09-30 23:27:14 -0700 | [diff] [blame] | 152 | 	xflag = abnr ? XAD_NOTRECORDED : 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 153 |  | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 154 | 	/* if we can extend the hint extent to cover the current request, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 155 | 	 * extend it.  otherwise, insert a new extent to | 
 | 156 | 	 * cover the current request. | 
 | 157 | 	 */ | 
 | 158 | 	if (xaddr && xaddr == nxaddr) | 
 | 159 | 		rc = xtExtend(0, ip, xoff, (int) nxlen, 0); | 
 | 160 | 	else | 
 | 161 | 		rc = xtInsert(0, ip, xflag, xoff, (int) nxlen, &nxaddr, 0); | 
 | 162 |  | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 163 | 	/* if the extend or insert failed, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 164 | 	 * free the newly allocated blocks and return the error. | 
 | 165 | 	 */ | 
 | 166 | 	if (rc) { | 
 | 167 | 		dbFree(ip, nxaddr, nxlen); | 
| Christoph Hellwig | 5dd4056 | 2010-03-03 09:05:00 -0500 | [diff] [blame] | 168 | 		dquot_free_block(ip, nxlen); | 
| Ingo Molnar | 1de8744 | 2006-01-24 15:22:50 -0600 | [diff] [blame] | 169 | 		mutex_unlock(&JFS_IP(ip)->commit_mutex); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 170 | 		return (rc); | 
 | 171 | 	} | 
 | 172 |  | 
 | 173 | 	/* set the results of the extent allocation */ | 
 | 174 | 	XADaddress(xp, nxaddr); | 
 | 175 | 	XADlength(xp, nxlen); | 
 | 176 | 	XADoffset(xp, xoff); | 
 | 177 | 	xp->flag = xflag; | 
 | 178 |  | 
 | 179 | 	mark_inode_dirty(ip); | 
 | 180 |  | 
| Ingo Molnar | 1de8744 | 2006-01-24 15:22:50 -0600 | [diff] [blame] | 181 | 	mutex_unlock(&JFS_IP(ip)->commit_mutex); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 182 | 	/* | 
 | 183 | 	 * COMMIT_SyncList flags an anonymous tlock on page that is on | 
 | 184 | 	 * sync list. | 
 | 185 | 	 * We need to commit the inode to get the page written disk. | 
 | 186 | 	 */ | 
 | 187 | 	if (test_and_clear_cflag(COMMIT_Synclist,ip)) | 
 | 188 | 		jfs_commit_inode(ip, 0); | 
 | 189 |  | 
 | 190 | 	return (0); | 
 | 191 | } | 
 | 192 |  | 
 | 193 |  | 
 | 194 | #ifdef _NOTYET | 
 | 195 | /* | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 196 |  * NAME:	extRealloc() | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 197 |  * | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 198 |  * FUNCTION:	extend the allocation of a file extent containing a | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 199 |  *		partial back last page. | 
 | 200 |  * | 
 | 201 |  * PARAMETERS: | 
 | 202 |  *	ip	- the inode of the file. | 
 | 203 |  *	cp	- cbuf for the partial backed last page. | 
 | 204 |  *	xlen	- request size of the resulting extent. | 
 | 205 |  *	xp	- pointer to an xad. on successful exit, the xad | 
 | 206 |  *		  describes the newly allocated extent. | 
| Richard Knutsson | 4d81715 | 2006-09-30 23:27:14 -0700 | [diff] [blame] | 207 |  *	abnr	- bool indicating whether the newly allocated extent | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 208 |  *		  should be marked as allocated but not recorded. | 
 | 209 |  * | 
 | 210 |  * RETURN VALUES: | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 211 |  *	0	- success | 
 | 212 |  *	-EIO	- i/o error. | 
 | 213 |  *	-ENOSPC	- insufficient disk resources. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 214 |  */ | 
| Richard Knutsson | 4d81715 | 2006-09-30 23:27:14 -0700 | [diff] [blame] | 215 | int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 216 | { | 
 | 217 | 	struct super_block *sb = ip->i_sb; | 
 | 218 | 	s64 xaddr, xlen, nxaddr, delta, xoff; | 
 | 219 | 	s64 ntail, nextend, ninsert; | 
 | 220 | 	int rc, nbperpage = JFS_SBI(sb)->nbperpage; | 
 | 221 | 	int xflag; | 
 | 222 |  | 
 | 223 | 	/* This blocks if we are low on resources */ | 
 | 224 | 	txBeginAnon(ip->i_sb); | 
 | 225 |  | 
| Ingo Molnar | 1de8744 | 2006-01-24 15:22:50 -0600 | [diff] [blame] | 226 | 	mutex_lock(&JFS_IP(ip)->commit_mutex); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 227 | 	/* validate extent length */ | 
 | 228 | 	if (nxlen > MAXXLEN) | 
 | 229 | 		nxlen = MAXXLEN; | 
 | 230 |  | 
 | 231 | 	/* get the extend (partial) page's disk block address and | 
 | 232 | 	 * number of blocks. | 
 | 233 | 	 */ | 
 | 234 | 	xaddr = addressXAD(xp); | 
 | 235 | 	xlen = lengthXAD(xp); | 
 | 236 | 	xoff = offsetXAD(xp); | 
 | 237 |  | 
 | 238 | 	/* if the extend page is abnr and if the request is for | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 239 | 	 * the extent to be allocated and recorded, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 240 | 	 * make the page allocated and recorded. | 
 | 241 | 	 */ | 
 | 242 | 	if ((xp->flag & XAD_NOTRECORDED) && !abnr) { | 
 | 243 | 		xp->flag = 0; | 
 | 244 | 		if ((rc = xtUpdate(0, ip, xp))) | 
 | 245 | 			goto exit; | 
 | 246 | 	} | 
 | 247 |  | 
 | 248 | 	/* try to allocated the request number of blocks for the | 
 | 249 | 	 * extent.  dbRealloc() first tries to satisfy the request | 
 | 250 | 	 * by extending the allocation in place. otherwise, it will | 
 | 251 | 	 * try to allocate a new set of blocks large enough for the | 
 | 252 | 	 * request.  in satisfying a request, dbReAlloc() may allocate | 
 | 253 | 	 * less than what was request but will always allocate enough | 
 | 254 | 	 * space as to satisfy the extend page. | 
 | 255 | 	 */ | 
 | 256 | 	if ((rc = extBrealloc(ip, xaddr, xlen, &nxlen, &nxaddr))) | 
 | 257 | 		goto exit; | 
 | 258 |  | 
 | 259 | 	/* Allocat blocks to quota. */ | 
| Christoph Hellwig | 5dd4056 | 2010-03-03 09:05:00 -0500 | [diff] [blame] | 260 | 	rc = dquot_alloc_block(ip, nxlen); | 
 | 261 | 	if (rc) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 262 | 		dbFree(ip, nxaddr, (s64) nxlen); | 
| Ingo Molnar | 1de8744 | 2006-01-24 15:22:50 -0600 | [diff] [blame] | 263 | 		mutex_unlock(&JFS_IP(ip)->commit_mutex); | 
| Christoph Hellwig | 5dd4056 | 2010-03-03 09:05:00 -0500 | [diff] [blame] | 264 | 		return rc; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 265 | 	} | 
 | 266 |  | 
 | 267 | 	delta = nxlen - xlen; | 
 | 268 |  | 
 | 269 | 	/* check if the extend page is not abnr but the request is abnr | 
 | 270 | 	 * and the allocated disk space is for more than one page.  if this | 
 | 271 | 	 * is the case, there is a miss match of abnr between the extend page | 
 | 272 | 	 * and the one or more pages following the extend page.  as a result, | 
 | 273 | 	 * two extents will have to be manipulated. the first will be that | 
 | 274 | 	 * of the extent of the extend page and will be manipulated thru | 
 | 275 | 	 * an xtExtend() or an xtTailgate(), depending upon whether the | 
 | 276 | 	 * disk allocation occurred as an inplace extension.  the second | 
 | 277 | 	 * extent will be manipulated (created) through an xtInsert() and | 
 | 278 | 	 * will be for the pages following the extend page. | 
 | 279 | 	 */ | 
 | 280 | 	if (abnr && (!(xp->flag & XAD_NOTRECORDED)) && (nxlen > nbperpage)) { | 
 | 281 | 		ntail = nbperpage; | 
 | 282 | 		nextend = ntail - xlen; | 
 | 283 | 		ninsert = nxlen - nbperpage; | 
 | 284 |  | 
 | 285 | 		xflag = XAD_NOTRECORDED; | 
 | 286 | 	} else { | 
 | 287 | 		ntail = nxlen; | 
 | 288 | 		nextend = delta; | 
 | 289 | 		ninsert = 0; | 
 | 290 |  | 
 | 291 | 		xflag = xp->flag; | 
 | 292 | 	} | 
 | 293 |  | 
 | 294 | 	/* if we were able to extend the disk allocation in place, | 
 | 295 | 	 * extend the extent.  otherwise, move the extent to a | 
 | 296 | 	 * new disk location. | 
 | 297 | 	 */ | 
 | 298 | 	if (xaddr == nxaddr) { | 
 | 299 | 		/* extend the extent */ | 
 | 300 | 		if ((rc = xtExtend(0, ip, xoff + xlen, (int) nextend, 0))) { | 
 | 301 | 			dbFree(ip, xaddr + xlen, delta); | 
| Christoph Hellwig | 5dd4056 | 2010-03-03 09:05:00 -0500 | [diff] [blame] | 302 | 			dquot_free_block(ip, nxlen); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 303 | 			goto exit; | 
 | 304 | 		} | 
 | 305 | 	} else { | 
 | 306 | 		/* | 
 | 307 | 		 * move the extent to a new location: | 
 | 308 | 		 * | 
 | 309 | 		 * xtTailgate() accounts for relocated tail extent; | 
 | 310 | 		 */ | 
 | 311 | 		if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) { | 
 | 312 | 			dbFree(ip, nxaddr, nxlen); | 
| Christoph Hellwig | 5dd4056 | 2010-03-03 09:05:00 -0500 | [diff] [blame] | 313 | 			dquot_free_block(ip, nxlen); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 314 | 			goto exit; | 
 | 315 | 		} | 
 | 316 | 	} | 
 | 317 |  | 
 | 318 |  | 
 | 319 | 	/* check if we need to also insert a new extent */ | 
 | 320 | 	if (ninsert) { | 
 | 321 | 		/* perform the insert.  if it fails, free the blocks | 
 | 322 | 		 * to be inserted and make it appear that we only did | 
 | 323 | 		 * the xtExtend() or xtTailgate() above. | 
 | 324 | 		 */ | 
 | 325 | 		xaddr = nxaddr + ntail; | 
 | 326 | 		if (xtInsert (0, ip, xflag, xoff + ntail, (int) ninsert, | 
 | 327 | 			      &xaddr, 0)) { | 
 | 328 | 			dbFree(ip, xaddr, (s64) ninsert); | 
 | 329 | 			delta = nextend; | 
 | 330 | 			nxlen = ntail; | 
 | 331 | 			xflag = 0; | 
 | 332 | 		} | 
 | 333 | 	} | 
 | 334 |  | 
 | 335 | 	/* set the return results */ | 
 | 336 | 	XADaddress(xp, nxaddr); | 
 | 337 | 	XADlength(xp, nxlen); | 
 | 338 | 	XADoffset(xp, xoff); | 
 | 339 | 	xp->flag = xflag; | 
 | 340 |  | 
 | 341 | 	mark_inode_dirty(ip); | 
 | 342 | exit: | 
| Ingo Molnar | 1de8744 | 2006-01-24 15:22:50 -0600 | [diff] [blame] | 343 | 	mutex_unlock(&JFS_IP(ip)->commit_mutex); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 344 | 	return (rc); | 
 | 345 | } | 
 | 346 | #endif			/* _NOTYET */ | 
 | 347 |  | 
 | 348 |  | 
 | 349 | /* | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 350 |  * NAME:	extHint() | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 351 |  * | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 352 |  * FUNCTION:	produce an extent allocation hint for a file offset. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 353 |  * | 
 | 354 |  * PARAMETERS: | 
 | 355 |  *	ip	- the inode of the file. | 
 | 356 |  *	offset  - file offset for which the hint is needed. | 
 | 357 |  *	xp	- pointer to the xad that is to be filled in with | 
 | 358 |  *		  the hint. | 
 | 359 |  * | 
 | 360 |  * RETURN VALUES: | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 361 |  *	0	- success | 
 | 362 |  *	-EIO	- i/o error. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 363 |  */ | 
 | 364 | int extHint(struct inode *ip, s64 offset, xad_t * xp) | 
 | 365 | { | 
 | 366 | 	struct super_block *sb = ip->i_sb; | 
| Dave Kleikamp | fec1878 | 2009-01-09 15:42:04 -0600 | [diff] [blame] | 367 | 	int nbperpage = JFS_SBI(sb)->nbperpage; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 368 | 	s64 prev; | 
| Dave Kleikamp | fec1878 | 2009-01-09 15:42:04 -0600 | [diff] [blame] | 369 | 	int rc = 0; | 
 | 370 | 	s64 xaddr; | 
 | 371 | 	int xlen; | 
 | 372 | 	int xflag; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 373 |  | 
 | 374 | 	/* init the hint as "no hint provided" */ | 
 | 375 | 	XADaddress(xp, 0); | 
 | 376 |  | 
 | 377 | 	/* determine the starting extent offset of the page previous | 
 | 378 | 	 * to the page containing the offset. | 
 | 379 | 	 */ | 
 | 380 | 	prev = ((offset & ~POFFSET) >> JFS_SBI(sb)->l2bsize) - nbperpage; | 
 | 381 |  | 
| Dave Kleikamp | fec1878 | 2009-01-09 15:42:04 -0600 | [diff] [blame] | 382 | 	/* if the offset is in the first page of the file, no hint provided. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 383 | 	 */ | 
 | 384 | 	if (prev < 0) | 
| Dave Kleikamp | fec1878 | 2009-01-09 15:42:04 -0600 | [diff] [blame] | 385 | 		goto out; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 386 |  | 
| Dave Kleikamp | fec1878 | 2009-01-09 15:42:04 -0600 | [diff] [blame] | 387 | 	rc = xtLookup(ip, prev, nbperpage, &xflag, &xaddr, &xlen, 0); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 388 |  | 
| Dave Kleikamp | fec1878 | 2009-01-09 15:42:04 -0600 | [diff] [blame] | 389 | 	if ((rc == 0) && xlen) { | 
 | 390 | 		if (xlen != nbperpage) { | 
 | 391 | 			jfs_error(ip->i_sb, "extHint: corrupt xtree"); | 
 | 392 | 			rc = -EIO; | 
 | 393 | 		} | 
 | 394 | 		XADaddress(xp, xaddr); | 
 | 395 | 		XADlength(xp, xlen); | 
| Dave Kleikamp | f7c52fd | 2009-06-16 13:43:22 -0500 | [diff] [blame] | 396 | 		XADoffset(xp, prev); | 
| Dave Kleikamp | fec1878 | 2009-01-09 15:42:04 -0600 | [diff] [blame] | 397 | 		/* | 
 | 398 | 		 * only preserve the abnr flag within the xad flags | 
 | 399 | 		 * of the returned hint. | 
 | 400 | 		 */ | 
 | 401 | 		xp->flag  = xflag & XAD_NOTRECORDED; | 
 | 402 | 	} else | 
 | 403 | 		rc = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 404 |  | 
| Dave Kleikamp | fec1878 | 2009-01-09 15:42:04 -0600 | [diff] [blame] | 405 | out: | 
 | 406 | 	return (rc); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 407 | } | 
 | 408 |  | 
 | 409 |  | 
 | 410 | /* | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 411 |  * NAME:	extRecord() | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 412 |  * | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 413 |  * FUNCTION:	change a page with a file from not recorded to recorded. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 414 |  * | 
 | 415 |  * PARAMETERS: | 
 | 416 |  *	ip	- inode of the file. | 
 | 417 |  *	cp	- cbuf of the file page. | 
 | 418 |  * | 
 | 419 |  * RETURN VALUES: | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 420 |  *	0	- success | 
 | 421 |  *	-EIO	- i/o error. | 
 | 422 |  *	-ENOSPC	- insufficient disk resources. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 423 |  */ | 
 | 424 | int extRecord(struct inode *ip, xad_t * xp) | 
 | 425 | { | 
 | 426 | 	int rc; | 
 | 427 |  | 
 | 428 | 	txBeginAnon(ip->i_sb); | 
 | 429 |  | 
| Ingo Molnar | 1de8744 | 2006-01-24 15:22:50 -0600 | [diff] [blame] | 430 | 	mutex_lock(&JFS_IP(ip)->commit_mutex); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 431 |  | 
 | 432 | 	/* update the extent */ | 
 | 433 | 	rc = xtUpdate(0, ip, xp); | 
 | 434 |  | 
| Ingo Molnar | 1de8744 | 2006-01-24 15:22:50 -0600 | [diff] [blame] | 435 | 	mutex_unlock(&JFS_IP(ip)->commit_mutex); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 436 | 	return rc; | 
 | 437 | } | 
 | 438 |  | 
 | 439 |  | 
 | 440 | #ifdef _NOTYET | 
 | 441 | /* | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 442 |  * NAME:	extFill() | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 443 |  * | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 444 |  * FUNCTION:	allocate disk space for a file page that represents | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 445 |  *		a file hole. | 
 | 446 |  * | 
 | 447 |  * PARAMETERS: | 
 | 448 |  *	ip	- the inode of the file. | 
 | 449 |  *	cp	- cbuf of the file page represent the hole. | 
 | 450 |  * | 
 | 451 |  * RETURN VALUES: | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 452 |  *	0	- success | 
 | 453 |  *	-EIO	- i/o error. | 
 | 454 |  *	-ENOSPC	- insufficient disk resources. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 455 |  */ | 
 | 456 | int extFill(struct inode *ip, xad_t * xp) | 
 | 457 | { | 
 | 458 | 	int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage; | 
| Theodore Ts'o | ba52de1 | 2006-09-27 01:50:49 -0700 | [diff] [blame] | 459 | 	s64 blkno = offsetXAD(xp) >> ip->i_blkbits; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 460 |  | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 461 | //	assert(ISSPARSE(ip)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 462 |  | 
 | 463 | 	/* initialize the extent allocation hint */ | 
 | 464 | 	XADaddress(xp, 0); | 
 | 465 |  | 
 | 466 | 	/* allocate an extent to fill the hole */ | 
| Richard Knutsson | 4d81715 | 2006-09-30 23:27:14 -0700 | [diff] [blame] | 467 | 	if ((rc = extAlloc(ip, nbperpage, blkno, xp, false))) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 468 | 		return (rc); | 
 | 469 |  | 
 | 470 | 	assert(lengthPXD(xp) == nbperpage); | 
 | 471 |  | 
 | 472 | 	return (0); | 
 | 473 | } | 
 | 474 | #endif			/* _NOTYET */ | 
 | 475 |  | 
 | 476 |  | 
 | 477 | /* | 
 | 478 |  * NAME:	extBalloc() | 
 | 479 |  * | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 480 |  * FUNCTION:	allocate disk blocks to form an extent. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 481 |  * | 
 | 482 |  *		initially, we will try to allocate disk blocks for the | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 483 |  *		requested size (nblocks).  if this fails (nblocks | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 484 |  *		contiguous free blocks not available), we'll try to allocate | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 485 |  *		a smaller number of blocks (producing a smaller extent), with | 
 | 486 |  *		this smaller number of blocks consisting of the requested | 
 | 487 |  *		number of blocks rounded down to the next smaller power of 2 | 
 | 488 |  *		number (i.e. 16 -> 8).  we'll continue to round down and | 
 | 489 |  *		retry the allocation until the number of blocks to allocate | 
 | 490 |  *		is smaller than the number of blocks per page. | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 491 |  * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 492 |  * PARAMETERS: | 
 | 493 |  *	ip	 - the inode of the file. | 
 | 494 |  *	hint	 - disk block number to be used as an allocation hint. | 
 | 495 |  *	*nblocks - pointer to an s64 value.  on entry, this value specifies | 
 | 496 |  *		   the desired number of block to be allocated. on successful | 
 | 497 |  *		   exit, this value is set to the number of blocks actually | 
 | 498 |  *		   allocated. | 
 | 499 |  *	blkno	 - pointer to a block address that is filled in on successful | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 500 |  *		   return with the starting block number of the newly | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 501 |  *		   allocated block range. | 
 | 502 |  * | 
 | 503 |  * RETURN VALUES: | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 504 |  *	0	- success | 
 | 505 |  *	-EIO	- i/o error. | 
 | 506 |  *	-ENOSPC	- insufficient disk resources. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 507 |  */ | 
 | 508 | static int | 
 | 509 | extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno) | 
 | 510 | { | 
 | 511 | 	struct jfs_inode_info *ji = JFS_IP(ip); | 
 | 512 | 	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); | 
 | 513 | 	s64 nb, nblks, daddr, max; | 
 | 514 | 	int rc, nbperpage = sbi->nbperpage; | 
 | 515 | 	struct bmap *bmp = sbi->bmap; | 
 | 516 | 	int ag; | 
 | 517 |  | 
 | 518 | 	/* get the number of blocks to initially attempt to allocate. | 
 | 519 | 	 * we'll first try the number of blocks requested unless this | 
| Andreas Mohr | d6e05ed | 2006-06-26 18:35:02 +0200 | [diff] [blame] | 520 | 	 * number is greater than the maximum number of contiguous free | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 521 | 	 * blocks in the map. in that case, we'll start off with the | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 522 | 	 * maximum free. | 
 | 523 | 	 */ | 
 | 524 | 	max = (s64) 1 << bmp->db_maxfreebud; | 
 | 525 | 	if (*nblocks >= max && *nblocks > nbperpage) | 
 | 526 | 		nb = nblks = (max > nbperpage) ? max : nbperpage; | 
 | 527 | 	else | 
 | 528 | 		nb = nblks = *nblocks; | 
 | 529 |  | 
 | 530 | 	/* try to allocate blocks */ | 
 | 531 | 	while ((rc = dbAlloc(ip, hint, nb, &daddr)) != 0) { | 
 | 532 | 		/* if something other than an out of space error, | 
 | 533 | 		 * stop and return this error. | 
 | 534 | 		 */ | 
 | 535 | 		if (rc != -ENOSPC) | 
 | 536 | 			return (rc); | 
 | 537 |  | 
 | 538 | 		/* decrease the allocation request size */ | 
 | 539 | 		nb = min(nblks, extRoundDown(nb)); | 
 | 540 |  | 
 | 541 | 		/* give up if we cannot cover a page */ | 
 | 542 | 		if (nb < nbperpage) | 
 | 543 | 			return (rc); | 
 | 544 | 	} | 
 | 545 |  | 
 | 546 | 	*nblocks = nb; | 
 | 547 | 	*blkno = daddr; | 
 | 548 |  | 
 | 549 | 	if (S_ISREG(ip->i_mode) && (ji->fileset == FILESYSTEM_I)) { | 
 | 550 | 		ag = BLKTOAG(daddr, sbi); | 
 | 551 | 		spin_lock_irq(&ji->ag_lock); | 
 | 552 | 		if (ji->active_ag == -1) { | 
 | 553 | 			atomic_inc(&bmp->db_active[ag]); | 
 | 554 | 			ji->active_ag = ag; | 
 | 555 | 		} else if (ji->active_ag != ag) { | 
 | 556 | 			atomic_dec(&bmp->db_active[ji->active_ag]); | 
 | 557 | 			atomic_inc(&bmp->db_active[ag]); | 
 | 558 | 			ji->active_ag = ag; | 
 | 559 | 		} | 
 | 560 | 		spin_unlock_irq(&ji->ag_lock); | 
 | 561 | 	} | 
 | 562 |  | 
 | 563 | 	return (0); | 
 | 564 | } | 
 | 565 |  | 
 | 566 |  | 
 | 567 | #ifdef _NOTYET | 
 | 568 | /* | 
 | 569 |  * NAME:	extBrealloc() | 
 | 570 |  * | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 571 |  * FUNCTION:	attempt to extend an extent's allocation. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 572 |  * | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 573 |  *		Initially, we will try to extend the extent's allocation | 
 | 574 |  *		in place.  If this fails, we'll try to move the extent | 
 | 575 |  *		to a new set of blocks.  If moving the extent, we initially | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 576 |  *		will try to allocate disk blocks for the requested size | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 577 |  *		(newnblks).  if this fails (new contiguous free blocks not | 
| Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 578 |  *		available), we'll try to allocate a smaller number of | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 579 |  *		blocks (producing a smaller extent), with this smaller | 
 | 580 |  *		number of blocks consisting of the requested number of | 
 | 581 |  *		blocks rounded down to the next smaller power of 2 | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 582 |  *		number (i.e. 16 -> 8).  We'll continue to round down and | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 583 |  *		retry the allocation until the number of blocks to allocate | 
 | 584 |  *		is smaller than the number of blocks per page. | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 585 |  * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 586 |  * PARAMETERS: | 
 | 587 |  *	ip	 - the inode of the file. | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 588 |  *	blkno	 - starting block number of the extents current allocation. | 
 | 589 |  *	nblks	 - number of blocks within the extents current allocation. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 590 |  *	newnblks - pointer to a s64 value.  on entry, this value is the | 
 | 591 |  *		   the new desired extent size (number of blocks).  on | 
 | 592 |  *		   successful exit, this value is set to the extent's actual | 
 | 593 |  *		   new size (new number of blocks). | 
 | 594 |  *	newblkno - the starting block number of the extents new allocation. | 
 | 595 |  * | 
 | 596 |  * RETURN VALUES: | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 597 |  *	0	- success | 
 | 598 |  *	-EIO	- i/o error. | 
 | 599 |  *	-ENOSPC	- insufficient disk resources. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 600 |  */ | 
 | 601 | static int | 
 | 602 | extBrealloc(struct inode *ip, | 
 | 603 | 	    s64 blkno, s64 nblks, s64 * newnblks, s64 * newblkno) | 
 | 604 | { | 
 | 605 | 	int rc; | 
 | 606 |  | 
 | 607 | 	/* try to extend in place */ | 
 | 608 | 	if ((rc = dbExtend(ip, blkno, nblks, *newnblks - nblks)) == 0) { | 
 | 609 | 		*newblkno = blkno; | 
 | 610 | 		return (0); | 
 | 611 | 	} else { | 
 | 612 | 		if (rc != -ENOSPC) | 
 | 613 | 			return (rc); | 
 | 614 | 	} | 
 | 615 |  | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 616 | 	/* in place extension not possible. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 617 | 	 * try to move the extent to a new set of blocks. | 
 | 618 | 	 */ | 
 | 619 | 	return (extBalloc(ip, blkno, newnblks, newblkno)); | 
 | 620 | } | 
 | 621 | #endif			/* _NOTYET */ | 
 | 622 |  | 
 | 623 |  | 
 | 624 | /* | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 625 |  * NAME:	extRoundDown() | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 626 |  * | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 627 |  * FUNCTION:	round down a specified number of blocks to the next | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 628 |  *		smallest power of 2 number. | 
 | 629 |  * | 
 | 630 |  * PARAMETERS: | 
 | 631 |  *	nb	- the inode of the file. | 
 | 632 |  * | 
 | 633 |  * RETURN VALUES: | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 634 |  *	next smallest power of 2 number. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 635 |  */ | 
 | 636 | static s64 extRoundDown(s64 nb) | 
 | 637 | { | 
 | 638 | 	int i; | 
 | 639 | 	u64 m, k; | 
 | 640 |  | 
 | 641 | 	for (i = 0, m = (u64) 1 << 63; i < 64; i++, m >>= 1) { | 
 | 642 | 		if (m & nb) | 
 | 643 | 			break; | 
 | 644 | 	} | 
 | 645 |  | 
 | 646 | 	i = 63 - i; | 
 | 647 | 	k = (u64) 1 << i; | 
 | 648 | 	k = ((k - 1) & nb) ? k : k >> 1; | 
 | 649 |  | 
 | 650 | 	return (k); | 
 | 651 | } |