⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jfs_dtree.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	dtDeleteUp() * * function: *	free empty pages as propagating deletion up the tree * * parameter: * * return: */static int dtDeleteUp(tid_t tid, struct inode *ip,	   struct metapage * fmp, dtpage_t * fp, struct btstack * btstack){	int rc = 0;	struct metapage *mp;	dtpage_t *p;	int index, nextindex;	int xlen;	struct btframe *parent;	struct dt_lock *dtlck;	struct tlock *tlck;	struct lv *lv;	struct pxd_lock *pxdlock;	int i;	/*	 *      keep the root leaf page which has become empty	 */	if (BT_IS_ROOT(fmp)) {		/*		 * reset the root		 *		 * dtInitRoot() acquires txlock on the root		 */		dtInitRoot(tid, ip, PARENT(ip));		DT_PUTPAGE(fmp);		return 0;	}	/*	 *      free the non-root leaf page	 */	/*	 * acquire a transaction lock on the page	 *	 * write FREEXTENT|NOREDOPAGE log record	 * N.B. linelock is overlaid as freed extent descriptor, and	 * the buffer page is freed;	 */	tlck = txMaplock(tid, ip, tlckDTREE | tlckFREE);	pxdlock = (struct pxd_lock *) & tlck->lock;	pxdlock->flag = mlckFREEPXD;	pxdlock->pxd = fp->header.self;	pxdlock->index = 1;	/* update sibling pointers */	if ((rc = dtRelink(tid, ip, fp))) {		BT_PUTPAGE(fmp);		return rc;	}	xlen = lengthPXD(&fp->header.self);	ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);	/* free/invalidate its buffer page */	discard_metapage(fmp);	/*	 *      propagate page deletion up the directory tree	 *	 * If the delete from the parent page makes it empty,	 * continue all the way up the tree.	 * stop if the root page is reached (which is never deleted) or	 * if the entry deletion does not empty the page.	 */	while ((parent = BT_POP(btstack)) != NULL) {		/* pin the parent page <sp> */		DT_GETPAGE(ip, parent->bn, mp, PSIZE, p, rc);		if (rc)			return rc;		/*		 * free the extent of the child page deleted		 */		index = parent->index;		/*		 * delete the entry for the child page from parent		 */		nextindex = p->header.nextindex;		/*		 * the parent has the single entry being deleted:		 *		 * free the parent page which has become empty.		 */		if (nextindex == 1) {			/*			 * keep the root internal page which has become empty			 */			if (p->header.flag & BT_ROOT) {				/*				 * reset the root				 *				 * dtInitRoot() acquires txlock on the root				 */				dtInitRoot(tid, ip, PARENT(ip));				DT_PUTPAGE(mp);				return 0;			}			/*			 * free the parent page			 */			else {				/*				 * acquire a transaction lock on the page				 *				 * write FREEXTENT|NOREDOPAGE log record				 */				tlck =				    txMaplock(tid, ip,					      tlckDTREE | tlckFREE);				pxdlock = (struct pxd_lock *) & tlck->lock;				pxdlock->flag = mlckFREEPXD;				pxdlock->pxd = p->header.self;				pxdlock->index = 1;				/* update sibling pointers */				if ((rc = dtRelink(tid, ip, p))) {					DT_PUTPAGE(mp);					return rc;				}				xlen = lengthPXD(&p->header.self);				ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);				/* free/invalidate its buffer page */				discard_metapage(mp);				/* propagate up */				continue;			}		}		/*		 * the parent has other entries remaining:		 *		 * delete the router entry from the parent page.		 */		BT_MARK_DIRTY(mp, ip);		/*		 * acquire a transaction lock on the page		 *		 * action: router entry deletion		 */		tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);		dtlck = (struct dt_lock *) & tlck->lock;		/* linelock header */		if (dtlck->index >= dtlck->maxcnt)			dtlck = (struct dt_lock *) txLinelock(dtlck);		lv = & dtlck->lv[dtlck->index];		lv->offset = 0;		lv->length = 1;		dtlck->index++;		/* linelock stbl of non-root leaf page */		if (!(p->header.flag & BT_ROOT)) {			if (dtlck->index < dtlck->maxcnt)				lv++;			else {				dtlck = (struct dt_lock *) txLinelock(dtlck);				lv = & dtlck->lv[0];			}			i = index >> L2DTSLOTSIZE;			lv->offset = p->header.stblindex + i;			lv->length =			    ((p->header.nextindex - 1) >> L2DTSLOTSIZE) -			    i + 1;			dtlck->index++;		}		/* free the router entry */		dtDeleteEntry(p, index, &dtlck);		/* reset key of new leftmost entry of level (for consistency) */		if (index == 0 &&		    ((p->header.flag & BT_ROOT) || p->header.prev == 0))			dtTruncateEntry(p, 0, &dtlck);		/* unpin the parent page */		DT_PUTPAGE(mp);		/* exit propagation up */		break;	}	return 0;}#ifdef _NOTYET/* * NAME:        dtRelocate() * * FUNCTION:    relocate dtpage (internal or leaf) of directory; *              This function is mainly used by defragfs utility. */int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,	       s64 nxaddr){	int rc = 0;	struct metapage *mp, *pmp, *lmp, *rmp;	dtpage_t *p, *pp, *rp = 0, *lp= 0;	s64 bn;	int index;	struct btstack btstack;	pxd_t *pxd;	s64 oxaddr, nextbn, prevbn;	int xlen, xsize;	struct tlock *tlck;	struct dt_lock *dtlck;	struct pxd_lock *pxdlock;	s8 *stbl;	struct lv *lv;	oxaddr = addressPXD(opxd);	xlen = lengthPXD(opxd);	jfs_info("dtRelocate: lmxaddr:%Ld xaddr:%Ld:%Ld xlen:%d",		   (long long)lmxaddr, (long long)oxaddr, (long long)nxaddr,		   xlen);	/*	 *      1. get the internal parent dtpage covering	 *      router entry for the tartget page to be relocated;	 */	rc = dtSearchNode(ip, lmxaddr, opxd, &btstack);	if (rc)		return rc;	/* retrieve search result */	DT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);	jfs_info("dtRelocate: parent router entry validated.");	/*	 *      2. relocate the target dtpage	 */	/* read in the target page from src extent */	DT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc);	if (rc) {		/* release the pinned parent page */		DT_PUTPAGE(pmp);		return rc;	}	/*	 * read in sibling pages if any to update sibling pointers;	 */	rmp = NULL;	if (p->header.next) {		nextbn = le64_to_cpu(p->header.next);		DT_GETPAGE(ip, nextbn, rmp, PSIZE, rp, rc);		if (rc) {			DT_PUTPAGE(mp);			DT_PUTPAGE(pmp);			return (rc);		}	}	lmp = NULL;	if (p->header.prev) {		prevbn = le64_to_cpu(p->header.prev);		DT_GETPAGE(ip, prevbn, lmp, PSIZE, lp, rc);		if (rc) {			DT_PUTPAGE(mp);			DT_PUTPAGE(pmp);			if (rmp)				DT_PUTPAGE(rmp);			return (rc);		}	}	/* at this point, all xtpages to be updated are in memory */	/*	 * update sibling pointers of sibling dtpages if any;	 */	if (lmp) {		tlck = txLock(tid, ip, lmp, tlckDTREE | tlckRELINK);		dtlck = (struct dt_lock *) & tlck->lock;		/* linelock header */		ASSERT(dtlck->index == 0);		lv = & dtlck->lv[0];		lv->offset = 0;		lv->length = 1;		dtlck->index++;		lp->header.next = cpu_to_le64(nxaddr);		DT_PUTPAGE(lmp);	}	if (rmp) {		tlck = txLock(tid, ip, rmp, tlckDTREE | tlckRELINK);		dtlck = (struct dt_lock *) & tlck->lock;		/* linelock header */		ASSERT(dtlck->index == 0);		lv = & dtlck->lv[0];		lv->offset = 0;		lv->length = 1;		dtlck->index++;		rp->header.prev = cpu_to_le64(nxaddr);		DT_PUTPAGE(rmp);	}	/*	 * update the target dtpage to be relocated	 *	 * write LOG_REDOPAGE of LOG_NEW type for dst page	 * for the whole target page (logredo() will apply	 * after image and update bmap for allocation of the	 * dst extent), and update bmap for allocation of	 * the dst extent;	 */	tlck = txLock(tid, ip, mp, tlckDTREE | tlckNEW);	dtlck = (struct dt_lock *) & tlck->lock;	/* linelock header */	ASSERT(dtlck->index == 0);	lv = & dtlck->lv[0];	/* update the self address in the dtpage header */	pxd = &p->header.self;	PXDaddress(pxd, nxaddr);	/* the dst page is the same as the src page, i.e.,	 * linelock for afterimage of the whole page;	 */	lv->offset = 0;	lv->length = p->header.maxslot;	dtlck->index++;	/* update the buffer extent descriptor of the dtpage */	xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize;#ifdef _STILL_TO_PORT	bmSetXD(mp, nxaddr, xsize);#endif /* _STILL_TO_PORT */	/* unpin the relocated page */	DT_PUTPAGE(mp);	jfs_info("dtRelocate: target dtpage relocated.");	/* the moved extent is dtpage, then a LOG_NOREDOPAGE log rec	 * needs to be written (in logredo(), the LOG_NOREDOPAGE log rec	 * will also force a bmap update ).	 */	/*	 *      3. acquire maplock for the source extent to be freed;	 */	/* for dtpage relocation, write a LOG_NOREDOPAGE record	 * for the source dtpage (logredo() will init NoRedoPage	 * filter and will also update bmap for free of the source	 * dtpage), and upadte bmap for free of the source dtpage;	 */	tlck = txMaplock(tid, ip, tlckDTREE | tlckFREE);	pxdlock = (struct pxd_lock *) & tlck->lock;	pxdlock->flag = mlckFREEPXD;	PXDaddress(&pxdlock->pxd, oxaddr);	PXDlength(&pxdlock->pxd, xlen);	pxdlock->index = 1;	/*	 *      4. update the parent router entry for relocation;	 *	 * acquire tlck for the parent entry covering the target dtpage;	 * write LOG_REDOPAGE to apply after image only;	 */	jfs_info("dtRelocate: update parent router entry.");	tlck = txLock(tid, ip, pmp, tlckDTREE | tlckENTRY);	dtlck = (struct dt_lock *) & tlck->lock;	lv = & dtlck->lv[dtlck->index];	/* update the PXD with the new address */	stbl = DT_GETSTBL(pp);	pxd = (pxd_t *) & pp->slot[stbl[index]];	PXDaddress(pxd, nxaddr);	lv->offset = stbl[index];	lv->length = 1;	dtlck->index++;	/* unpin the parent dtpage */	DT_PUTPAGE(pmp);	return rc;}/* * NAME:	dtSearchNode() * * FUNCTION:	Search for an dtpage containing a specified address *              This function is mainly used by defragfs utility. * * NOTE:	Search result on stack, the found page is pinned at exit. *		The result page must be an internal dtpage. *		lmxaddr give the address of the left most page of the *		dtree level, in which the required dtpage resides. */static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd,			struct btstack * btstack){	int rc = 0;	s64 bn;	struct metapage *mp;	dtpage_t *p;	int psize = 288;	/* initial in-line directory */	s8 *stbl;	int i;	pxd_t *pxd;	struct btframe *btsp;	BT_CLR(btstack);	/* reset stack */	/*	 *      descend tree to the level with specified leftmost page	 *	 *  by convention, root bn = 0.	 */	for (bn = 0;;) {		/* get/pin the page to search */		DT_GETPAGE(ip, bn, mp, psize, p, rc);		if (rc)			return rc;		/* does the xaddr of leftmost page of the levevl		 * matches levevl search key ?		 */		if (p->header.flag & BT_ROOT) {			if (lmxaddr == 0)				break;		} else if (addressPXD(&p->header.self) == lmxaddr)			break;		/*		 * descend down to leftmost child page		 */		if (p->header.flag & BT_LEAF) {			DT_PUTPAGE(mp);			return -ESTALE;		}		/* get the leftmost entry */		stbl = DT_GETSTBL(p);		pxd = (pxd_t *) & p->slot[stbl[0]];		/* get the child page block address */		bn = addressPXD(pxd);		psize = lengthPXD(pxd) << JFS_SBI(ip->i_sb)->l2bsize;		/* unpin the parent page */		DT_PUTPAGE(mp);	}	/*	 *      search each page at the current levevl	 */      loop:	stbl = DT_GETSTBL(p);	for (i = 0; i < p->header.nextindex; i++) {		pxd = (pxd_t *) & p->slot[stbl[i]];		/* found the specified router entry */		if (addressPXD(pxd) == addressPXD(kpxd) &&		    lengthPXD(pxd) == lengthPXD(kpxd)) {			btsp = btstack->top;			btsp->bn = bn;			btsp->index = i;			btsp->mp = mp;			return 0;		}	}	/* get the right sibling page if any */	if (p->header.next)		bn = le64_to_cpu(p->header.next);	else {		DT_PUTPAGE(mp);		return -ESTALE;	}	/* unpin current page */	DT_PUTPAGE(mp);	/* get the right sibling page */	DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);	if (rc)		return rc;	goto loop;}#endif /* _NOTYET *//* *	dtRelink() * * function: *	link around a freed page. * * parameter: *	fp:	page to be freed * * return: */static int dtRelink(tid_t tid, struct inode *ip, dtpage_t * p){	int rc;	struct metapage *mp;	s64 nextbn, prevbn;	struct tlock *tlck;	struct dt_lock *dtlck;	struct lv *lv;	nextbn = le64_to_cpu(p->header.next);	prevbn = le64_to_cpu(p->header.prev);	/* update prev pointer of the next page */	if (nextbn != 0) {		DT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);		if (rc)			return rc;		BT_MARK_DIRTY(mp, ip);		/*		 * acquire a transaction lock on the next page		 *		 * action: update prev pointer;		 */		tlck = txLock(tid, ip, mp, tlckDTREE | tlckRELINK);		jfs_info("dtRelink nextbn: tlck = 0x%p, ip = 0x%p, mp=0x%p",			tlck, ip, mp);		dtlck = (struct dt_lock *) & tlck->lock;		/* linelock header */		if (dtlck->index >= dtlck->maxcnt)			dtlck = (struct dt_lock *) txLinelock(dtlck);		lv = & dtlck->lv[dtlck->index];		lv->offset = 0;		lv->length = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -