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

📄 xfs_dir2_leaf.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		    dep->name[0] == args->name[0] &&		    memcmp(dep->name, args->name, args->namelen) == 0) {			*dbpp = dbp;			*indexp = index;			return 0;		}	}	/*	 * No match found, return ENOENT.	 */	ASSERT(args->oknoent);	if (dbp)		xfs_da_brelse(tp, dbp);	xfs_da_brelse(tp, lbp);	return XFS_ERROR(ENOENT);}/* * Remove an entry from a leaf format directory. */int						/* error */xfs_dir2_leaf_removename(	xfs_da_args_t		*args)		/* operation arguments */{	__be16			*bestsp;	/* leaf block best freespace */	xfs_dir2_data_t		*data;		/* data block structure */	xfs_dir2_db_t		db;		/* data block number */	xfs_dabuf_t		*dbp;		/* data block buffer */	xfs_dir2_data_entry_t	*dep;		/* data entry structure */	xfs_inode_t		*dp;		/* incore directory inode */	int			error;		/* error return code */	xfs_dir2_db_t		i;		/* temporary data block # */	int			index;		/* index into leaf entries */	xfs_dabuf_t		*lbp;		/* leaf buffer */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */	xfs_mount_t		*mp;		/* filesystem mount point */	int			needlog;	/* need to log data header */	int			needscan;	/* need to rescan data frees */	xfs_dir2_data_off_t	oldbest;	/* old value of best free */	xfs_trans_t		*tp;		/* transaction pointer */	xfs_dir2_trace_args("leaf_removename", args);	/*	 * Lookup the leaf entry, get the leaf and data blocks read in.	 */	if ((error = xfs_dir2_leaf_lookup_int(args, &lbp, &index, &dbp))) {		return error;	}	dp = args->dp;	tp = args->trans;	mp = dp->i_mount;	leaf = lbp->data;	data = dbp->data;	xfs_dir2_data_check(dp, dbp);	/*	 * Point to the leaf entry, use that to point to the data entry.	 */	lep = &leaf->ents[index];	db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));	dep = (xfs_dir2_data_entry_t *)	      ((char *)data + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));	needscan = needlog = 0;	oldbest = be16_to_cpu(data->hdr.bestfree[0].length);	ltp = xfs_dir2_leaf_tail_p(mp, leaf);	bestsp = xfs_dir2_leaf_bests_p(ltp);	ASSERT(be16_to_cpu(bestsp[db]) == oldbest);	/*	 * Mark the former data entry unused.	 */	xfs_dir2_data_make_free(tp, dbp,		(xfs_dir2_data_aoff_t)((char *)dep - (char *)data),		xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);	/*	 * We just mark the leaf entry stale by putting a null in it.	 */	be16_add(&leaf->hdr.stale, 1);	xfs_dir2_leaf_log_header(tp, lbp);	lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);	xfs_dir2_leaf_log_ents(tp, lbp, index, index);	/*	 * Scan the freespace in the data block again if necessary,	 * log the data block header if necessary.	 */	if (needscan)		xfs_dir2_data_freescan(mp, data, &needlog);	if (needlog)		xfs_dir2_data_log_header(tp, dbp);	/*	 * If the longest freespace in the data block has changed,	 * put the new value in the bests table and log that.	 */	if (be16_to_cpu(data->hdr.bestfree[0].length) != oldbest) {		bestsp[db] = data->hdr.bestfree[0].length;		xfs_dir2_leaf_log_bests(tp, lbp, db, db);	}	xfs_dir2_data_check(dp, dbp);	/*	 * If the data block is now empty then get rid of the data block.	 */	if (be16_to_cpu(data->hdr.bestfree[0].length) ==	    mp->m_dirblksize - (uint)sizeof(data->hdr)) {		ASSERT(db != mp->m_dirdatablk);		if ((error = xfs_dir2_shrink_inode(args, db, dbp))) {			/*			 * Nope, can't get rid of it because it caused			 * allocation of a bmap btree block to do so.			 * Just go on, returning success, leaving the			 * empty block in place.			 */			if (error == ENOSPC && args->total == 0) {				xfs_da_buf_done(dbp);				error = 0;			}			xfs_dir2_leaf_check(dp, lbp);			xfs_da_buf_done(lbp);			return error;		}		dbp = NULL;		/*		 * If this is the last data block then compact the		 * bests table by getting rid of entries.		 */		if (db == be32_to_cpu(ltp->bestcount) - 1) {			/*			 * Look for the last active entry (i).			 */			for (i = db - 1; i > 0; i--) {				if (be16_to_cpu(bestsp[i]) != NULLDATAOFF)					break;			}			/*			 * Copy the table down so inactive entries at the			 * end are removed.			 */			memmove(&bestsp[db - i], bestsp,				(be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp));			be32_add(&ltp->bestcount, -(db - i));			xfs_dir2_leaf_log_tail(tp, lbp);			xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);		} else			bestsp[db] = cpu_to_be16(NULLDATAOFF);	}	/*	 * If the data block was not the first one, drop it.	 */	else if (db != mp->m_dirdatablk && dbp != NULL) {		xfs_da_buf_done(dbp);		dbp = NULL;	}	xfs_dir2_leaf_check(dp, lbp);	/*	 * See if we can convert to block form.	 */	return xfs_dir2_leaf_to_block(args, lbp, dbp);}/* * Replace the inode number in a leaf format directory entry. */int						/* error */xfs_dir2_leaf_replace(	xfs_da_args_t		*args)		/* operation arguments */{	xfs_dabuf_t		*dbp;		/* data block buffer */	xfs_dir2_data_entry_t	*dep;		/* data block entry */	xfs_inode_t		*dp;		/* incore directory inode */	int			error;		/* error return code */	int			index;		/* index of leaf entry */	xfs_dabuf_t		*lbp;		/* leaf buffer */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */	xfs_trans_t		*tp;		/* transaction pointer */	xfs_dir2_trace_args("leaf_replace", args);	/*	 * Look up the entry.	 */	if ((error = xfs_dir2_leaf_lookup_int(args, &lbp, &index, &dbp))) {		return error;	}	dp = args->dp;	leaf = lbp->data;	/*	 * Point to the leaf entry, get data address from it.	 */	lep = &leaf->ents[index];	/*	 * Point to the data entry.	 */	dep = (xfs_dir2_data_entry_t *)	      ((char *)dbp->data +	       xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));	ASSERT(args->inumber != be64_to_cpu(dep->inumber));	/*	 * Put the new inode number in, log it.	 */	dep->inumber = cpu_to_be64(args->inumber);	tp = args->trans;	xfs_dir2_data_log_entry(tp, dbp, dep);	xfs_da_buf_done(dbp);	xfs_dir2_leaf_check(dp, lbp);	xfs_da_brelse(tp, lbp);	return 0;}/* * Return index in the leaf block (lbp) which is either the first * one with this hash value, or if there are none, the insert point * for that hash value. */int						/* index value */xfs_dir2_leaf_search_hash(	xfs_da_args_t		*args,		/* operation arguments */	xfs_dabuf_t		*lbp)		/* leaf buffer */{	xfs_dahash_t		hash=0;		/* hash from this entry */	xfs_dahash_t		hashwant;	/* hash value looking for */	int			high;		/* high leaf index */	int			low;		/* low leaf index */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */	int			mid=0;		/* current leaf index */	leaf = lbp->data;#ifndef __KERNEL__	if (!leaf->hdr.count)		return 0;#endif	/*	 * Note, the table cannot be empty, so we have to go through the loop.	 * Binary search the leaf entries looking for our hash value.	 */	for (lep = leaf->ents, low = 0, high = be16_to_cpu(leaf->hdr.count) - 1,		hashwant = args->hashval;	     low <= high; ) {		mid = (low + high) >> 1;		if ((hash = be32_to_cpu(lep[mid].hashval)) == hashwant)			break;		if (hash < hashwant)			low = mid + 1;		else			high = mid - 1;	}	/*	 * Found one, back up through all the equal hash values.	 */	if (hash == hashwant) {		while (mid > 0 && be32_to_cpu(lep[mid - 1].hashval) == hashwant) {			mid--;		}	}	/*	 * Need to point to an entry higher than ours.	 */	else if (hash < hashwant)		mid++;	return mid;}/* * Trim off a trailing data block.  We know it's empty since the leaf * freespace table says so. */int						/* error */xfs_dir2_leaf_trim_data(	xfs_da_args_t		*args,		/* operation arguments */	xfs_dabuf_t		*lbp,		/* leaf buffer */	xfs_dir2_db_t		db)		/* data block number */{	__be16			*bestsp;	/* leaf bests table */#ifdef DEBUG	xfs_dir2_data_t		*data;		/* data block structure */#endif	xfs_dabuf_t		*dbp;		/* data block buffer */	xfs_inode_t		*dp;		/* incore directory inode */	int			error;		/* error return value */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */	xfs_mount_t		*mp;		/* filesystem mount point */	xfs_trans_t		*tp;		/* transaction pointer */	dp = args->dp;	mp = dp->i_mount;	tp = args->trans;	/*	 * Read the offending data block.  We need its buffer.	 */	if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp,			XFS_DATA_FORK))) {		return error;	}#ifdef DEBUG	data = dbp->data;	ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC);#endif	/* this seems to be an error	 * data is only valid if DEBUG is defined?	 * RMC 09/08/1999	 */	leaf = lbp->data;	ltp = xfs_dir2_leaf_tail_p(mp, leaf);	ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) ==	       mp->m_dirblksize - (uint)sizeof(data->hdr));	ASSERT(db == be32_to_cpu(ltp->bestcount) - 1);	/*	 * Get rid of the data block.	 */	if ((error = xfs_dir2_shrink_inode(args, db, dbp))) {		ASSERT(error != ENOSPC);		xfs_da_brelse(tp, dbp);		return error;	}	/*	 * Eliminate the last bests entry from the table.	 */	bestsp = xfs_dir2_leaf_bests_p(ltp);	be32_add(&ltp->bestcount, -1);	memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp));	xfs_dir2_leaf_log_tail(tp, lbp);	xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);	return 0;}/* * Convert node form directory to leaf form directory. * The root of the node form dir needs to already be a LEAFN block. * Just return if we can't do anything. */int						/* error */xfs_dir2_node_to_leaf(	xfs_da_state_t		*state)		/* directory operation state */{	xfs_da_args_t		*args;		/* operation arguments */	xfs_inode_t		*dp;		/* incore directory inode */	int			error;		/* error return code */	xfs_dabuf_t		*fbp;		/* buffer for freespace block */	xfs_fileoff_t		fo;		/* freespace file offset */	xfs_dir2_free_t		*free;		/* freespace structure */	xfs_dabuf_t		*lbp;		/* buffer for leaf block */	xfs_dir2_leaf_tail_t	*ltp;		/* tail of leaf structure */	xfs_dir2_leaf_t		*leaf;		/* leaf structure */	xfs_mount_t		*mp;		/* filesystem mount point */	int			rval;		/* successful free trim? */	xfs_trans_t		*tp;		/* transaction pointer */	/*	 * There's more than a leaf level in the btree, so there must	 * be multiple leafn blocks.  Give up.	 */	if (state->path.active > 1)		return 0;	args = state->args;	xfs_dir2_trace_args("node_to_leaf", args);	mp = state->mp;	dp = args->dp;	tp = args->trans;	/*	 * Get the last offset in the file.	 */	if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK))) {		return error;	}	fo -= mp->m_dirblkfsbs;	/*	 * If there are freespace blocks other than the first one,	 * take this opportunity to remove trailing empty freespace blocks	 * that may have been left behind during no-space-reservation	 * operations.	 */	while (fo > mp->m_dirfreeblk) {		if ((error = xfs_dir2_node_trim_free(args, fo, &rval))) {			return error;		}		if (rval)			fo -= mp->m_dirblkfsbs;		else			return 0;	}	/*	 * Now find the block just before the freespace block.	 */	if ((error = xfs_bmap_last_before(tp, dp, &fo, XFS_DATA_FORK))) {		return error;	}	/*	 * If it's not the single leaf block, give up.	 */	if (XFS_FSB_TO_B(mp, fo) > XFS_DIR2_LEAF_OFFSET + mp->m_dirblksize)		return 0;	lbp = state->path.blk[0].bp;	leaf = lbp->data;	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);	/*	 * Read the freespace block.	 */	if ((error = xfs_da_read_buf(tp, dp, mp->m_dirfreeblk, -1, &fbp,			XFS_DATA_FORK))) {		return error;	}	free = fbp->data;	ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);	ASSERT(!free->hdr.firstdb);	/*	 * Now see if the leafn and free data will fit in a leaf1.	 * If not, release the buffer and give up.	 */	if ((uint)sizeof(leaf->hdr) +	    (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale)) * (uint)sizeof(leaf->ents[0]) +	    be32_to_cpu(free->hdr.nvalid) * (uint)sizeof(leaf->bests[0]) +	    (uint)sizeof(leaf->tail) >	    mp->m_dirblksize) {		xfs_da_brelse(tp, fbp);		return 0;	}	/*	 * If the leaf has any stale entries in it, compress them out.	 * The compact routine will log the header.	 */	if (be16_to_cpu(leaf->hdr.stale))		xfs_dir2_leaf_compact(args, lbp);	else		xfs_dir2_leaf_log_header(tp, lbp);	leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAF1_MAGIC);	/*	 * Set up the leaf tail from the freespace block.	 */	ltp = xfs_dir2_leaf_tail_p(mp, leaf);	ltp->bestcount = free->hdr.nvalid;	/*	 * Set up the leaf bests table.	 */	memcpy(xfs_dir2_leaf_bests_p(ltp), free->bests,		be32_to_cpu(ltp->bestcount) * sizeof(leaf->bests[0]));	xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);	xfs_dir2_leaf_log_tail(tp, lbp);	xfs_dir2_leaf_check(dp, lbp);	/*	 * Get rid of the freespace block.	 */	error = xfs_dir2_shrink_inode(args, XFS_DIR2_FREE_FIRSTDB(mp), fbp);	if (error) {		/*		 * This can't fail here because it can only happen when		 * punching out the middle of an extent, and this is an		 * isolated block.		 */		ASSERT(error != ENOSPC);		return error;	}	fbp = NULL;	/*	 * Now see if we can convert the single-leaf directory	 * down to a block form directory.	 * This routine always kills the dabuf for the leaf, so	 * eliminate it from the path.	 */	error = xfs_dir2_leaf_to_block(args, lbp, NULL);	state->path.blk[0].bp = NULL;	return error;}

⌨️ 快捷键说明

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