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

📄 jfs_xtree.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			/* init for parent page split */			split->mp = smp;			split->index = skip;	/* index at insert */			split->flag = XAD_NEW;			split->off = offsetXAD(&rcp->xad[XTENTRYSTART]);			split->len = JFS_SBI(ip->i_sb)->nbperpage;			split->addr = rcbn;			/* unpin previous right child page */			XT_PUTPAGE(rcmp);			/* The split routines insert the new entry,			 * and acquire txLock as appropriate.			 * return <rp> pinned and its block number <rpbn>.			 */			rc = (sp->header.flag & BT_ROOT) ?			    xtSplitRoot(tid, ip, split, &rmp) :			    xtSplitPage(tid, ip, split, &rmp, &rbn);			if (rc) {				XT_PUTPAGE(smp);				return rc;			}			XT_PUTPAGE(smp);			/* keep new child page <rp> pinned */		}		/*		 * parent page is not full - insert in parent page		 */		else {			/*			 * insert router entry in parent for the right child			 * page from the first entry of the right child page:			 */			/*			 * acquire a transaction lock on the parent page;			 *			 * action: router xad insertion;			 */			BT_MARK_DIRTY(smp, ip);			/*			 * if insert into middle, shift right remaining entries			 */			if (skip < nextindex)				memmove(&sp->xad[skip + 1], &sp->xad[skip],					(nextindex -					 skip) << L2XTSLOTSIZE);			/* insert the router entry */			xad = &sp->xad[skip];			XT_PUTENTRY(xad, XAD_NEW,				    offsetXAD(&rcp->xad[XTENTRYSTART]),				    JFS_SBI(ip->i_sb)->nbperpage, rcbn);			/* advance next available entry index. */			sp->header.nextindex =			    cpu_to_le16(le16_to_cpu(sp->header.nextindex) +					1);			/* Don't log it if there are no links to the file */			if (!test_cflag(COMMIT_Nolink, ip)) {				tlck = txLock(tid, ip, smp,					      tlckXTREE | tlckGROW);				xtlck = (struct xtlock *) & tlck->lock;				xtlck->lwm.offset = (xtlck->lwm.offset) ?				    min(skip, (int)xtlck->lwm.offset) : skip;				xtlck->lwm.length =				    le16_to_cpu(sp->header.nextindex) -				    xtlck->lwm.offset;			}			/* unpin parent page */			XT_PUTPAGE(smp);			/* exit propagate up */			break;		}	}	/* unpin current right page */	XT_PUTPAGE(rmp);	return 0;}/* *      xtSplitPage() * * function: *      split a full non-root page into *      original/split/left page and new right page *      i.e., the original/split page remains as left page. * * parameter: *      int		tid, *      struct inode    *ip, *      struct xtsplit  *split, *      struct metapage	**rmpp, *      u64		*rbnp, * * return: *      Pointer to page in which to insert or NULL on error. */static intxtSplitPage(tid_t tid, struct inode *ip,	    struct xtsplit * split, struct metapage ** rmpp, s64 * rbnp){	int rc = 0;	struct metapage *smp;	xtpage_t *sp;	struct metapage *rmp;	xtpage_t *rp;		/* new right page allocated */	s64 rbn;		/* new right page block number */	struct metapage *mp;	xtpage_t *p;	s64 nextbn;	int skip, maxentry, middle, righthalf, n;	xad_t *xad;	struct pxdlist *pxdlist;	pxd_t *pxd;	struct tlock *tlck;	struct xtlock *sxtlck = 0, *rxtlck = 0;	smp = split->mp;	sp = XT_PAGE(ip, smp);	INCREMENT(xtStat.split);	/*	 * allocate the new right page for the split	 */	pxdlist = split->pxdlist;	pxd = &pxdlist->pxd[pxdlist->npxd];	pxdlist->npxd++;	rbn = addressPXD(pxd);	rmp = get_metapage(ip, rbn, PSIZE, 1);	if (rmp == NULL)		return -EIO;	jfs_info("xtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);	BT_MARK_DIRTY(rmp, ip);	/*	 * action: new page;	 */	rp = (xtpage_t *) rmp->data;	rp->header.self = *pxd;	rp->header.flag = sp->header.flag & BT_TYPE;	rp->header.maxentry = sp->header.maxentry;	/* little-endian */	rp->header.nextindex = cpu_to_le16(XTENTRYSTART);	BT_MARK_DIRTY(smp, ip);	/* Don't log it if there are no links to the file */	if (!test_cflag(COMMIT_Nolink, ip)) {		/*		 * acquire a transaction lock on the new right page;		 */		tlck = txLock(tid, ip, rmp, tlckXTREE | tlckNEW);		rxtlck = (struct xtlock *) & tlck->lock;		rxtlck->lwm.offset = XTENTRYSTART;		/*		 * acquire a transaction lock on the split page		 */		tlck = txLock(tid, ip, smp, tlckXTREE | tlckGROW);		sxtlck = (struct xtlock *) & tlck->lock;	}	/*	 * initialize/update sibling pointers of <sp> and <rp>	 */	nextbn = le64_to_cpu(sp->header.next);	rp->header.next = cpu_to_le64(nextbn);	rp->header.prev = cpu_to_le64(addressPXD(&sp->header.self));	sp->header.next = cpu_to_le64(rbn);	skip = split->index;	/*	 *      sequential append at tail (after last entry of last page)	 *	 * if splitting the last page on a level because of appending	 * a entry to it (skip is maxentry), it's likely that the access is	 * sequential. adding an empty page on the side of the level is less	 * work and can push the fill factor much higher than normal.	 * if we're wrong it's no big deal -  we will do the split the right	 * way next time.	 * (it may look like it's equally easy to do a similar hack for	 * reverse sorted data, that is, split the tree left, but it's not.	 * Be my guest.)	 */	if (nextbn == 0 && skip == le16_to_cpu(sp->header.maxentry)) {		/*		 * acquire a transaction lock on the new/right page;		 *		 * action: xad insertion;		 */		/* insert entry at the first entry of the new right page */		xad = &rp->xad[XTENTRYSTART];		XT_PUTENTRY(xad, split->flag, split->off, split->len,			    split->addr);		rp->header.nextindex = cpu_to_le16(XTENTRYSTART + 1);		if (!test_cflag(COMMIT_Nolink, ip)) {			/* rxtlck->lwm.offset = XTENTRYSTART; */			rxtlck->lwm.length = 1;		}		*rmpp = rmp;		*rbnp = rbn;		ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));		jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp);		return 0;	}	/*	 *      non-sequential insert (at possibly middle page)	 */	/*	 * update previous pointer of old next/right page of <sp>	 */	if (nextbn != 0) {		XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);		if (rc) {			XT_PUTPAGE(rmp);			return rc;		}		BT_MARK_DIRTY(mp, ip);		/*		 * acquire a transaction lock on the next page;		 *		 * action:sibling pointer update;		 */		if (!test_cflag(COMMIT_Nolink, ip))			tlck = txLock(tid, ip, mp, tlckXTREE | tlckRELINK);		p->header.prev = cpu_to_le64(rbn);		/* sibling page may have been updated previously, or		 * it may be updated later;		 */		XT_PUTPAGE(mp);	}	/*	 * split the data between the split and new/right pages	 */	maxentry = le16_to_cpu(sp->header.maxentry);	middle = maxentry >> 1;	righthalf = maxentry - middle;	/*	 * skip index in old split/left page - insert into left page:	 */	if (skip <= middle) {		/* move right half of split page to the new right page */		memmove(&rp->xad[XTENTRYSTART], &sp->xad[middle],			righthalf << L2XTSLOTSIZE);		/* shift right tail of left half to make room for new entry */		if (skip < middle)			memmove(&sp->xad[skip + 1], &sp->xad[skip],				(middle - skip) << L2XTSLOTSIZE);		/* insert new entry */		xad = &sp->xad[skip];		XT_PUTENTRY(xad, split->flag, split->off, split->len,			    split->addr);		/* update page header */		sp->header.nextindex = cpu_to_le16(middle + 1);		if (!test_cflag(COMMIT_Nolink, ip)) {			sxtlck->lwm.offset = (sxtlck->lwm.offset) ?			    min(skip, (int)sxtlck->lwm.offset) : skip;		}		rp->header.nextindex =		    cpu_to_le16(XTENTRYSTART + righthalf);	}	/*	 * skip index in new right page - insert into right page:	 */	else {		/* move left head of right half to right page */		n = skip - middle;		memmove(&rp->xad[XTENTRYSTART], &sp->xad[middle],			n << L2XTSLOTSIZE);		/* insert new entry */		n += XTENTRYSTART;		xad = &rp->xad[n];		XT_PUTENTRY(xad, split->flag, split->off, split->len,			    split->addr);		/* move right tail of right half to right page */		if (skip < maxentry)			memmove(&rp->xad[n + 1], &sp->xad[skip],				(maxentry - skip) << L2XTSLOTSIZE);		/* update page header */		sp->header.nextindex = cpu_to_le16(middle);		if (!test_cflag(COMMIT_Nolink, ip)) {			sxtlck->lwm.offset = (sxtlck->lwm.offset) ?			    min(middle, (int)sxtlck->lwm.offset) : middle;		}		rp->header.nextindex = cpu_to_le16(XTENTRYSTART +						   righthalf + 1);	}	if (!test_cflag(COMMIT_Nolink, ip)) {		sxtlck->lwm.length = le16_to_cpu(sp->header.nextindex) -		    sxtlck->lwm.offset;		/* rxtlck->lwm.offset = XTENTRYSTART; */		rxtlck->lwm.length = le16_to_cpu(rp->header.nextindex) -		    XTENTRYSTART;	}	*rmpp = rmp;	*rbnp = rbn;	ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));	jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp);	return rc;}/* *      xtSplitRoot() * * function: *      split the full root page into *      original/root/split page and new right page *      i.e., root remains fixed in tree anchor (inode) and *      the root is copied to a single new right child page *      since root page << non-root page, and *      the split root page contains a single entry for the *      new right child page. * * parameter: *      int		tid, *      struct inode    *ip, *      struct xtsplit  *split, *      struct metapage	**rmpp) * * return: *      Pointer to page in which to insert or NULL on error. */static intxtSplitRoot(tid_t tid,	    struct inode *ip, struct xtsplit * split, struct metapage ** rmpp){	xtpage_t *sp;	struct metapage *rmp;	xtpage_t *rp;	s64 rbn;	int skip, nextindex;	xad_t *xad;	pxd_t *pxd;	struct pxdlist *pxdlist;	struct tlock *tlck;	struct xtlock *xtlck;	sp = &JFS_IP(ip)->i_xtroot;	INCREMENT(xtStat.split);	/*	 *      allocate a single (right) child page	 */	pxdlist = split->pxdlist;	pxd = &pxdlist->pxd[pxdlist->npxd];	pxdlist->npxd++;	rbn = addressPXD(pxd);	rmp = get_metapage(ip, rbn, PSIZE, 1);	if (rmp == NULL)		return -EIO;	jfs_info("xtSplitRoot: ip:0x%p rmp:0x%p", ip, rmp);	/*	 * acquire a transaction lock on the new right page;	 *	 * action: new page;	 */	BT_MARK_DIRTY(rmp, ip);	rp = (xtpage_t *) rmp->data;	rp->header.flag =	    (sp->header.flag & BT_LEAF) ? BT_LEAF : BT_INTERNAL;	rp->header.self = *pxd;	rp->header.nextindex = cpu_to_le16(XTENTRYSTART);	rp->header.maxentry = cpu_to_le16(PSIZE >> L2XTSLOTSIZE);	/* initialize sibling pointers */	rp->header.next = 0;	rp->header.prev = 0;	/*	 * copy the in-line root page into new right page extent	 */	nextindex = le16_to_cpu(sp->header.maxentry);	memmove(&rp->xad[XTENTRYSTART], &sp->xad[XTENTRYSTART],		(nextindex - XTENTRYSTART) << L2XTSLOTSIZE);	/*	 * insert the new entry into the new right/child page	 * (skip index in the new right page will not change)	 */	skip = split->index;	/* if insert into middle, shift right remaining entries */	if (skip != nextindex)		memmove(&rp->xad[skip + 1], &rp->xad[skip],			(nextindex - skip) * sizeof(xad_t));	xad = &rp->xad[skip];	XT_PUTENTRY(xad, split->flag, split->off, split->len, split->addr);	/* update page header */	rp->header.nextindex = cpu_to_le16(nextindex + 1);	if (!test_cflag(COMMIT_Nolink, ip)) {		tlck = txLock(tid, ip, rmp, tlckXTREE | tlckNEW);		xtlck = (struct xtlock *) & tlck->lock;		xtlck->lwm.offset = XTENTRYSTART;		xtlck->lwm.length = le16_to_cpu(rp->header.nextindex) -		    XTENTRYSTART;	}	/*	 *      reset the root	 *	 * init root with the single entry for the new right page	 * set the 1st entry offset to 0, which force the left-most key	 * at any level of the tree to be less than any search key.	 */	/*	 * acquire a transaction lock on the root page (in-memory inode);	 *	 * action: root split;	 */	BT_MARK_DIRTY(split->mp, ip);	xad = &sp->xad[XTENTRYSTART];	XT_PUTENTRY(xad, XAD_NEW, 0, JFS_SBI(ip->i_sb)->nbperpage, rbn);	/* update page header of root */	sp->header.flag &= ~BT_LEAF;	sp->header.flag |= BT_INTERNAL;	sp->header.nextindex = cpu_to_le16(XTENTRYSTART + 1);	if (!test_cflag(COMMIT_Nolink, ip)) {		tlck = txLock(tid, ip, split->mp, tlckXTREE | tlckGROW);		xtlck = (struct xtlock *) & tlck->lock;		xtlck->lwm.offset = XTENTRYSTART;		xtlck->lwm.length = 1;	}	*rmpp = rmp;	ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));	jfs_info("xtSplitRoot: sp:0x%p rp:0x%p", sp, rp);	return 0;}/* *      xtExtend() * * function: extend in-place; * * note: existing extent may or may not have been committed. * caller is responsible for pager buffer cache update, and * working block allocation map update; * update pmap: alloc whole extended extent; */int xtExtend(tid_t tid,		/* transaction id */	     struct inode *ip, s64 xoff,	/* delta extent offset */	     s32 xlen,		/* delta extent length */	     int flag){	int rc = 0;	int cmp;	struct metapage *mp;	/* meta-page buffer */	xtpage_t *p;		/* base B+-tree index page */	s64 bn;	int index, nextindex, len;	struct btstack btstack;	/* traverse stack */	struct xtsplit split;	/* split information */	xad_t *xad;	s64 xaddr;	struct tlock *tlck;	struct xtlock *xtlck = 0;	int rootsplit = 0;	jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);	/* there must exist extent to be extended */	if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT)))		return rc;	/* retrieve search result */	XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);	if (cmp != 0) {		XT_PUTPAGE(mp);		jfs_error(ip->i_sb, "xtExtend: xtSearch did not find extent");		return -EIO;	}	/* extension must be contiguous */	xad = &p->xad[index];	if ((offsetXAD(xad) + lengthXAD(xad)) != xoff) {		XT_PUTPAGE(mp);		jfs_error(ip->i_sb, "xtExtend: extension is not contiguous");		return -EIO;	}	/*	 * acquire a transaction lock on the leaf page;	 *	 * action: xad insertion/extension;	 */	BT_MARK_DIRTY(mp, ip);	if (!test_cflag(COMMIT_Nolink, ip)) {		tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);		xtlck = (struct xtlock *) & tlck->lock;	}	/* extend will overflow extent ? */	xlen = lengthXAD(xad) + xlen;	if ((len = xlen - MAXXLEN) <= 0)		goto extendOld;

⌨️ 快捷键说明

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