xfs_dir2_off_t xfs_dir2_db_off_to_byte(xfs_mount_t *mp, xfs_dir2_db_t db, xfs_dir2_data_aoff_t o) { return XFS_DIR2_DB_OFF_TO_BYTE(mp, db, o); }
/* * Remove the given block from the directory. * This routine is used for data and free blocks, leaf/node are done * by xfs_da_shrink_inode. */ int xfs_dir2_shrink_inode( xfs_da_args_t *args, xfs_dir2_db_t db, xfs_dabuf_t *bp) { xfs_fileoff_t bno; /* directory file offset */ xfs_dablk_t da; /* directory file offset */ int done; /* bunmap is finished */ xfs_inode_t *dp; int error; xfs_mount_t *mp; xfs_trans_t *tp; xfs_dir2_trace_args_db("shrink_inode", args, db, bp); dp = args->dp; mp = dp->i_mount; tp = args->trans; da = XFS_DIR2_DB_TO_DA(mp, db); /* * Unmap the fsblock(s). */ if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, NULL, &done))) { /* * ENOSPC actually can happen if we're in a removename with * no space reservation, and the resulting block removal * would cause a bmap btree split or conversion from extents * to btree. This can only happen for un-fragmented * directory blocks, since you need to be punching out * the middle of an extent. * In this case we need to leave the block in the file, * and not binval it. * So the block has to be in a consistent empty state * and appropriately logged. * We don't free up the buffer, the caller can tell it * hasn't happened since it got an error back. */ return error; } ASSERT(done); /* * Invalidate the buffer from the transaction. */ xfs_da_binval(tp, bp); /* * If it's not a data block, we're done. */ if (db >= XFS_DIR2_LEAF_FIRSTDB(mp)) return 0; /* * If the block isn't the last one in the directory, we're done. */ if (dp->i_d.di_size > XFS_DIR2_DB_OFF_TO_BYTE(mp, db + 1, 0)) return 0; bno = da; if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) { /* * This can't really happen unless there's kernel corruption. */ return error; } if (db == mp->m_dirdatablk) ASSERT(bno == 0); else ASSERT(bno > 0); /* * Set the size to the new last block. */ dp->i_d.di_size = XFS_FSB_TO_B(mp, bno); xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); return 0; }