2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) International Business Machines Corp . , 2000 - 2004
*
* 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
2006-10-02 18:55:27 +04:00
* the Free Software Foundation ; either version 2 of the License , or
2005-04-17 02:20:36 +04:00
* ( at your option ) any later version .
2006-10-02 18:55:27 +04:00
*
2005-04-17 02:20:36 +04:00
* This program is distributed in the hope that it will 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
2006-10-02 18:55:27 +04:00
* along with this program ; if not , write to the Free Software
2005-04-17 02:20:36 +04:00
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/fs.h>
# include <linux/quotaops.h>
# include "jfs_incore.h"
2005-05-05 00:29:35 +04:00
# include "jfs_inode.h"
2005-04-17 02:20:36 +04:00
# include "jfs_superblock.h"
# include "jfs_dmap.h"
# include "jfs_extent.h"
# include "jfs_debug.h"
/*
* forward references
*/
static int extBalloc ( struct inode * , s64 , s64 * , s64 * ) ;
# ifdef _NOTYET
static int extBrealloc ( struct inode * , s64 , s64 , s64 * , s64 * ) ;
# endif
static s64 extRoundDown ( s64 nb ) ;
2007-06-07 00:28:35 +04:00
# define DPD(a) (printk("(a): %d\n",(a)))
# define DPC(a) (printk("(a): %c\n",(a)))
2005-04-17 02:20:36 +04:00
# define DPL1(a) \
{ \
if ( ( a ) > > 32 ) \
printk ( " (a): %x%08x " , ( a ) ) ; \
else \
printk ( " (a): %x " , ( a ) < < 32 ) ; \
}
# define DPL(a) \
{ \
if ( ( a ) > > 32 ) \
printk ( " (a): %x%08x \n " , ( a ) ) ; \
else \
printk ( " (a): %x \n " , ( a ) < < 32 ) ; \
}
2007-06-07 00:28:35 +04:00
# define DPD1(a) (printk("(a): %d ",(a)))
# define DPX(a) (printk("(a): %08x\n",(a)))
# define DPX1(a) (printk("(a): %08x ",(a)))
# define DPS(a) (printk("%s\n",(a)))
# define DPE(a) (printk("\nENTERING: %s\n",(a)))
# define DPE1(a) (printk("\nENTERING: %s",(a)))
# define DPS1(a) (printk(" %s ",(a)))
2005-04-17 02:20:36 +04:00
/*
* NAME : extAlloc ( )
*
2007-06-07 00:28:35 +04:00
* FUNCTION : allocate an extent for a specified page range within a
2005-04-17 02:20:36 +04:00
* file .
*
* PARAMETERS :
* ip - the inode of the file .
* xlen - requested extent length .
* pno - the starting page number with the file .
* xp - pointer to an xad . on entry , xad describes an
* extent that is used as an allocation hint if the
* xaddr of the xad is non - zero . on successful exit ,
* the xad describes the newly allocated extent .
2006-10-01 10:27:14 +04:00
* abnr - bool indicating whether the newly allocated extent
2005-04-17 02:20:36 +04:00
* should be marked as allocated but not recorded .
*
* RETURN VALUES :
2007-06-07 00:28:35 +04:00
* 0 - success
* - EIO - i / o error .
* - ENOSPC - insufficient disk resources .
2005-04-17 02:20:36 +04:00
*/
int
2006-10-01 10:27:14 +04:00
extAlloc ( struct inode * ip , s64 xlen , s64 pno , xad_t * xp , bool abnr )
2005-04-17 02:20:36 +04:00
{
struct jfs_sb_info * sbi = JFS_SBI ( ip - > i_sb ) ;
s64 nxlen , nxaddr , xoff , hint , xaddr = 0 ;
int rc ;
int xflag ;
/* This blocks if we are low on resources */
txBeginAnon ( ip - > i_sb ) ;
/* Avoid race with jfs_commit_inode() */
2006-01-25 00:22:50 +03:00
mutex_lock ( & JFS_IP ( ip ) - > commit_mutex ) ;
2005-04-17 02:20:36 +04:00
/* validate extent length */
if ( xlen > MAXXLEN )
xlen = MAXXLEN ;
/* get the page's starting extent offset */
xoff = pno < < sbi - > l2nbperpage ;
/* check if an allocation hint was provided */
if ( ( hint = addressXAD ( xp ) ) ) {
/* get the size of the extent described by the hint */
nxlen = lengthXAD ( xp ) ;
/* check if the hint is for the portion of the file
* immediately previous to the current allocation
* request and if hint extent has the same abnr
* value as the current request . if so , we can
* extend the hint extent to include the current
* extent if we can allocate the blocks immediately
* following the hint extent .
*/
if ( offsetXAD ( xp ) + nxlen = = xoff & &
2006-10-01 10:27:14 +04:00
abnr = = ( ( xp - > flag & XAD_NOTRECORDED ) ? true : false ) )
2005-04-17 02:20:36 +04:00
xaddr = hint + nxlen ;
/* adjust the hint to the last block of the extent */
hint + = ( nxlen - 1 ) ;
}
/* allocate the disk blocks for the extent. initially, extBalloc()
2006-10-02 18:55:27 +04:00
* will try to allocate disk blocks for the requested size ( xlen ) .
2006-06-26 20:35:02 +04:00
* if this fails ( xlen contiguous free blocks not avaliable ) , it ' ll
2005-04-17 02:20:36 +04:00
* try to allocate a smaller number of blocks ( producing a smaller
* extent ) , with this smaller number of blocks consisting of the
* requested number of blocks rounded down to the next smaller
* power of 2 number ( i . e . 16 - > 8 ) . it ' ll continue to round down
* and retry the allocation until the number of blocks to allocate
* is smaller than the number of blocks per page .
*/
nxlen = xlen ;
if ( ( rc = extBalloc ( ip , hint ? hint : INOHINT ( ip ) , & nxlen , & nxaddr ) ) ) {
2006-01-25 00:22:50 +03:00
mutex_unlock ( & JFS_IP ( ip ) - > commit_mutex ) ;
2005-04-17 02:20:36 +04:00
return ( rc ) ;
}
/* Allocate blocks to quota. */
if ( DQUOT_ALLOC_BLOCK ( ip , nxlen ) ) {
dbFree ( ip , nxaddr , ( s64 ) nxlen ) ;
2006-01-25 00:22:50 +03:00
mutex_unlock ( & JFS_IP ( ip ) - > commit_mutex ) ;
2005-04-17 02:20:36 +04:00
return - EDQUOT ;
}
/* determine the value of the extent flag */
2006-10-01 10:27:14 +04:00
xflag = abnr ? XAD_NOTRECORDED : 0 ;
2005-04-17 02:20:36 +04:00
2006-10-02 18:55:27 +04:00
/* if we can extend the hint extent to cover the current request,
2005-04-17 02:20:36 +04:00
* extend it . otherwise , insert a new extent to
* cover the current request .
*/
if ( xaddr & & xaddr = = nxaddr )
rc = xtExtend ( 0 , ip , xoff , ( int ) nxlen , 0 ) ;
else
rc = xtInsert ( 0 , ip , xflag , xoff , ( int ) nxlen , & nxaddr , 0 ) ;
2006-10-02 18:55:27 +04:00
/* if the extend or insert failed,
2005-04-17 02:20:36 +04:00
* free the newly allocated blocks and return the error .
*/
if ( rc ) {
dbFree ( ip , nxaddr , nxlen ) ;
DQUOT_FREE_BLOCK ( ip , nxlen ) ;
2006-01-25 00:22:50 +03:00
mutex_unlock ( & JFS_IP ( ip ) - > commit_mutex ) ;
2005-04-17 02:20:36 +04:00
return ( rc ) ;
}
/* set the results of the extent allocation */
XADaddress ( xp , nxaddr ) ;
XADlength ( xp , nxlen ) ;
XADoffset ( xp , xoff ) ;
xp - > flag = xflag ;
mark_inode_dirty ( ip ) ;
2006-01-25 00:22:50 +03:00
mutex_unlock ( & JFS_IP ( ip ) - > commit_mutex ) ;
2005-04-17 02:20:36 +04:00
/*
* COMMIT_SyncList flags an anonymous tlock on page that is on
* sync list .
* We need to commit the inode to get the page written disk .
*/
if ( test_and_clear_cflag ( COMMIT_Synclist , ip ) )
jfs_commit_inode ( ip , 0 ) ;
return ( 0 ) ;
}
# ifdef _NOTYET
/*
2007-06-07 00:28:35 +04:00
* NAME : extRealloc ( )
2005-04-17 02:20:36 +04:00
*
2007-06-07 00:28:35 +04:00
* FUNCTION : extend the allocation of a file extent containing a
2005-04-17 02:20:36 +04:00
* partial back last page .
*
* PARAMETERS :
* ip - the inode of the file .
* cp - cbuf for the partial backed last page .
* xlen - request size of the resulting extent .
* xp - pointer to an xad . on successful exit , the xad
* describes the newly allocated extent .
2006-10-01 10:27:14 +04:00
* abnr - bool indicating whether the newly allocated extent
2005-04-17 02:20:36 +04:00
* should be marked as allocated but not recorded .
*
* RETURN VALUES :
2007-06-07 00:28:35 +04:00
* 0 - success
* - EIO - i / o error .
* - ENOSPC - insufficient disk resources .
2005-04-17 02:20:36 +04:00
*/
2006-10-01 10:27:14 +04:00
int extRealloc ( struct inode * ip , s64 nxlen , xad_t * xp , bool abnr )
2005-04-17 02:20:36 +04:00
{
struct super_block * sb = ip - > i_sb ;
s64 xaddr , xlen , nxaddr , delta , xoff ;
s64 ntail , nextend , ninsert ;
int rc , nbperpage = JFS_SBI ( sb ) - > nbperpage ;
int xflag ;
/* This blocks if we are low on resources */
txBeginAnon ( ip - > i_sb ) ;
2006-01-25 00:22:50 +03:00
mutex_lock ( & JFS_IP ( ip ) - > commit_mutex ) ;
2005-04-17 02:20:36 +04:00
/* validate extent length */
if ( nxlen > MAXXLEN )
nxlen = MAXXLEN ;
/* get the extend (partial) page's disk block address and
* number of blocks .
*/
xaddr = addressXAD ( xp ) ;
xlen = lengthXAD ( xp ) ;
xoff = offsetXAD ( xp ) ;
/* if the extend page is abnr and if the request is for
2006-10-02 18:55:27 +04:00
* the extent to be allocated and recorded ,
2005-04-17 02:20:36 +04:00
* make the page allocated and recorded .
*/
if ( ( xp - > flag & XAD_NOTRECORDED ) & & ! abnr ) {
xp - > flag = 0 ;
if ( ( rc = xtUpdate ( 0 , ip , xp ) ) )
goto exit ;
}
/* try to allocated the request number of blocks for the
* extent . dbRealloc ( ) first tries to satisfy the request
* by extending the allocation in place . otherwise , it will
* try to allocate a new set of blocks large enough for the
* request . in satisfying a request , dbReAlloc ( ) may allocate
* less than what was request but will always allocate enough
* space as to satisfy the extend page .
*/
if ( ( rc = extBrealloc ( ip , xaddr , xlen , & nxlen , & nxaddr ) ) )
goto exit ;
/* Allocat blocks to quota. */
if ( DQUOT_ALLOC_BLOCK ( ip , nxlen ) ) {
dbFree ( ip , nxaddr , ( s64 ) nxlen ) ;
2006-01-25 00:22:50 +03:00
mutex_unlock ( & JFS_IP ( ip ) - > commit_mutex ) ;
2005-04-17 02:20:36 +04:00
return - EDQUOT ;
}
delta = nxlen - xlen ;
/* check if the extend page is not abnr but the request is abnr
* and the allocated disk space is for more than one page . if this
* is the case , there is a miss match of abnr between the extend page
* and the one or more pages following the extend page . as a result ,
* two extents will have to be manipulated . the first will be that
* of the extent of the extend page and will be manipulated thru
* an xtExtend ( ) or an xtTailgate ( ) , depending upon whether the
* disk allocation occurred as an inplace extension . the second
* extent will be manipulated ( created ) through an xtInsert ( ) and
* will be for the pages following the extend page .
*/
if ( abnr & & ( ! ( xp - > flag & XAD_NOTRECORDED ) ) & & ( nxlen > nbperpage ) ) {
ntail = nbperpage ;
nextend = ntail - xlen ;
ninsert = nxlen - nbperpage ;
xflag = XAD_NOTRECORDED ;
} else {
ntail = nxlen ;
nextend = delta ;
ninsert = 0 ;
xflag = xp - > flag ;
}
/* if we were able to extend the disk allocation in place,
* extend the extent . otherwise , move the extent to a
* new disk location .
*/
if ( xaddr = = nxaddr ) {
/* extend the extent */
if ( ( rc = xtExtend ( 0 , ip , xoff + xlen , ( int ) nextend , 0 ) ) ) {
dbFree ( ip , xaddr + xlen , delta ) ;
DQUOT_FREE_BLOCK ( ip , nxlen ) ;
goto exit ;
}
} else {
/*
* move the extent to a new location :
*
* xtTailgate ( ) accounts for relocated tail extent ;
*/
if ( ( rc = xtTailgate ( 0 , ip , xoff , ( int ) ntail , nxaddr , 0 ) ) ) {
dbFree ( ip , nxaddr , nxlen ) ;
DQUOT_FREE_BLOCK ( ip , nxlen ) ;
goto exit ;
}
}
/* check if we need to also insert a new extent */
if ( ninsert ) {
/* perform the insert. if it fails, free the blocks
* to be inserted and make it appear that we only did
* the xtExtend ( ) or xtTailgate ( ) above .
*/
xaddr = nxaddr + ntail ;
if ( xtInsert ( 0 , ip , xflag , xoff + ntail , ( int ) ninsert ,
& xaddr , 0 ) ) {
dbFree ( ip , xaddr , ( s64 ) ninsert ) ;
delta = nextend ;
nxlen = ntail ;
xflag = 0 ;
}
}
/* set the return results */
XADaddress ( xp , nxaddr ) ;
XADlength ( xp , nxlen ) ;
XADoffset ( xp , xoff ) ;
xp - > flag = xflag ;
mark_inode_dirty ( ip ) ;
exit :
2006-01-25 00:22:50 +03:00
mutex_unlock ( & JFS_IP ( ip ) - > commit_mutex ) ;
2005-04-17 02:20:36 +04:00
return ( rc ) ;
}
# endif /* _NOTYET */
/*
2007-06-07 00:28:35 +04:00
* NAME : extHint ( )
2005-04-17 02:20:36 +04:00
*
2007-06-07 00:28:35 +04:00
* FUNCTION : produce an extent allocation hint for a file offset .
2005-04-17 02:20:36 +04:00
*
* PARAMETERS :
* ip - the inode of the file .
* offset - file offset for which the hint is needed .
* xp - pointer to the xad that is to be filled in with
* the hint .
*
* RETURN VALUES :
2007-06-07 00:28:35 +04:00
* 0 - success
* - EIO - i / o error .
2005-04-17 02:20:36 +04:00
*/
int extHint ( struct inode * ip , s64 offset , xad_t * xp )
{
struct super_block * sb = ip - > i_sb ;
struct xadlist xadl ;
struct lxdlist lxdl ;
lxd_t lxd ;
s64 prev ;
int rc , nbperpage = JFS_SBI ( sb ) - > nbperpage ;
/* init the hint as "no hint provided" */
XADaddress ( xp , 0 ) ;
/* determine the starting extent offset of the page previous
* to the page containing the offset .
*/
prev = ( ( offset & ~ POFFSET ) > > JFS_SBI ( sb ) - > l2bsize ) - nbperpage ;
/* if the offsets in the first page of the file,
* no hint provided .
*/
if ( prev < 0 )
return ( 0 ) ;
/* prepare to lookup the previous page's extent info */
lxdl . maxnlxd = 1 ;
lxdl . nlxd = 1 ;
lxdl . lxd = & lxd ;
LXDoffset ( & lxd , prev )
2007-06-07 00:28:35 +04:00
LXDlength ( & lxd , nbperpage ) ;
2005-04-17 02:20:36 +04:00
xadl . maxnxad = 1 ;
xadl . nxad = 0 ;
xadl . xad = xp ;
/* perform the lookup */
if ( ( rc = xtLookupList ( ip , & lxdl , & xadl , 0 ) ) )
return ( rc ) ;
2007-06-07 00:28:35 +04:00
/* check if no extent exists for the previous page.
2005-04-17 02:20:36 +04:00
* this is possible for sparse files .
*/
if ( xadl . nxad = = 0 ) {
2007-06-07 00:28:35 +04:00
// assert(ISSPARSE(ip));
2005-04-17 02:20:36 +04:00
return ( 0 ) ;
}
/* only preserve the abnr flag within the xad flags
* of the returned hint .
*/
xp - > flag & = XAD_NOTRECORDED ;
2007-06-07 00:28:35 +04:00
if ( xadl . nxad ! = 1 | | lengthXAD ( xp ) ! = nbperpage ) {
2005-04-17 02:20:36 +04:00
jfs_error ( ip - > i_sb , " extHint: corrupt xtree " ) ;
return - EIO ;
2007-06-07 00:28:35 +04:00
}
2005-04-17 02:20:36 +04:00
return ( 0 ) ;
}
/*
2007-06-07 00:28:35 +04:00
* NAME : extRecord ( )
2005-04-17 02:20:36 +04:00
*
2007-06-07 00:28:35 +04:00
* FUNCTION : change a page with a file from not recorded to recorded .
2005-04-17 02:20:36 +04:00
*
* PARAMETERS :
* ip - inode of the file .
* cp - cbuf of the file page .
*
* RETURN VALUES :
2007-06-07 00:28:35 +04:00
* 0 - success
* - EIO - i / o error .
* - ENOSPC - insufficient disk resources .
2005-04-17 02:20:36 +04:00
*/
int extRecord ( struct inode * ip , xad_t * xp )
{
int rc ;
txBeginAnon ( ip - > i_sb ) ;
2006-01-25 00:22:50 +03:00
mutex_lock ( & JFS_IP ( ip ) - > commit_mutex ) ;
2005-04-17 02:20:36 +04:00
/* update the extent */
rc = xtUpdate ( 0 , ip , xp ) ;
2006-01-25 00:22:50 +03:00
mutex_unlock ( & JFS_IP ( ip ) - > commit_mutex ) ;
2005-04-17 02:20:36 +04:00
return rc ;
}
# ifdef _NOTYET
/*
2007-06-07 00:28:35 +04:00
* NAME : extFill ( )
2005-04-17 02:20:36 +04:00
*
2007-06-07 00:28:35 +04:00
* FUNCTION : allocate disk space for a file page that represents
2005-04-17 02:20:36 +04:00
* a file hole .
*
* PARAMETERS :
* ip - the inode of the file .
* cp - cbuf of the file page represent the hole .
*
* RETURN VALUES :
2007-06-07 00:28:35 +04:00
* 0 - success
* - EIO - i / o error .
* - ENOSPC - insufficient disk resources .
2005-04-17 02:20:36 +04:00
*/
int extFill ( struct inode * ip , xad_t * xp )
{
int rc , nbperpage = JFS_SBI ( ip - > i_sb ) - > nbperpage ;
2006-09-27 12:50:49 +04:00
s64 blkno = offsetXAD ( xp ) > > ip - > i_blkbits ;
2005-04-17 02:20:36 +04:00
2007-06-07 00:28:35 +04:00
// assert(ISSPARSE(ip));
2005-04-17 02:20:36 +04:00
/* initialize the extent allocation hint */
XADaddress ( xp , 0 ) ;
/* allocate an extent to fill the hole */
2006-10-01 10:27:14 +04:00
if ( ( rc = extAlloc ( ip , nbperpage , blkno , xp , false ) ) )
2005-04-17 02:20:36 +04:00
return ( rc ) ;
assert ( lengthPXD ( xp ) = = nbperpage ) ;
return ( 0 ) ;
}
# endif /* _NOTYET */
/*
* NAME : extBalloc ( )
*
2007-06-07 00:28:35 +04:00
* FUNCTION : allocate disk blocks to form an extent .
2005-04-17 02:20:36 +04:00
*
* initially , we will try to allocate disk blocks for the
2006-10-02 18:55:27 +04:00
* requested size ( nblocks ) . if this fails ( nblocks
2006-06-26 20:35:02 +04:00
* contiguous free blocks not avaliable ) , we ' ll try to allocate
2005-04-17 02:20:36 +04:00
* a smaller number of blocks ( producing a smaller extent ) , with
* this smaller number of blocks consisting of the requested
* number of blocks rounded down to the next smaller power of 2
* number ( i . e . 16 - > 8 ) . we ' ll continue to round down and
* retry the allocation until the number of blocks to allocate
* is smaller than the number of blocks per page .
2006-10-02 18:55:27 +04:00
*
2005-04-17 02:20:36 +04:00
* PARAMETERS :
* ip - the inode of the file .
* hint - disk block number to be used as an allocation hint .
* * nblocks - pointer to an s64 value . on entry , this value specifies
* the desired number of block to be allocated . on successful
* exit , this value is set to the number of blocks actually
* allocated .
* blkno - pointer to a block address that is filled in on successful
2006-10-02 18:55:27 +04:00
* return with the starting block number of the newly
2005-04-17 02:20:36 +04:00
* allocated block range .
*
* RETURN VALUES :
2007-06-07 00:28:35 +04:00
* 0 - success
* - EIO - i / o error .
* - ENOSPC - insufficient disk resources .
2005-04-17 02:20:36 +04:00
*/
static int
extBalloc ( struct inode * ip , s64 hint , s64 * nblocks , s64 * blkno )
{
struct jfs_inode_info * ji = JFS_IP ( ip ) ;
struct jfs_sb_info * sbi = JFS_SBI ( ip - > i_sb ) ;
s64 nb , nblks , daddr , max ;
int rc , nbperpage = sbi - > nbperpage ;
struct bmap * bmp = sbi - > bmap ;
int ag ;
/* get the number of blocks to initially attempt to allocate.
* we ' ll first try the number of blocks requested unless this
2006-06-26 20:35:02 +04:00
* number is greater than the maximum number of contiguous free
2006-10-02 18:55:27 +04:00
* blocks in the map . in that case , we ' ll start off with the
2005-04-17 02:20:36 +04:00
* maximum free .
*/
max = ( s64 ) 1 < < bmp - > db_maxfreebud ;
if ( * nblocks > = max & & * nblocks > nbperpage )
nb = nblks = ( max > nbperpage ) ? max : nbperpage ;
else
nb = nblks = * nblocks ;
/* try to allocate blocks */
while ( ( rc = dbAlloc ( ip , hint , nb , & daddr ) ) ! = 0 ) {
/* if something other than an out of space error,
* stop and return this error .
*/
if ( rc ! = - ENOSPC )
return ( rc ) ;
/* decrease the allocation request size */
nb = min ( nblks , extRoundDown ( nb ) ) ;
/* give up if we cannot cover a page */
if ( nb < nbperpage )
return ( rc ) ;
}
* nblocks = nb ;
* blkno = daddr ;
if ( S_ISREG ( ip - > i_mode ) & & ( ji - > fileset = = FILESYSTEM_I ) ) {
ag = BLKTOAG ( daddr , sbi ) ;
spin_lock_irq ( & ji - > ag_lock ) ;
if ( ji - > active_ag = = - 1 ) {
atomic_inc ( & bmp - > db_active [ ag ] ) ;
ji - > active_ag = ag ;
} else if ( ji - > active_ag ! = ag ) {
atomic_dec ( & bmp - > db_active [ ji - > active_ag ] ) ;
atomic_inc ( & bmp - > db_active [ ag ] ) ;
ji - > active_ag = ag ;
}
spin_unlock_irq ( & ji - > ag_lock ) ;
}
return ( 0 ) ;
}
# ifdef _NOTYET
/*
* NAME : extBrealloc ( )
*
2007-06-07 00:28:35 +04:00
* FUNCTION : attempt to extend an extent ' s allocation .
2005-04-17 02:20:36 +04:00
*
2006-10-02 18:55:27 +04:00
* Initially , we will try to extend the extent ' s allocation
* in place . If this fails , we ' ll try to move the extent
* to a new set of blocks . If moving the extent , we initially
2005-04-17 02:20:36 +04:00
* will try to allocate disk blocks for the requested size
2006-10-02 18:55:27 +04:00
* ( newnblks ) . if this fails ( new contiguous free blocks not
* avaliable ) , we ' ll try to allocate a smaller number of
2005-04-17 02:20:36 +04:00
* blocks ( producing a smaller extent ) , with this smaller
* number of blocks consisting of the requested number of
* blocks rounded down to the next smaller power of 2
2006-10-02 18:55:27 +04:00
* number ( i . e . 16 - > 8 ) . We ' ll continue to round down and
2005-04-17 02:20:36 +04:00
* retry the allocation until the number of blocks to allocate
* is smaller than the number of blocks per page .
2006-10-02 18:55:27 +04:00
*
2005-04-17 02:20:36 +04:00
* PARAMETERS :
* ip - the inode of the file .
2007-06-07 00:28:35 +04:00
* blkno - starting block number of the extents current allocation .
* nblks - number of blocks within the extents current allocation .
2005-04-17 02:20:36 +04:00
* newnblks - pointer to a s64 value . on entry , this value is the
* the new desired extent size ( number of blocks ) . on
* successful exit , this value is set to the extent ' s actual
* new size ( new number of blocks ) .
* newblkno - the starting block number of the extents new allocation .
*
* RETURN VALUES :
2007-06-07 00:28:35 +04:00
* 0 - success
* - EIO - i / o error .
* - ENOSPC - insufficient disk resources .
2005-04-17 02:20:36 +04:00
*/
static int
extBrealloc ( struct inode * ip ,
s64 blkno , s64 nblks , s64 * newnblks , s64 * newblkno )
{
int rc ;
/* try to extend in place */
if ( ( rc = dbExtend ( ip , blkno , nblks , * newnblks - nblks ) ) = = 0 ) {
* newblkno = blkno ;
return ( 0 ) ;
} else {
if ( rc ! = - ENOSPC )
return ( rc ) ;
}
2006-10-02 18:55:27 +04:00
/* in place extension not possible.
2005-04-17 02:20:36 +04:00
* try to move the extent to a new set of blocks .
*/
return ( extBalloc ( ip , blkno , newnblks , newblkno ) ) ;
}
# endif /* _NOTYET */
/*
2007-06-07 00:28:35 +04:00
* NAME : extRoundDown ( )
2005-04-17 02:20:36 +04:00
*
2007-06-07 00:28:35 +04:00
* FUNCTION : round down a specified number of blocks to the next
2005-04-17 02:20:36 +04:00
* smallest power of 2 number .
*
* PARAMETERS :
* nb - the inode of the file .
*
* RETURN VALUES :
2007-06-07 00:28:35 +04:00
* next smallest power of 2 number .
2005-04-17 02:20:36 +04:00
*/
static s64 extRoundDown ( s64 nb )
{
int i ;
u64 m , k ;
for ( i = 0 , m = ( u64 ) 1 < < 63 ; i < 64 ; i + + , m > > = 1 ) {
if ( m & nb )
break ;
}
i = 63 - i ;
k = ( u64 ) 1 < < i ;
k = ( ( k - 1 ) & nb ) ? k : k > > 1 ;
return ( k ) ;
}