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

📄 jfs_dtree.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	xaddr = addressPXD(pxd);	tpxd = &sp->header.self;	txaddr = addressPXD(tpxd);	/* in-place extension */	if (xaddr == txaddr) {		type = tlckEXTEND;	}	/* relocation */	else {		type = tlckNEW;		/* save moved extent descriptor for later free */		tlck = txMaplock(tid, ip, tlckDTREE | tlckRELOCATE);		pxdlock = (struct pxd_lock *) & tlck->lock;		pxdlock->flag = mlckFREEPXD;		pxdlock->pxd = sp->header.self;		pxdlock->index = 1;		/*		 * Update directory index table to reflect new page address		 */		if (DO_INDEX(ip)) {			s64 lblock;			mp = 0;			stbl = DT_GETSTBL(sp);			for (n = 0; n < sp->header.nextindex; n++) {				ldtentry =				    (struct ldtentry *) & sp->slot[stbl[n]];				modify_index(tid, ip,					     le32_to_cpu(ldtentry->index),					     xaddr, n, &mp, &lblock);			}			if (mp)				release_metapage(mp);		}	}	/*	 *      extend the page	 */	sp->header.self = *pxd;	jfs_info("dtExtendPage: ip:0x%p smp:0x%p sp:0x%p", ip, smp, sp);	BT_MARK_DIRTY(smp, ip);	/*	 * acquire a transaction lock on the extended/leaf page	 */	tlck = txLock(tid, ip, smp, tlckDTREE | type);	dtlck = (struct dt_lock *) & tlck->lock;	lv = & dtlck->lv[0];	/* update buffer extent descriptor of extended page */	xlen = lengthPXD(pxd);	xsize = xlen << JFS_SBI(sb)->l2bsize;#ifdef _STILL_TO_PORT	bmSetXD(smp, xaddr, xsize);#endif				/*  _STILL_TO_PORT */	/*	 * copy old stbl to new stbl at start of extended area	 */	oldstblindex = sp->header.stblindex;	oldstblsize = (sp->header.maxslot + 31) >> L2DTSLOTSIZE;	newstblindex = sp->header.maxslot;	n = xsize >> L2DTSLOTSIZE;	newstblsize = (n + 31) >> L2DTSLOTSIZE;	memcpy(&sp->slot[newstblindex], &sp->slot[oldstblindex],	       sp->header.nextindex);	/*	 * in-line extension: linelock old area of extended page	 */	if (type == tlckEXTEND) {		/* linelock header */		lv->offset = 0;		lv->length = 1;		dtlck->index++;		lv++;		/* linelock new stbl of extended page */		lv->offset = newstblindex;		lv->length = newstblsize;	}	/*	 * relocation: linelock whole relocated area	 */	else {		lv->offset = 0;		lv->length = sp->header.maxslot + newstblsize;	}	dtlck->index++;	sp->header.maxslot = n;	sp->header.stblindex = newstblindex;	/* sp->header.nextindex remains the same */	/*	 * add old stbl region at head of freelist	 */	fsi = oldstblindex;	f = &sp->slot[fsi];	last = sp->header.freelist;	for (n = 0; n < oldstblsize; n++, fsi++, f++) {		f->next = last;		last = fsi;	}	sp->header.freelist = last;	sp->header.freecnt += oldstblsize;	/*	 * append free region of newly extended area at tail of freelist	 */	/* init free region of newly extended area */	fsi = n = newstblindex + newstblsize;	f = &sp->slot[fsi];	for (fsi++; fsi < sp->header.maxslot; f++, fsi++)		f->next = fsi;	f->next = -1;	/* append new free region at tail of old freelist */	fsi = sp->header.freelist;	if (fsi == -1)		sp->header.freelist = n;	else {		do {			f = &sp->slot[fsi];			fsi = f->next;		} while (fsi != -1);		f->next = n;	}	sp->header.freecnt += sp->header.maxslot - n;	/*	 * insert the new entry	 */	dtInsertEntry(sp, split->index, split->key, split->data, &dtlck);	BT_MARK_DIRTY(pmp, ip);	/*	 * linelock any freeslots residing in old extent	 */	if (type == tlckEXTEND) {		n = sp->header.maxslot >> 2;		if (sp->header.freelist < n)			dtLinelockFreelist(sp, n, &dtlck);	}	/*	 *      update parent entry on the parent/root page	 */	/*	 * acquire a transaction lock on the parent/root page	 */	tlck = txLock(tid, ip, pmp, tlckDTREE | tlckENTRY);	dtlck = (struct dt_lock *) & tlck->lock;	lv = & dtlck->lv[dtlck->index];	/* linelock parent entry - 1st slot */	lv->offset = 1;	lv->length = 1;	dtlck->index++;	/* update the parent pxd for page extension */	tpxd = (pxd_t *) & pp->slot[1];	*tpxd = *pxd;	/* Since the directory might have an EA and/or ACL associated with it	 * we need to make sure we take that into account when setting the	 * i_nblocks	 */	ip->i_blocks = LBLK2PBLK(ip->i_sb, xlen +				 ((JFS_IP(ip)->ea.flag & DXD_EXTENT) ?				  lengthDXD(&JFS_IP(ip)->ea) : 0) +				 ((JFS_IP(ip)->acl.flag & DXD_EXTENT) ?				  lengthDXD(&JFS_IP(ip)->acl) : 0));	DT_PUTPAGE(pmp);	return 0;}/* *	dtSplitRoot() * * 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: * * return: 0 - success; *	   errno - failure; *	return new page pinned; */static int dtSplitRoot(tid_t tid,	    struct inode *ip, struct dtsplit * split, struct metapage ** rmpp){	struct super_block *sb = ip->i_sb;	struct metapage *smp;	dtroot_t *sp;	struct metapage *rmp;	dtpage_t *rp;	s64 rbn;	int xlen;	int xsize;	struct dtslot *f;	s8 *stbl;	int fsi, stblsize, n;	struct idtentry *s;	pxd_t *ppxd;	struct pxdlist *pxdlist;	pxd_t *pxd;	struct dt_lock *dtlck;	struct tlock *tlck;	struct lv *lv;	/* get split root page */	smp = split->mp;	sp = &JFS_IP(ip)->i_dtroot;	/*	 *      allocate/initialize a single (right) child page	 *	 * N.B. at first split, a one (or two) block to fit new entry	 * is allocated; at subsequent split, a full page is allocated;	 */	pxdlist = split->pxdlist;	pxd = &pxdlist->pxd[pxdlist->npxd];	pxdlist->npxd++;	rbn = addressPXD(pxd);	xlen = lengthPXD(pxd);	xsize = xlen << JFS_SBI(sb)->l2bsize;	rmp = get_metapage(ip, rbn, xsize, 1);	if (!rmp)		return -EIO;	rp = rmp->data;	BT_MARK_DIRTY(rmp, ip);	/*	 * acquire a transaction lock on the new right page	 */	tlck = txLock(tid, ip, rmp, tlckDTREE | tlckNEW);	dtlck = (struct dt_lock *) & tlck->lock;	rp->header.flag =	    (sp->header.flag & BT_LEAF) ? BT_LEAF : BT_INTERNAL;	rp->header.self = *pxd;	/* initialize sibling pointers */	rp->header.next = 0;	rp->header.prev = 0;	/*	 *      move in-line root page into new right page extent	 */	/* linelock header + copied entries + new stbl (1st slot) in new page */	ASSERT(dtlck->index == 0);	lv = & dtlck->lv[0];	lv->offset = 0;	lv->length = 10;	/* 1 + 8 + 1 */	dtlck->index++;	n = xsize >> L2DTSLOTSIZE;	rp->header.maxslot = n;	stblsize = (n + 31) >> L2DTSLOTSIZE;	/* copy old stbl to new stbl at start of extended area */	rp->header.stblindex = DTROOTMAXSLOT;	stbl = (s8 *) & rp->slot[DTROOTMAXSLOT];	memcpy(stbl, sp->header.stbl, sp->header.nextindex);	rp->header.nextindex = sp->header.nextindex;	/* copy old data area to start of new data area */	memcpy(&rp->slot[1], &sp->slot[1], IDATASIZE);	/*	 * append free region of newly extended area at tail of freelist	 */	/* init free region of newly extended area */	fsi = n = DTROOTMAXSLOT + stblsize;	f = &rp->slot[fsi];	for (fsi++; fsi < rp->header.maxslot; f++, fsi++)		f->next = fsi;	f->next = -1;	/* append new free region at tail of old freelist */	fsi = sp->header.freelist;	if (fsi == -1)		rp->header.freelist = n;	else {		rp->header.freelist = fsi;		do {			f = &rp->slot[fsi];			fsi = f->next;		} while (fsi != -1);		f->next = n;	}	rp->header.freecnt = sp->header.freecnt + rp->header.maxslot - n;	/*	 * Update directory index table for entries now in right page	 */	if ((rp->header.flag & BT_LEAF) && DO_INDEX(ip)) {		s64 lblock;		struct metapage *mp = 0;		struct ldtentry *ldtentry;		stbl = DT_GETSTBL(rp);		for (n = 0; n < rp->header.nextindex; n++) {			ldtentry = (struct ldtentry *) & rp->slot[stbl[n]];			modify_index(tid, ip, le32_to_cpu(ldtentry->index),				     rbn, n, &mp, &lblock);		}		if (mp)			release_metapage(mp);	}	/*	 * insert the new entry into the new right/child page	 * (skip index in the new right page will not change)	 */	dtInsertEntry(rp, split->index, split->key, split->data, &dtlck);	/*	 *      reset parent/root 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.	 *	 * The btree comparison code guarantees that the left-most key on any	 * level of the tree is never used, so it doesn't need to be filled in.	 */	BT_MARK_DIRTY(smp, ip);	/*	 * acquire a transaction lock on the root page (in-memory inode)	 */	tlck = txLock(tid, ip, smp, tlckDTREE | tlckNEW | tlckBTROOT);	dtlck = (struct dt_lock *) & tlck->lock;	/* linelock root */	ASSERT(dtlck->index == 0);	lv = & dtlck->lv[0];	lv->offset = 0;	lv->length = DTROOTMAXSLOT;	dtlck->index++;	/* update page header of root */	if (sp->header.flag & BT_LEAF) {		sp->header.flag &= ~BT_LEAF;		sp->header.flag |= BT_INTERNAL;	}	/* init the first entry */	s = (struct idtentry *) & sp->slot[DTENTRYSTART];	ppxd = (pxd_t *) s;	*ppxd = *pxd;	s->next = -1;	s->namlen = 0;	stbl = sp->header.stbl;	stbl[0] = DTENTRYSTART;	sp->header.nextindex = 1;	/* init freelist */	fsi = DTENTRYSTART + 1;	f = &sp->slot[fsi];	/* init free region of remaining area */	for (fsi++; fsi < DTROOTMAXSLOT; f++, fsi++)		f->next = fsi;	f->next = -1;	sp->header.freelist = DTENTRYSTART + 1;	sp->header.freecnt = DTROOTMAXSLOT - (DTENTRYSTART + 1);	*rmpp = rmp;	ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));	return 0;}/* *	dtDelete() * * function: delete the entry(s) referenced by a key. * * parameter: * * return: */int dtDelete(tid_t tid,	 struct inode *ip, struct component_name * key, ino_t * ino, int flag){	int rc = 0;	s64 bn;	struct metapage *mp, *imp;	dtpage_t *p;	int index;	struct btstack btstack;	struct dt_lock *dtlck;	struct tlock *tlck;	struct lv *lv;	int i;	struct ldtentry *ldtentry;	u8 *stbl;	u32 table_index, next_index;	struct metapage *nmp;	dtpage_t *np;	/*	 *      search for the entry to delete:	 *	 * dtSearch() returns (leaf page pinned, index at which to delete).	 */	if ((rc = dtSearch(ip, key, ino, &btstack, flag)))		return rc;	/* retrieve search result */	DT_GETSEARCH(ip, btstack.top, bn, mp, p, index);	/*	 * We need to find put the index of the next entry into the	 * directory index table in order to resume a readdir from this	 * entry.	 */	if (DO_INDEX(ip)) {		stbl = DT_GETSTBL(p);		ldtentry = (struct ldtentry *) & p->slot[stbl[index]];		table_index = le32_to_cpu(ldtentry->index);		if (index == (p->header.nextindex - 1)) {			/*			 * Last entry in this leaf page			 */			if ((p->header.flag & BT_ROOT)			    || (p->header.next == 0))				next_index = -1;			else {				/* Read next leaf page */				DT_GETPAGE(ip, le64_to_cpu(p->header.next),					   nmp, PSIZE, np, rc);				if (rc)					next_index = -1;				else {					stbl = DT_GETSTBL(np);					ldtentry =					    (struct ldtentry *) & np->					    slot[stbl[0]];					next_index =					    le32_to_cpu(ldtentry->index);					DT_PUTPAGE(nmp);				}			}		} else {			ldtentry =			    (struct ldtentry *) & p->slot[stbl[index + 1]];			next_index = le32_to_cpu(ldtentry->index);		}		free_index(tid, ip, table_index, next_index);	}	/*	 * the leaf page becomes empty, delete the page	 */	if (p->header.nextindex == 1) {		/* delete empty page */		rc = dtDeleteUp(tid, ip, mp, p, &btstack);	}	/*	 * the leaf page has other entries remaining:	 *	 * delete the entry from the leaf page.	 */	else {		BT_MARK_DIRTY(mp, ip);		/*		 * acquire a transaction lock on the leaf page		 */		tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);		dtlck = (struct dt_lock *) & tlck->lock;		/*		 * Do not assume that dtlck->index will be zero.  During a		 * rename within a directory, this transaction may have		 * modified this page already when adding the new entry.		 */		/* 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)				dtlck = (struct dt_lock *) txLinelock(dtlck);			lv = & dtlck->lv[dtlck->index];			i = index >> L2DTSLOTSIZE;			lv->offset = p->header.stblindex + i;			lv->length =			    ((p->header.nextindex - 1) >> L2DTSLOTSIZE) -			    i + 1;			dtlck->index++;		}		/* free the leaf entry */		dtDeleteEntry(p, index, &dtlck);		/*		 * Update directory index table for entries moved in stbl		 */		if (DO_INDEX(ip) && index < p->header.nextindex) {			s64 lblock;			imp = 0;			stbl = DT_GETSTBL(p);			for (i = index; i < p->header.nextindex; i++) {				ldtentry =				    (struct ldtentry *) & p->slot[stbl[i]];				modify_index(tid, ip,					     le32_to_cpu(ldtentry->index),					     bn, i, &imp, &lblock);			}			if (imp)				release_metapage(imp);		}		DT_PUTPAGE(mp);	}	return rc;}/*

⌨️ 快捷键说明

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