📄 jfs_extent.c
字号:
/* * Copyright (C) International Business Machines Corp., 2000-2003 * * 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; either version 2 of the License, or * (at your option) any later version. * * 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 * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <linux/fs.h>#include "jfs_incore.h"#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 _NOTYETstatic int extBrealloc(struct inode *, s64, s64, s64 *, s64 *);#endifstatic s64 extRoundDown(s64 nb);/* * external references */extern int jfs_commit_inode(struct inode *, int);#define DPD(a) (printk("(a): %d\n",(a)))#define DPC(a) (printk("(a): %c\n",(a)))#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); \}#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)))/* * NAME: extAlloc() * * FUNCTION: allocate an extent for a specified page range within a * 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. * abnr - boolean_t indicating whether the newly allocated extent * should be marked as allocated but not recorded. * * RETURN VALUES: * 0 - success * -EIO - i/o error. * -ENOSPC - insufficient disk resources. */intextAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr){ 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() */ down(&JFS_IP(ip)->commit_sem); /* 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 && abnr == ((xp->flag & XAD_NOTRECORDED) ? TRUE : FALSE)) 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() * will try to allocate disk blocks for the requested size (xlen). * if this fails (xlen contigious free blocks not avaliable), it'll * 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))) { up(&JFS_IP(ip)->commit_sem); return (rc); } /* determine the value of the extent flag */ xflag = (abnr == TRUE) ? XAD_NOTRECORDED : 0; /* if we can extend the hint extent to cover the current request, * 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); /* if the extend or insert failed, * free the newly allocated blocks and return the error. */ if (rc) { dbFree(ip, nxaddr, nxlen); up(&JFS_IP(ip)->commit_sem); return (rc); } /* update the number of blocks allocated to the file */ ip->i_blocks += LBLK2PBLK(ip->i_sb, nxlen); /* set the results of the extent allocation */ XADaddress(xp, nxaddr); XADlength(xp, nxlen); XADoffset(xp, xoff); xp->flag = xflag; mark_inode_dirty(ip); set_cflag(COMMIT_Syncdata, ip); up(&JFS_IP(ip)->commit_sem); /* * 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/* * NAME: extRealloc() * * FUNCTION: extend the allocation of a file extent containing a * 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. * abnr - boolean_t indicating whether the newly allocated extent * should be marked as allocated but not recorded. * * RETURN VALUES: * 0 - success * -EIO - i/o error. * -ENOSPC - insufficient disk resources. */int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr){ 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); down(&JFS_IP(ip)->commit_sem); /* 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 * the extent to be allocated and recorded, * 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; 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); 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); 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; } } /* update the inode with the number of blocks allocated */ ip->i_blocks += LBLK2PBLK(sb, delta); /* set the return results */ XADaddress(xp, nxaddr); XADlength(xp, nxlen);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -