xfs: update for 3.6-rc1
Numerous cleanups and several bug fixes. Here are some highlights: * Discontiguous directory buffer support * Inode allocator refactoring * Removal of the IO lock in inode reclaim * Implementation of .update_time * Fix for handling of EOF in xfs_vm_writepage * Fix for races in xfsaild, and idle mode is re-enabled * Fix for a crash in xfs_buf completion handlers on unmount. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIcBAABAgAGBQJQFtCvAAoJENaLyazVq6ZOIuEQAINJXb4SK9oBrdwGmq+Vsqf2 Eh4OmzZmdnSPrxfFGmqvyL9DdUBvGBuidwOcVLMAXGtzbxE9USK9NuKC5zN/hJip 8tIyv/8bqZ0aD4RJlHGN5zKFoQh/9Tag+JsaaqWstO8Ir1tA/5p04hDAz492btfT 49SvnV64sJ1fi7pmaJblMWMMtlWJjD6iOldaHwnKBQ3LKmcgy9sD9DY5HiGOTr1j ecKtucX7B8Q9oFLKHaKEwTYZRRYDNuTbqZmI6hlEcA5hT280jotsGA4q/aXx/gHS lZuBaqVtNFT5WCKm+j/et76tmTfIh0CSbo64ZfgSOESy2BkEVXHg5XJ1gDvPdV+L 6eBlUx3jaiNyFVHxVzFhzwKC/XdaITCd/ixFEogRDmoppDXencTCibLJXHNXxupN BCAyTLCxEJIE9WCeOMmwHA0450bMY4or13NGep57pIvG8GomtdG1WncTRIo84KV5 0W5ocaUTGP7ROsr+KF8U9C7H866OHzVFijA+vvcTy8GtsT/xOCFxuJrqPVb+kgD7 mIKaoK7iH6Kufu433TzsLEcUkF36gq/7NytPKjQhURLpZhxkHG3rq6LC0HXp6uuZ QgX5Y5Gl7SwDovIrndXmQXRnGrzvqHLguZl65+rB1CKggjemkLSdSLhryoNVjLU2 iB7/hvzOUdYFMRRz2mLc =2wkC -----END PGP SIGNATURE----- Merge tag 'for-linus-v3.6-rc1' of git://oss.sgi.com/xfs/xfs Pull xfs update from Ben Myers: "Numerous cleanups and several bug fixes. Here are some highlights: - Discontiguous directory buffer support - Inode allocator refactoring - Removal of the IO lock in inode reclaim - Implementation of .update_time - Fix for handling of EOF in xfs_vm_writepage - Fix for races in xfsaild, and idle mode is re-enabled - Fix for a crash in xfs_buf completion handlers on unmount." Fix up trivial conflicts in fs/xfs/{xfs_buf.c,xfs_log.c,xfs_log_priv.h} due to duplicate patches that had already been merged for 3.5. * tag 'for-linus-v3.6-rc1' of git://oss.sgi.com/xfs/xfs: (44 commits) xfs: wait for the write the superblock on unmount xfs: re-enable xfsaild idle mode and fix associated races xfs: remove iolock lock classes xfs: avoid the iolock in xfs_free_eofblocks for evicted inodes xfs: do not take the iolock in xfs_inactive xfs: remove xfs_inactive_attrs xfs: clean up xfs_inactive xfs: do not read the AGI buffer in xfs_dialloc until nessecary xfs: refactor xfs_ialloc_ag_select xfs: add a short cut to xfs_dialloc for the non-NULL agbp case xfs: remove the alloc_done argument to xfs_dialloc xfs: split xfs_dialloc xfs: remove xfs_ialloc_find_free Prefix IO_XX flags with XFS_IO_XX to avoid namespace colision. xfs: remove xfs_inotobp xfs: merge xfs_itobp into xfs_imap_to_bp xfs: handle EOF correctly in xfs_vm_writepage xfs: implement ->update_time xfs: fix comment typo of struct xfs_da_blkinfo. xfs: do not call xfs_bdstrat_cb in xfs_buf_iodone_callbacks ...
This commit is contained in:
Коммит
37cd9600a9
|
@ -50,20 +50,6 @@ typedef struct xfs_alloc_rec_incore {
|
|||
/* btree pointer type */
|
||||
typedef __be32 xfs_alloc_ptr_t;
|
||||
|
||||
/*
|
||||
* Minimum and maximum blocksize and sectorsize.
|
||||
* The blocksize upper limit is pretty much arbitrary.
|
||||
* The sectorsize upper limit is due to sizeof(sb_sectsize).
|
||||
*/
|
||||
#define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */
|
||||
#define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */
|
||||
#define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG)
|
||||
#define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG)
|
||||
#define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */
|
||||
#define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */
|
||||
#define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG)
|
||||
#define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG)
|
||||
|
||||
/*
|
||||
* Block numbers in the AG:
|
||||
* SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3.
|
||||
|
|
|
@ -179,7 +179,7 @@ xfs_finish_ioend(
|
|||
if (atomic_dec_and_test(&ioend->io_remaining)) {
|
||||
struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount;
|
||||
|
||||
if (ioend->io_type == IO_UNWRITTEN)
|
||||
if (ioend->io_type == XFS_IO_UNWRITTEN)
|
||||
queue_work(mp->m_unwritten_workqueue, &ioend->io_work);
|
||||
else if (ioend->io_append_trans)
|
||||
queue_work(mp->m_data_workqueue, &ioend->io_work);
|
||||
|
@ -210,7 +210,7 @@ xfs_end_io(
|
|||
* For unwritten extents we need to issue transactions to convert a
|
||||
* range to normal written extens after the data I/O has finished.
|
||||
*/
|
||||
if (ioend->io_type == IO_UNWRITTEN) {
|
||||
if (ioend->io_type == XFS_IO_UNWRITTEN) {
|
||||
/*
|
||||
* For buffered I/O we never preallocate a transaction when
|
||||
* doing the unwritten extent conversion, but for direct I/O
|
||||
|
@ -312,7 +312,7 @@ xfs_map_blocks(
|
|||
if (XFS_FORCED_SHUTDOWN(mp))
|
||||
return -XFS_ERROR(EIO);
|
||||
|
||||
if (type == IO_UNWRITTEN)
|
||||
if (type == XFS_IO_UNWRITTEN)
|
||||
bmapi_flags |= XFS_BMAPI_IGSTATE;
|
||||
|
||||
if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
|
||||
|
@ -323,10 +323,10 @@ xfs_map_blocks(
|
|||
|
||||
ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
|
||||
(ip->i_df.if_flags & XFS_IFEXTENTS));
|
||||
ASSERT(offset <= mp->m_maxioffset);
|
||||
ASSERT(offset <= mp->m_super->s_maxbytes);
|
||||
|
||||
if (offset + count > mp->m_maxioffset)
|
||||
count = mp->m_maxioffset - offset;
|
||||
if (offset + count > mp->m_super->s_maxbytes)
|
||||
count = mp->m_super->s_maxbytes - offset;
|
||||
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
|
||||
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
|
||||
|
@ -336,7 +336,7 @@ xfs_map_blocks(
|
|||
if (error)
|
||||
return -XFS_ERROR(error);
|
||||
|
||||
if (type == IO_DELALLOC &&
|
||||
if (type == XFS_IO_DELALLOC &&
|
||||
(!nimaps || isnullstartblock(imap->br_startblock))) {
|
||||
error = xfs_iomap_write_allocate(ip, offset, count, imap);
|
||||
if (!error)
|
||||
|
@ -345,7 +345,7 @@ xfs_map_blocks(
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (type == IO_UNWRITTEN) {
|
||||
if (type == XFS_IO_UNWRITTEN) {
|
||||
ASSERT(nimaps);
|
||||
ASSERT(imap->br_startblock != HOLESTARTBLOCK);
|
||||
ASSERT(imap->br_startblock != DELAYSTARTBLOCK);
|
||||
|
@ -634,11 +634,11 @@ xfs_check_page_type(
|
|||
bh = head = page_buffers(page);
|
||||
do {
|
||||
if (buffer_unwritten(bh))
|
||||
acceptable += (type == IO_UNWRITTEN);
|
||||
acceptable += (type == XFS_IO_UNWRITTEN);
|
||||
else if (buffer_delay(bh))
|
||||
acceptable += (type == IO_DELALLOC);
|
||||
acceptable += (type == XFS_IO_DELALLOC);
|
||||
else if (buffer_dirty(bh) && buffer_mapped(bh))
|
||||
acceptable += (type == IO_OVERWRITE);
|
||||
acceptable += (type == XFS_IO_OVERWRITE);
|
||||
else
|
||||
break;
|
||||
} while ((bh = bh->b_this_page) != head);
|
||||
|
@ -721,11 +721,11 @@ xfs_convert_page(
|
|||
if (buffer_unwritten(bh) || buffer_delay(bh) ||
|
||||
buffer_mapped(bh)) {
|
||||
if (buffer_unwritten(bh))
|
||||
type = IO_UNWRITTEN;
|
||||
type = XFS_IO_UNWRITTEN;
|
||||
else if (buffer_delay(bh))
|
||||
type = IO_DELALLOC;
|
||||
type = XFS_IO_DELALLOC;
|
||||
else
|
||||
type = IO_OVERWRITE;
|
||||
type = XFS_IO_OVERWRITE;
|
||||
|
||||
if (!xfs_imap_valid(inode, imap, offset)) {
|
||||
done = 1;
|
||||
|
@ -733,7 +733,7 @@ xfs_convert_page(
|
|||
}
|
||||
|
||||
lock_buffer(bh);
|
||||
if (type != IO_OVERWRITE)
|
||||
if (type != XFS_IO_OVERWRITE)
|
||||
xfs_map_at_offset(inode, bh, imap, offset);
|
||||
xfs_add_to_ioend(inode, bh, offset, type,
|
||||
ioendp, done);
|
||||
|
@ -831,7 +831,7 @@ xfs_aops_discard_page(
|
|||
struct buffer_head *bh, *head;
|
||||
loff_t offset = page_offset(page);
|
||||
|
||||
if (!xfs_check_page_type(page, IO_DELALLOC))
|
||||
if (!xfs_check_page_type(page, XFS_IO_DELALLOC))
|
||||
goto out_invalidate;
|
||||
|
||||
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
|
||||
|
@ -927,11 +927,26 @@ xfs_vm_writepage(
|
|||
end_index = offset >> PAGE_CACHE_SHIFT;
|
||||
last_index = (offset - 1) >> PAGE_CACHE_SHIFT;
|
||||
if (page->index >= end_index) {
|
||||
if ((page->index >= end_index + 1) ||
|
||||
!(i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) {
|
||||
unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1);
|
||||
|
||||
/*
|
||||
* Just skip the page if it is fully outside i_size, e.g. due
|
||||
* to a truncate operation that is in progress.
|
||||
*/
|
||||
if (page->index >= end_index + 1 || offset_into_page == 0) {
|
||||
unlock_page(page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The page straddles i_size. It must be zeroed out on each
|
||||
* and every writepage invocation because it may be mmapped.
|
||||
* "A file is mapped in multiples of the page size. For a file
|
||||
* that is not a multiple of the page size, the remaining
|
||||
* memory is zeroed when mapped, and writes to that region are
|
||||
* not written out to the file."
|
||||
*/
|
||||
zero_user_segment(page, offset_into_page, PAGE_CACHE_SIZE);
|
||||
}
|
||||
|
||||
end_offset = min_t(unsigned long long,
|
||||
|
@ -941,7 +956,7 @@ xfs_vm_writepage(
|
|||
|
||||
bh = head = page_buffers(page);
|
||||
offset = page_offset(page);
|
||||
type = IO_OVERWRITE;
|
||||
type = XFS_IO_OVERWRITE;
|
||||
|
||||
if (wbc->sync_mode == WB_SYNC_NONE)
|
||||
nonblocking = 1;
|
||||
|
@ -966,18 +981,18 @@ xfs_vm_writepage(
|
|||
}
|
||||
|
||||
if (buffer_unwritten(bh)) {
|
||||
if (type != IO_UNWRITTEN) {
|
||||
type = IO_UNWRITTEN;
|
||||
if (type != XFS_IO_UNWRITTEN) {
|
||||
type = XFS_IO_UNWRITTEN;
|
||||
imap_valid = 0;
|
||||
}
|
||||
} else if (buffer_delay(bh)) {
|
||||
if (type != IO_DELALLOC) {
|
||||
type = IO_DELALLOC;
|
||||
if (type != XFS_IO_DELALLOC) {
|
||||
type = XFS_IO_DELALLOC;
|
||||
imap_valid = 0;
|
||||
}
|
||||
} else if (buffer_uptodate(bh)) {
|
||||
if (type != IO_OVERWRITE) {
|
||||
type = IO_OVERWRITE;
|
||||
if (type != XFS_IO_OVERWRITE) {
|
||||
type = XFS_IO_OVERWRITE;
|
||||
imap_valid = 0;
|
||||
}
|
||||
} else {
|
||||
|
@ -1013,7 +1028,7 @@ xfs_vm_writepage(
|
|||
}
|
||||
if (imap_valid) {
|
||||
lock_buffer(bh);
|
||||
if (type != IO_OVERWRITE)
|
||||
if (type != XFS_IO_OVERWRITE)
|
||||
xfs_map_at_offset(inode, bh, &imap, offset);
|
||||
xfs_add_to_ioend(inode, bh, offset, type, &ioend,
|
||||
new_ioend);
|
||||
|
@ -1054,7 +1069,7 @@ xfs_vm_writepage(
|
|||
* Reserve log space if we might write beyond the on-disk
|
||||
* inode size.
|
||||
*/
|
||||
if (ioend->io_type != IO_UNWRITTEN &&
|
||||
if (ioend->io_type != XFS_IO_UNWRITTEN &&
|
||||
xfs_ioend_is_append(ioend)) {
|
||||
err = xfs_setfilesize_trans_alloc(ioend);
|
||||
if (err)
|
||||
|
@ -1162,9 +1177,9 @@ __xfs_get_blocks(
|
|||
lockmode = xfs_ilock_map_shared(ip);
|
||||
}
|
||||
|
||||
ASSERT(offset <= mp->m_maxioffset);
|
||||
if (offset + size > mp->m_maxioffset)
|
||||
size = mp->m_maxioffset - offset;
|
||||
ASSERT(offset <= mp->m_super->s_maxbytes);
|
||||
if (offset + size > mp->m_super->s_maxbytes)
|
||||
size = mp->m_super->s_maxbytes - offset;
|
||||
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
|
||||
offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||
|
||||
|
@ -1351,7 +1366,7 @@ xfs_end_io_direct_write(
|
|||
ioend->io_iocb = iocb;
|
||||
ioend->io_result = ret;
|
||||
if (private && size > 0)
|
||||
ioend->io_type = IO_UNWRITTEN;
|
||||
ioend->io_type = XFS_IO_UNWRITTEN;
|
||||
|
||||
if (is_async) {
|
||||
ioend->io_isasync = 1;
|
||||
|
@ -1383,7 +1398,7 @@ xfs_vm_direct_IO(
|
|||
* and converts at least on unwritten extent we will cancel
|
||||
* the still clean transaction after the I/O has finished.
|
||||
*/
|
||||
iocb->private = ioend = xfs_alloc_ioend(inode, IO_DIRECT);
|
||||
iocb->private = ioend = xfs_alloc_ioend(inode, XFS_IO_DIRECT);
|
||||
if (offset + size > XFS_I(inode)->i_d.di_size) {
|
||||
ret = xfs_setfilesize_trans_alloc(ioend);
|
||||
if (ret)
|
||||
|
|
|
@ -24,17 +24,17 @@ extern mempool_t *xfs_ioend_pool;
|
|||
* Types of I/O for bmap clustering and I/O completion tracking.
|
||||
*/
|
||||
enum {
|
||||
IO_DIRECT = 0, /* special case for direct I/O ioends */
|
||||
IO_DELALLOC, /* mapping covers delalloc region */
|
||||
IO_UNWRITTEN, /* mapping covers allocated but uninitialized data */
|
||||
IO_OVERWRITE, /* mapping covers already allocated extent */
|
||||
XFS_IO_DIRECT = 0, /* special case for direct I/O ioends */
|
||||
XFS_IO_DELALLOC, /* covers delalloc region */
|
||||
XFS_IO_UNWRITTEN, /* covers allocated but uninitialized data */
|
||||
XFS_IO_OVERWRITE, /* covers already allocated extent */
|
||||
};
|
||||
|
||||
#define XFS_IO_TYPES \
|
||||
{ 0, "" }, \
|
||||
{ IO_DELALLOC, "delalloc" }, \
|
||||
{ IO_UNWRITTEN, "unwritten" }, \
|
||||
{ IO_OVERWRITE, "overwrite" }
|
||||
{ XFS_IO_DELALLOC, "delalloc" }, \
|
||||
{ XFS_IO_UNWRITTEN, "unwritten" }, \
|
||||
{ XFS_IO_OVERWRITE, "overwrite" }
|
||||
|
||||
/*
|
||||
* xfs_ioend struct manages large extent writes for XFS.
|
||||
|
|
|
@ -893,7 +893,7 @@ STATIC int
|
|||
xfs_attr_leaf_addname(xfs_da_args_t *args)
|
||||
{
|
||||
xfs_inode_t *dp;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
int retval, error, committed, forkoff;
|
||||
|
||||
trace_xfs_attr_leaf_addname(args);
|
||||
|
@ -915,11 +915,11 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
|
|||
*/
|
||||
retval = xfs_attr_leaf_lookup_int(bp, args);
|
||||
if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
|
||||
xfs_da_brelse(args->trans, bp);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
return(retval);
|
||||
} else if (retval == EEXIST) {
|
||||
if (args->flags & ATTR_CREATE) { /* pure create op */
|
||||
xfs_da_brelse(args->trans, bp);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
@ -937,7 +937,6 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
|
|||
* if required.
|
||||
*/
|
||||
retval = xfs_attr_leaf_add(bp, args);
|
||||
xfs_da_buf_done(bp);
|
||||
if (retval == ENOSPC) {
|
||||
/*
|
||||
* Promote the attribute list to the Btree format, then
|
||||
|
@ -1065,8 +1064,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
|
|||
*/
|
||||
if (committed)
|
||||
xfs_trans_ijoin(args->trans, dp, 0);
|
||||
} else
|
||||
xfs_da_buf_done(bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Commit the remove and start the next trans in series.
|
||||
|
@ -1092,7 +1090,7 @@ STATIC int
|
|||
xfs_attr_leaf_removename(xfs_da_args_t *args)
|
||||
{
|
||||
xfs_inode_t *dp;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
int error, committed, forkoff;
|
||||
|
||||
trace_xfs_attr_leaf_removename(args);
|
||||
|
@ -1111,7 +1109,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
|
|||
ASSERT(bp != NULL);
|
||||
error = xfs_attr_leaf_lookup_int(bp, args);
|
||||
if (error == ENOATTR) {
|
||||
xfs_da_brelse(args->trans, bp);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
return(error);
|
||||
}
|
||||
|
||||
|
@ -1141,8 +1139,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
|
|||
*/
|
||||
if (committed)
|
||||
xfs_trans_ijoin(args->trans, dp, 0);
|
||||
} else
|
||||
xfs_da_buf_done(bp);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -1155,7 +1152,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
|
|||
STATIC int
|
||||
xfs_attr_leaf_get(xfs_da_args_t *args)
|
||||
{
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
args->blkno = 0;
|
||||
|
@ -1167,11 +1164,11 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
|
|||
|
||||
error = xfs_attr_leaf_lookup_int(bp, args);
|
||||
if (error != EEXIST) {
|
||||
xfs_da_brelse(args->trans, bp);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
return(error);
|
||||
}
|
||||
error = xfs_attr_leaf_getvalue(bp, args);
|
||||
xfs_da_brelse(args->trans, bp);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
|
||||
error = xfs_attr_rmtval_get(args);
|
||||
}
|
||||
|
@ -1186,23 +1183,23 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context)
|
|||
{
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
int error;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
|
||||
context->cursor->blkno = 0;
|
||||
error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
|
||||
if (error)
|
||||
return XFS_ERROR(error);
|
||||
ASSERT(bp != NULL);
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
if (unlikely(leaf->hdr.info.magic != cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
|
||||
XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
|
||||
context->dp->i_mount, leaf);
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
return XFS_ERROR(EFSCORRUPTED);
|
||||
}
|
||||
|
||||
error = xfs_attr_leaf_list_int(bp, context);
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
return XFS_ERROR(error);
|
||||
}
|
||||
|
||||
|
@ -1489,7 +1486,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
|
|||
xfs_da_state_t *state;
|
||||
xfs_da_state_blk_t *blk;
|
||||
xfs_inode_t *dp;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
int retval, error, committed, forkoff;
|
||||
|
||||
trace_xfs_attr_node_removename(args);
|
||||
|
@ -1601,14 +1598,13 @@ xfs_attr_node_removename(xfs_da_args_t *args)
|
|||
*/
|
||||
ASSERT(state->path.active == 1);
|
||||
ASSERT(state->path.blk[0].bp);
|
||||
xfs_da_buf_done(state->path.blk[0].bp);
|
||||
state->path.blk[0].bp = NULL;
|
||||
|
||||
error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
|
||||
XFS_ATTR_FORK);
|
||||
if (error)
|
||||
goto out;
|
||||
ASSERT((((xfs_attr_leafblock_t *)bp->data)->hdr.info.magic) ==
|
||||
ASSERT((((xfs_attr_leafblock_t *)bp->b_addr)->hdr.info.magic) ==
|
||||
cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
|
||||
if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
|
||||
|
@ -1635,7 +1631,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
|
|||
if (committed)
|
||||
xfs_trans_ijoin(args->trans, dp, 0);
|
||||
} else
|
||||
xfs_da_brelse(args->trans, bp);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
}
|
||||
error = 0;
|
||||
|
||||
|
@ -1665,8 +1661,7 @@ xfs_attr_fillstate(xfs_da_state_t *state)
|
|||
ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
|
||||
for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
|
||||
if (blk->bp) {
|
||||
blk->disk_blkno = xfs_da_blkno(blk->bp);
|
||||
xfs_da_buf_done(blk->bp);
|
||||
blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
|
||||
blk->bp = NULL;
|
||||
} else {
|
||||
blk->disk_blkno = 0;
|
||||
|
@ -1681,8 +1676,7 @@ xfs_attr_fillstate(xfs_da_state_t *state)
|
|||
ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
|
||||
for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
|
||||
if (blk->bp) {
|
||||
blk->disk_blkno = xfs_da_blkno(blk->bp);
|
||||
xfs_da_buf_done(blk->bp);
|
||||
blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
|
||||
blk->bp = NULL;
|
||||
} else {
|
||||
blk->disk_blkno = 0;
|
||||
|
@ -1792,7 +1786,7 @@ xfs_attr_node_get(xfs_da_args_t *args)
|
|||
* If not in a transaction, we have to release all the buffers.
|
||||
*/
|
||||
for (i = 0; i < state->path.active; i++) {
|
||||
xfs_da_brelse(args->trans, state->path.blk[i].bp);
|
||||
xfs_trans_brelse(args->trans, state->path.blk[i].bp);
|
||||
state->path.blk[i].bp = NULL;
|
||||
}
|
||||
|
||||
|
@ -1808,7 +1802,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
|
|||
xfs_da_intnode_t *node;
|
||||
xfs_da_node_entry_t *btree;
|
||||
int error, i;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
|
||||
cursor = context->cursor;
|
||||
cursor->initted = 1;
|
||||
|
@ -1825,30 +1819,30 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
|
|||
if ((error != 0) && (error != EFSCORRUPTED))
|
||||
return(error);
|
||||
if (bp) {
|
||||
node = bp->data;
|
||||
node = bp->b_addr;
|
||||
switch (be16_to_cpu(node->hdr.info.magic)) {
|
||||
case XFS_DA_NODE_MAGIC:
|
||||
trace_xfs_attr_list_wrong_blk(context);
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
bp = NULL;
|
||||
break;
|
||||
case XFS_ATTR_LEAF_MAGIC:
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
if (cursor->hashval > be32_to_cpu(leaf->entries[
|
||||
be16_to_cpu(leaf->hdr.count)-1].hashval)) {
|
||||
trace_xfs_attr_list_wrong_blk(context);
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
bp = NULL;
|
||||
} else if (cursor->hashval <=
|
||||
be32_to_cpu(leaf->entries[0].hashval)) {
|
||||
trace_xfs_attr_list_wrong_blk(context);
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
bp = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
trace_xfs_attr_list_wrong_blk(context);
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
bp = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -1873,7 +1867,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
|
|||
context->dp->i_mount);
|
||||
return(XFS_ERROR(EFSCORRUPTED));
|
||||
}
|
||||
node = bp->data;
|
||||
node = bp->b_addr;
|
||||
if (node->hdr.info.magic ==
|
||||
cpu_to_be16(XFS_ATTR_LEAF_MAGIC))
|
||||
break;
|
||||
|
@ -1883,7 +1877,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
|
|||
XFS_ERRLEVEL_LOW,
|
||||
context->dp->i_mount,
|
||||
node);
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
return(XFS_ERROR(EFSCORRUPTED));
|
||||
}
|
||||
btree = node->btree;
|
||||
|
@ -1898,10 +1892,10 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
|
|||
}
|
||||
}
|
||||
if (i == be16_to_cpu(node->hdr.count)) {
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
return(0);
|
||||
}
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
}
|
||||
}
|
||||
ASSERT(bp != NULL);
|
||||
|
@ -1912,24 +1906,24 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
|
|||
* adding the information.
|
||||
*/
|
||||
for (;;) {
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
if (unlikely(leaf->hdr.info.magic !=
|
||||
cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
|
||||
XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
|
||||
XFS_ERRLEVEL_LOW,
|
||||
context->dp->i_mount, leaf);
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
return(XFS_ERROR(EFSCORRUPTED));
|
||||
}
|
||||
error = xfs_attr_leaf_list_int(bp, context);
|
||||
if (error) {
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
return error;
|
||||
}
|
||||
if (context->seen_enough || leaf->hdr.info.forw == 0)
|
||||
break;
|
||||
cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
|
||||
&bp, XFS_ATTR_FORK);
|
||||
if (error)
|
||||
|
@ -1941,7 +1935,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
|
|||
return(XFS_ERROR(EFSCORRUPTED));
|
||||
}
|
||||
}
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,10 +54,10 @@
|
|||
* Routines used for growing the Btree.
|
||||
*/
|
||||
STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block,
|
||||
xfs_dabuf_t **bpp);
|
||||
STATIC int xfs_attr_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
|
||||
int freemap_index);
|
||||
STATIC void xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer);
|
||||
struct xfs_buf **bpp);
|
||||
STATIC int xfs_attr_leaf_add_work(struct xfs_buf *leaf_buffer,
|
||||
xfs_da_args_t *args, int freemap_index);
|
||||
STATIC void xfs_attr_leaf_compact(xfs_trans_t *tp, struct xfs_buf *leaf_buffer);
|
||||
STATIC void xfs_attr_leaf_rebalance(xfs_da_state_t *state,
|
||||
xfs_da_state_blk_t *blk1,
|
||||
xfs_da_state_blk_t *blk2);
|
||||
|
@ -71,9 +71,9 @@ STATIC int xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
|
|||
* Routines used for shrinking the Btree.
|
||||
*/
|
||||
STATIC int xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
|
||||
xfs_dabuf_t *bp, int level);
|
||||
struct xfs_buf *bp, int level);
|
||||
STATIC int xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
|
||||
xfs_dabuf_t *bp);
|
||||
struct xfs_buf *bp);
|
||||
STATIC int xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
|
||||
xfs_dablk_t blkno, int blkcnt);
|
||||
|
||||
|
@ -480,7 +480,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
|
|||
char *tmpbuffer;
|
||||
int error, i, size;
|
||||
xfs_dablk_t blkno;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
xfs_ifork_t *ifp;
|
||||
|
||||
trace_xfs_attr_sf_to_leaf(args);
|
||||
|
@ -550,8 +550,6 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
|
|||
error = 0;
|
||||
|
||||
out:
|
||||
if(bp)
|
||||
xfs_da_buf_done(bp);
|
||||
kmem_free(tmpbuffer);
|
||||
return(error);
|
||||
}
|
||||
|
@ -737,14 +735,16 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
|
|||
* a shortform attribute list.
|
||||
*/
|
||||
int
|
||||
xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp)
|
||||
xfs_attr_shortform_allfit(
|
||||
struct xfs_buf *bp,
|
||||
struct xfs_inode *dp)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_attr_leaf_entry_t *entry;
|
||||
xfs_attr_leaf_name_local_t *name_loc;
|
||||
int bytes, i;
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
|
||||
entry = &leaf->entries[0];
|
||||
|
@ -774,7 +774,10 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp)
|
|||
* Convert a leaf attribute list to shortform attribute list
|
||||
*/
|
||||
int
|
||||
xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
|
||||
xfs_attr_leaf_to_shortform(
|
||||
struct xfs_buf *bp,
|
||||
xfs_da_args_t *args,
|
||||
int forkoff)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_attr_leaf_entry_t *entry;
|
||||
|
@ -791,10 +794,10 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
|
|||
ASSERT(tmpbuffer != NULL);
|
||||
|
||||
ASSERT(bp != NULL);
|
||||
memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount));
|
||||
memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(dp->i_mount));
|
||||
leaf = (xfs_attr_leafblock_t *)tmpbuffer;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
memset(bp->data, 0, XFS_LBSIZE(dp->i_mount));
|
||||
memset(bp->b_addr, 0, XFS_LBSIZE(dp->i_mount));
|
||||
|
||||
/*
|
||||
* Clean out the prior contents of the attribute list.
|
||||
|
@ -855,7 +858,7 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args)
|
|||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_da_intnode_t *node;
|
||||
xfs_inode_t *dp;
|
||||
xfs_dabuf_t *bp1, *bp2;
|
||||
struct xfs_buf *bp1, *bp2;
|
||||
xfs_dablk_t blkno;
|
||||
int error;
|
||||
|
||||
|
@ -877,10 +880,9 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args)
|
|||
if (error)
|
||||
goto out;
|
||||
ASSERT(bp2 != NULL);
|
||||
memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount));
|
||||
xfs_da_buf_done(bp1);
|
||||
memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(dp->i_mount));
|
||||
bp1 = NULL;
|
||||
xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1);
|
||||
xfs_trans_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1);
|
||||
|
||||
/*
|
||||
* Set up the new root node.
|
||||
|
@ -888,21 +890,17 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args)
|
|||
error = xfs_da_node_create(args, 0, 1, &bp1, XFS_ATTR_FORK);
|
||||
if (error)
|
||||
goto out;
|
||||
node = bp1->data;
|
||||
leaf = bp2->data;
|
||||
node = bp1->b_addr;
|
||||
leaf = bp2->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
/* both on-disk, don't endian-flip twice */
|
||||
node->btree[0].hashval =
|
||||
leaf->entries[be16_to_cpu(leaf->hdr.count)-1 ].hashval;
|
||||
node->btree[0].before = cpu_to_be32(blkno);
|
||||
node->hdr.count = cpu_to_be16(1);
|
||||
xfs_da_log_buf(args->trans, bp1, 0, XFS_LBSIZE(dp->i_mount) - 1);
|
||||
xfs_trans_log_buf(args->trans, bp1, 0, XFS_LBSIZE(dp->i_mount) - 1);
|
||||
error = 0;
|
||||
out:
|
||||
if (bp1)
|
||||
xfs_da_buf_done(bp1);
|
||||
if (bp2)
|
||||
xfs_da_buf_done(bp2);
|
||||
return(error);
|
||||
}
|
||||
|
||||
|
@ -916,12 +914,15 @@ out:
|
|||
* or a leaf in a node attribute list.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
|
||||
xfs_attr_leaf_create(
|
||||
xfs_da_args_t *args,
|
||||
xfs_dablk_t blkno,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_attr_leaf_hdr_t *hdr;
|
||||
xfs_inode_t *dp;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
trace_xfs_attr_leaf_create(args);
|
||||
|
@ -933,7 +934,7 @@ xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
|
|||
if (error)
|
||||
return(error);
|
||||
ASSERT(bp != NULL);
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount));
|
||||
hdr = &leaf->hdr;
|
||||
hdr->info.magic = cpu_to_be16(XFS_ATTR_LEAF_MAGIC);
|
||||
|
@ -947,7 +948,7 @@ xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
|
|||
hdr->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr->firstused) -
|
||||
sizeof(xfs_attr_leaf_hdr_t));
|
||||
|
||||
xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1);
|
||||
xfs_trans_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1);
|
||||
|
||||
*bpp = bp;
|
||||
return(0);
|
||||
|
@ -1014,7 +1015,9 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
|
|||
* Add a name to the leaf attribute list structure.
|
||||
*/
|
||||
int
|
||||
xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
||||
xfs_attr_leaf_add(
|
||||
struct xfs_buf *bp,
|
||||
struct xfs_da_args *args)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_attr_leaf_hdr_t *hdr;
|
||||
|
@ -1023,7 +1026,7 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
|||
|
||||
trace_xfs_attr_leaf_add(args);
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
ASSERT((args->index >= 0)
|
||||
&& (args->index <= be16_to_cpu(leaf->hdr.count)));
|
||||
|
@ -1085,7 +1088,10 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
|||
* Add a name to a leaf attribute list structure.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
|
||||
xfs_attr_leaf_add_work(
|
||||
struct xfs_buf *bp,
|
||||
xfs_da_args_t *args,
|
||||
int mapindex)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_attr_leaf_hdr_t *hdr;
|
||||
|
@ -1096,7 +1102,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
|
|||
xfs_mount_t *mp;
|
||||
int tmp, i;
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
hdr = &leaf->hdr;
|
||||
ASSERT((mapindex >= 0) && (mapindex < XFS_ATTR_LEAF_MAPSIZE));
|
||||
|
@ -1110,7 +1116,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
|
|||
tmp = be16_to_cpu(hdr->count) - args->index;
|
||||
tmp *= sizeof(xfs_attr_leaf_entry_t);
|
||||
memmove((char *)(entry+1), (char *)entry, tmp);
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry)));
|
||||
}
|
||||
be16_add_cpu(&hdr->count, 1);
|
||||
|
@ -1142,7 +1148,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
|
|||
args->index2++;
|
||||
}
|
||||
}
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
|
||||
ASSERT((args->index == 0) ||
|
||||
(be32_to_cpu(entry->hashval) >= be32_to_cpu((entry-1)->hashval)));
|
||||
|
@ -1174,7 +1180,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
|
|||
args->rmtblkno = 1;
|
||||
args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen);
|
||||
}
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, xfs_attr_leaf_name(leaf, args->index),
|
||||
xfs_attr_leaf_entsize(leaf, args->index)));
|
||||
|
||||
|
@ -1198,7 +1204,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
|
|||
}
|
||||
}
|
||||
be16_add_cpu(&hdr->usedbytes, xfs_attr_leaf_entsize(leaf, args->index));
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
|
||||
return(0);
|
||||
}
|
||||
|
@ -1207,7 +1213,9 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
|
|||
* Garbage collect a leaf attribute list block by copying it to a new buffer.
|
||||
*/
|
||||
STATIC void
|
||||
xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp)
|
||||
xfs_attr_leaf_compact(
|
||||
struct xfs_trans *trans,
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf_s, *leaf_d;
|
||||
xfs_attr_leaf_hdr_t *hdr_s, *hdr_d;
|
||||
|
@ -1217,14 +1225,14 @@ xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp)
|
|||
mp = trans->t_mountp;
|
||||
tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP);
|
||||
ASSERT(tmpbuffer != NULL);
|
||||
memcpy(tmpbuffer, bp->data, XFS_LBSIZE(mp));
|
||||
memset(bp->data, 0, XFS_LBSIZE(mp));
|
||||
memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(mp));
|
||||
memset(bp->b_addr, 0, XFS_LBSIZE(mp));
|
||||
|
||||
/*
|
||||
* Copy basic information
|
||||
*/
|
||||
leaf_s = (xfs_attr_leafblock_t *)tmpbuffer;
|
||||
leaf_d = bp->data;
|
||||
leaf_d = bp->b_addr;
|
||||
hdr_s = &leaf_s->hdr;
|
||||
hdr_d = &leaf_d->hdr;
|
||||
hdr_d->info = hdr_s->info; /* struct copy */
|
||||
|
@ -1247,7 +1255,7 @@ xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp)
|
|||
*/
|
||||
xfs_attr_leaf_moveents(leaf_s, 0, leaf_d, 0,
|
||||
be16_to_cpu(hdr_s->count), mp);
|
||||
xfs_da_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1);
|
||||
xfs_trans_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1);
|
||||
|
||||
kmem_free(tmpbuffer);
|
||||
}
|
||||
|
@ -1279,8 +1287,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
|
|||
*/
|
||||
ASSERT(blk1->magic == XFS_ATTR_LEAF_MAGIC);
|
||||
ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC);
|
||||
leaf1 = blk1->bp->data;
|
||||
leaf2 = blk2->bp->data;
|
||||
leaf1 = blk1->bp->b_addr;
|
||||
leaf2 = blk2->bp->b_addr;
|
||||
ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
args = state->args;
|
||||
|
@ -1298,8 +1306,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
|
|||
tmp_blk = blk1;
|
||||
blk1 = blk2;
|
||||
blk2 = tmp_blk;
|
||||
leaf1 = blk1->bp->data;
|
||||
leaf2 = blk2->bp->data;
|
||||
leaf1 = blk1->bp->b_addr;
|
||||
leaf2 = blk2->bp->b_addr;
|
||||
swap = 1;
|
||||
}
|
||||
hdr1 = &leaf1->hdr;
|
||||
|
@ -1346,8 +1354,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
|
|||
xfs_attr_leaf_moveents(leaf1, be16_to_cpu(hdr1->count) - count,
|
||||
leaf2, 0, count, state->mp);
|
||||
|
||||
xfs_da_log_buf(args->trans, blk1->bp, 0, state->blocksize-1);
|
||||
xfs_da_log_buf(args->trans, blk2->bp, 0, state->blocksize-1);
|
||||
xfs_trans_log_buf(args->trans, blk1->bp, 0, state->blocksize-1);
|
||||
xfs_trans_log_buf(args->trans, blk2->bp, 0, state->blocksize-1);
|
||||
} else if (count > be16_to_cpu(hdr1->count)) {
|
||||
/*
|
||||
* I assert that since all callers pass in an empty
|
||||
|
@ -1378,8 +1386,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
|
|||
xfs_attr_leaf_moveents(leaf2, 0, leaf1,
|
||||
be16_to_cpu(hdr1->count), count, state->mp);
|
||||
|
||||
xfs_da_log_buf(args->trans, blk1->bp, 0, state->blocksize-1);
|
||||
xfs_da_log_buf(args->trans, blk2->bp, 0, state->blocksize-1);
|
||||
xfs_trans_log_buf(args->trans, blk1->bp, 0, state->blocksize-1);
|
||||
xfs_trans_log_buf(args->trans, blk2->bp, 0, state->blocksize-1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1448,8 +1456,8 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
|
|||
/*
|
||||
* Set up environment.
|
||||
*/
|
||||
leaf1 = blk1->bp->data;
|
||||
leaf2 = blk2->bp->data;
|
||||
leaf1 = blk1->bp->b_addr;
|
||||
leaf2 = blk2->bp->b_addr;
|
||||
hdr1 = &leaf1->hdr;
|
||||
hdr2 = &leaf2->hdr;
|
||||
foundit = 0;
|
||||
|
@ -1551,7 +1559,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
|
|||
xfs_da_blkinfo_t *info;
|
||||
int count, bytes, forward, error, retval, i;
|
||||
xfs_dablk_t blkno;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
|
||||
/*
|
||||
* Check for the degenerate case of the block being over 50% full.
|
||||
|
@ -1559,7 +1567,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
|
|||
* to coalesce with a sibling.
|
||||
*/
|
||||
blk = &state->path.blk[ state->path.active-1 ];
|
||||
info = blk->bp->data;
|
||||
info = blk->bp->b_addr;
|
||||
ASSERT(info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
leaf = (xfs_attr_leafblock_t *)info;
|
||||
count = be16_to_cpu(leaf->hdr.count);
|
||||
|
@ -1622,13 +1630,13 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
|
|||
count = be16_to_cpu(leaf->hdr.count);
|
||||
bytes = state->blocksize - (state->blocksize>>2);
|
||||
bytes -= be16_to_cpu(leaf->hdr.usedbytes);
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
count += be16_to_cpu(leaf->hdr.count);
|
||||
bytes -= be16_to_cpu(leaf->hdr.usedbytes);
|
||||
bytes -= count * sizeof(xfs_attr_leaf_entry_t);
|
||||
bytes -= sizeof(xfs_attr_leaf_hdr_t);
|
||||
xfs_da_brelse(state->args->trans, bp);
|
||||
xfs_trans_brelse(state->args->trans, bp);
|
||||
if (bytes >= 0)
|
||||
break; /* fits with at least 25% to spare */
|
||||
}
|
||||
|
@ -1666,7 +1674,9 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
|
|||
* If two leaves are 37% full, when combined they will leave 25% free.
|
||||
*/
|
||||
int
|
||||
xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
||||
xfs_attr_leaf_remove(
|
||||
struct xfs_buf *bp,
|
||||
xfs_da_args_t *args)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_attr_leaf_hdr_t *hdr;
|
||||
|
@ -1676,7 +1686,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
|||
int tablesize, tmp, i;
|
||||
xfs_mount_t *mp;
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
hdr = &leaf->hdr;
|
||||
mp = args->trans->t_mountp;
|
||||
|
@ -1769,7 +1779,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
|||
*/
|
||||
memset(xfs_attr_leaf_name(leaf, args->index), 0, entsize);
|
||||
be16_add_cpu(&hdr->usedbytes, -entsize);
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, xfs_attr_leaf_name(leaf, args->index),
|
||||
entsize));
|
||||
|
||||
|
@ -1777,7 +1787,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
|||
* sizeof(xfs_attr_leaf_entry_t);
|
||||
memmove((char *)entry, (char *)(entry+1), tmp);
|
||||
be16_add_cpu(&hdr->count, -1);
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry)));
|
||||
entry = &leaf->entries[be16_to_cpu(hdr->count)];
|
||||
memset((char *)entry, 0, sizeof(xfs_attr_leaf_entry_t));
|
||||
|
@ -1807,7 +1817,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
|||
} else {
|
||||
hdr->holes = 1; /* mark as needing compaction */
|
||||
}
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
|
||||
|
||||
/*
|
||||
|
@ -1840,8 +1850,8 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
|
|||
mp = state->mp;
|
||||
ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC);
|
||||
ASSERT(save_blk->magic == XFS_ATTR_LEAF_MAGIC);
|
||||
drop_leaf = drop_blk->bp->data;
|
||||
save_leaf = save_blk->bp->data;
|
||||
drop_leaf = drop_blk->bp->b_addr;
|
||||
save_leaf = save_blk->bp->b_addr;
|
||||
ASSERT(drop_leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
ASSERT(save_leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
drop_hdr = &drop_leaf->hdr;
|
||||
|
@ -1906,7 +1916,7 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
|
|||
kmem_free(tmpbuffer);
|
||||
}
|
||||
|
||||
xfs_da_log_buf(state->args->trans, save_blk->bp, 0,
|
||||
xfs_trans_log_buf(state->args->trans, save_blk->bp, 0,
|
||||
state->blocksize - 1);
|
||||
|
||||
/*
|
||||
|
@ -1934,7 +1944,9 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
|
|||
* Don't change the args->value unless we find the attribute.
|
||||
*/
|
||||
int
|
||||
xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
||||
xfs_attr_leaf_lookup_int(
|
||||
struct xfs_buf *bp,
|
||||
xfs_da_args_t *args)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_attr_leaf_entry_t *entry;
|
||||
|
@ -1945,7 +1957,7 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
|||
|
||||
trace_xfs_attr_leaf_lookup(args);
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
ASSERT(be16_to_cpu(leaf->hdr.count)
|
||||
< (XFS_LBSIZE(args->dp->i_mount)/8));
|
||||
|
@ -2041,7 +2053,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
|||
* list structure.
|
||||
*/
|
||||
int
|
||||
xfs_attr_leaf_getvalue(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
||||
xfs_attr_leaf_getvalue(
|
||||
struct xfs_buf *bp,
|
||||
xfs_da_args_t *args)
|
||||
{
|
||||
int valuelen;
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
|
@ -2049,7 +2063,7 @@ xfs_attr_leaf_getvalue(xfs_dabuf_t *bp, xfs_da_args_t *args)
|
|||
xfs_attr_leaf_name_local_t *name_loc;
|
||||
xfs_attr_leaf_name_remote_t *name_rmt;
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
ASSERT(be16_to_cpu(leaf->hdr.count)
|
||||
< (XFS_LBSIZE(args->dp->i_mount)/8));
|
||||
|
@ -2247,12 +2261,14 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s,
|
|||
* Return 0 unless leaf2 should go before leaf1.
|
||||
*/
|
||||
int
|
||||
xfs_attr_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp)
|
||||
xfs_attr_leaf_order(
|
||||
struct xfs_buf *leaf1_bp,
|
||||
struct xfs_buf *leaf2_bp)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf1, *leaf2;
|
||||
|
||||
leaf1 = leaf1_bp->data;
|
||||
leaf2 = leaf2_bp->data;
|
||||
leaf1 = leaf1_bp->b_addr;
|
||||
leaf2 = leaf2_bp->b_addr;
|
||||
ASSERT((leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) &&
|
||||
(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)));
|
||||
if ((be16_to_cpu(leaf1->hdr.count) > 0) &&
|
||||
|
@ -2272,11 +2288,13 @@ xfs_attr_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp)
|
|||
* Pick up the last hashvalue from a leaf block.
|
||||
*/
|
||||
xfs_dahash_t
|
||||
xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count)
|
||||
xfs_attr_leaf_lasthash(
|
||||
struct xfs_buf *bp,
|
||||
int *count)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
if (count)
|
||||
*count = be16_to_cpu(leaf->hdr.count);
|
||||
|
@ -2337,7 +2355,9 @@ xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local)
|
|||
* Copy out attribute list entries for attr_list(), for leaf attribute lists.
|
||||
*/
|
||||
int
|
||||
xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
|
||||
xfs_attr_leaf_list_int(
|
||||
struct xfs_buf *bp,
|
||||
xfs_attr_list_context_t *context)
|
||||
{
|
||||
attrlist_cursor_kern_t *cursor;
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
|
@ -2345,7 +2365,7 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
|
|||
int retval, i;
|
||||
|
||||
ASSERT(bp != NULL);
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
cursor = context->cursor;
|
||||
cursor->initted = 1;
|
||||
|
||||
|
@ -2463,7 +2483,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args)
|
|||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_attr_leaf_entry_t *entry;
|
||||
xfs_attr_leaf_name_remote_t *name_rmt;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
#ifdef DEBUG
|
||||
xfs_attr_leaf_name_local_t *name_loc;
|
||||
|
@ -2482,7 +2502,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args)
|
|||
}
|
||||
ASSERT(bp != NULL);
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
ASSERT(args->index < be16_to_cpu(leaf->hdr.count));
|
||||
ASSERT(args->index >= 0);
|
||||
|
@ -2505,7 +2525,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args)
|
|||
#endif /* DEBUG */
|
||||
|
||||
entry->flags &= ~XFS_ATTR_INCOMPLETE;
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
|
||||
|
||||
if (args->rmtblkno) {
|
||||
|
@ -2513,10 +2533,9 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args)
|
|||
name_rmt = xfs_attr_leaf_name_remote(leaf, args->index);
|
||||
name_rmt->valueblk = cpu_to_be32(args->rmtblkno);
|
||||
name_rmt->valuelen = cpu_to_be32(args->valuelen);
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
|
||||
}
|
||||
xfs_da_buf_done(bp);
|
||||
|
||||
/*
|
||||
* Commit the flag value change and start the next trans in series.
|
||||
|
@ -2533,7 +2552,7 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args)
|
|||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_attr_leaf_entry_t *entry;
|
||||
xfs_attr_leaf_name_remote_t *name_rmt;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
trace_xfs_attr_leaf_setflag(args);
|
||||
|
@ -2548,7 +2567,7 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args)
|
|||
}
|
||||
ASSERT(bp != NULL);
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
ASSERT(args->index < be16_to_cpu(leaf->hdr.count));
|
||||
ASSERT(args->index >= 0);
|
||||
|
@ -2556,16 +2575,15 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args)
|
|||
|
||||
ASSERT((entry->flags & XFS_ATTR_INCOMPLETE) == 0);
|
||||
entry->flags |= XFS_ATTR_INCOMPLETE;
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
|
||||
if ((entry->flags & XFS_ATTR_LOCAL) == 0) {
|
||||
name_rmt = xfs_attr_leaf_name_remote(leaf, args->index);
|
||||
name_rmt->valueblk = 0;
|
||||
name_rmt->valuelen = 0;
|
||||
xfs_da_log_buf(args->trans, bp,
|
||||
xfs_trans_log_buf(args->trans, bp,
|
||||
XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
|
||||
}
|
||||
xfs_da_buf_done(bp);
|
||||
|
||||
/*
|
||||
* Commit the flag value change and start the next trans in series.
|
||||
|
@ -2586,7 +2604,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args)
|
|||
xfs_attr_leafblock_t *leaf1, *leaf2;
|
||||
xfs_attr_leaf_entry_t *entry1, *entry2;
|
||||
xfs_attr_leaf_name_remote_t *name_rmt;
|
||||
xfs_dabuf_t *bp1, *bp2;
|
||||
struct xfs_buf *bp1, *bp2;
|
||||
int error;
|
||||
#ifdef DEBUG
|
||||
xfs_attr_leaf_name_local_t *name_loc;
|
||||
|
@ -2620,13 +2638,13 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args)
|
|||
bp2 = bp1;
|
||||
}
|
||||
|
||||
leaf1 = bp1->data;
|
||||
leaf1 = bp1->b_addr;
|
||||
ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
ASSERT(args->index < be16_to_cpu(leaf1->hdr.count));
|
||||
ASSERT(args->index >= 0);
|
||||
entry1 = &leaf1->entries[ args->index ];
|
||||
|
||||
leaf2 = bp2->data;
|
||||
leaf2 = bp2->b_addr;
|
||||
ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
ASSERT(args->index2 < be16_to_cpu(leaf2->hdr.count));
|
||||
ASSERT(args->index2 >= 0);
|
||||
|
@ -2660,30 +2678,27 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args)
|
|||
ASSERT((entry2->flags & XFS_ATTR_INCOMPLETE) == 0);
|
||||
|
||||
entry1->flags &= ~XFS_ATTR_INCOMPLETE;
|
||||
xfs_da_log_buf(args->trans, bp1,
|
||||
xfs_trans_log_buf(args->trans, bp1,
|
||||
XFS_DA_LOGRANGE(leaf1, entry1, sizeof(*entry1)));
|
||||
if (args->rmtblkno) {
|
||||
ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0);
|
||||
name_rmt = xfs_attr_leaf_name_remote(leaf1, args->index);
|
||||
name_rmt->valueblk = cpu_to_be32(args->rmtblkno);
|
||||
name_rmt->valuelen = cpu_to_be32(args->valuelen);
|
||||
xfs_da_log_buf(args->trans, bp1,
|
||||
xfs_trans_log_buf(args->trans, bp1,
|
||||
XFS_DA_LOGRANGE(leaf1, name_rmt, sizeof(*name_rmt)));
|
||||
}
|
||||
|
||||
entry2->flags |= XFS_ATTR_INCOMPLETE;
|
||||
xfs_da_log_buf(args->trans, bp2,
|
||||
xfs_trans_log_buf(args->trans, bp2,
|
||||
XFS_DA_LOGRANGE(leaf2, entry2, sizeof(*entry2)));
|
||||
if ((entry2->flags & XFS_ATTR_LOCAL) == 0) {
|
||||
name_rmt = xfs_attr_leaf_name_remote(leaf2, args->index2);
|
||||
name_rmt->valueblk = 0;
|
||||
name_rmt->valuelen = 0;
|
||||
xfs_da_log_buf(args->trans, bp2,
|
||||
xfs_trans_log_buf(args->trans, bp2,
|
||||
XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt)));
|
||||
}
|
||||
xfs_da_buf_done(bp1);
|
||||
if (bp1 != bp2)
|
||||
xfs_da_buf_done(bp2);
|
||||
|
||||
/*
|
||||
* Commit the flag value change and start the next trans in series.
|
||||
|
@ -2706,7 +2721,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
|
|||
{
|
||||
xfs_da_blkinfo_t *info;
|
||||
xfs_daddr_t blkno;
|
||||
xfs_dabuf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
/*
|
||||
|
@ -2718,20 +2733,20 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
|
|||
error = xfs_da_read_buf(*trans, dp, 0, -1, &bp, XFS_ATTR_FORK);
|
||||
if (error)
|
||||
return(error);
|
||||
blkno = xfs_da_blkno(bp);
|
||||
blkno = XFS_BUF_ADDR(bp);
|
||||
|
||||
/*
|
||||
* Invalidate the tree, even if the "tree" is only a single leaf block.
|
||||
* This is a depth-first traversal!
|
||||
*/
|
||||
info = bp->data;
|
||||
info = bp->b_addr;
|
||||
if (info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)) {
|
||||
error = xfs_attr_node_inactive(trans, dp, bp, 1);
|
||||
} else if (info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) {
|
||||
error = xfs_attr_leaf_inactive(trans, dp, bp);
|
||||
} else {
|
||||
error = XFS_ERROR(EIO);
|
||||
xfs_da_brelse(*trans, bp);
|
||||
xfs_trans_brelse(*trans, bp);
|
||||
}
|
||||
if (error)
|
||||
return(error);
|
||||
|
@ -2742,7 +2757,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
|
|||
error = xfs_da_get_buf(*trans, dp, 0, blkno, &bp, XFS_ATTR_FORK);
|
||||
if (error)
|
||||
return(error);
|
||||
xfs_da_binval(*trans, bp); /* remove from cache */
|
||||
xfs_trans_binval(*trans, bp); /* remove from cache */
|
||||
/*
|
||||
* Commit the invalidate and start the next transaction.
|
||||
*/
|
||||
|
@ -2756,34 +2771,37 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
|
|||
* We're doing a depth-first traversal in order to invalidate everything.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
|
||||
int level)
|
||||
xfs_attr_node_inactive(
|
||||
struct xfs_trans **trans,
|
||||
struct xfs_inode *dp,
|
||||
struct xfs_buf *bp,
|
||||
int level)
|
||||
{
|
||||
xfs_da_blkinfo_t *info;
|
||||
xfs_da_intnode_t *node;
|
||||
xfs_dablk_t child_fsb;
|
||||
xfs_daddr_t parent_blkno, child_blkno;
|
||||
int error, count, i;
|
||||
xfs_dabuf_t *child_bp;
|
||||
struct xfs_buf *child_bp;
|
||||
|
||||
/*
|
||||
* Since this code is recursive (gasp!) we must protect ourselves.
|
||||
*/
|
||||
if (level > XFS_DA_NODE_MAXDEPTH) {
|
||||
xfs_da_brelse(*trans, bp); /* no locks for later trans */
|
||||
xfs_trans_brelse(*trans, bp); /* no locks for later trans */
|
||||
return(XFS_ERROR(EIO));
|
||||
}
|
||||
|
||||
node = bp->data;
|
||||
node = bp->b_addr;
|
||||
ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
|
||||
parent_blkno = xfs_da_blkno(bp); /* save for re-read later */
|
||||
parent_blkno = XFS_BUF_ADDR(bp); /* save for re-read later */
|
||||
count = be16_to_cpu(node->hdr.count);
|
||||
if (!count) {
|
||||
xfs_da_brelse(*trans, bp);
|
||||
xfs_trans_brelse(*trans, bp);
|
||||
return(0);
|
||||
}
|
||||
child_fsb = be32_to_cpu(node->btree[0].before);
|
||||
xfs_da_brelse(*trans, bp); /* no locks for later trans */
|
||||
xfs_trans_brelse(*trans, bp); /* no locks for later trans */
|
||||
|
||||
/*
|
||||
* If this is the node level just above the leaves, simply loop
|
||||
|
@ -2803,12 +2821,12 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
|
|||
return(error);
|
||||
if (child_bp) {
|
||||
/* save for re-read later */
|
||||
child_blkno = xfs_da_blkno(child_bp);
|
||||
child_blkno = XFS_BUF_ADDR(child_bp);
|
||||
|
||||
/*
|
||||
* Invalidate the subtree, however we have to.
|
||||
*/
|
||||
info = child_bp->data;
|
||||
info = child_bp->b_addr;
|
||||
if (info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)) {
|
||||
error = xfs_attr_node_inactive(trans, dp,
|
||||
child_bp, level+1);
|
||||
|
@ -2817,7 +2835,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
|
|||
child_bp);
|
||||
} else {
|
||||
error = XFS_ERROR(EIO);
|
||||
xfs_da_brelse(*trans, child_bp);
|
||||
xfs_trans_brelse(*trans, child_bp);
|
||||
}
|
||||
if (error)
|
||||
return(error);
|
||||
|
@ -2830,7 +2848,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
|
|||
&child_bp, XFS_ATTR_FORK);
|
||||
if (error)
|
||||
return(error);
|
||||
xfs_da_binval(*trans, child_bp);
|
||||
xfs_trans_binval(*trans, child_bp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2843,7 +2861,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
|
|||
if (error)
|
||||
return(error);
|
||||
child_fsb = be32_to_cpu(node->btree[i+1].before);
|
||||
xfs_da_brelse(*trans, bp);
|
||||
xfs_trans_brelse(*trans, bp);
|
||||
}
|
||||
/*
|
||||
* Atomically commit the whole invalidate stuff.
|
||||
|
@ -2863,7 +2881,10 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
|
|||
* caught holding something that the logging code wants to flush to disk.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
|
||||
xfs_attr_leaf_inactive(
|
||||
struct xfs_trans **trans,
|
||||
struct xfs_inode *dp,
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
xfs_attr_leafblock_t *leaf;
|
||||
xfs_attr_leaf_entry_t *entry;
|
||||
|
@ -2871,7 +2892,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
|
|||
xfs_attr_inactive_list_t *list, *lp;
|
||||
int error, count, size, tmp, i;
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
|
||||
|
||||
/*
|
||||
|
@ -2892,7 +2913,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
|
|||
* If there are no "remote" values, we're done.
|
||||
*/
|
||||
if (count == 0) {
|
||||
xfs_da_brelse(*trans, bp);
|
||||
xfs_trans_brelse(*trans, bp);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -2919,7 +2940,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
|
|||
}
|
||||
}
|
||||
}
|
||||
xfs_da_brelse(*trans, bp); /* unlock for trans. in freextent() */
|
||||
xfs_trans_brelse(*trans, bp); /* unlock for trans. in freextent() */
|
||||
|
||||
/*
|
||||
* Invalidate each of the "remote" value extents.
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
struct attrlist;
|
||||
struct attrlist_cursor_kern;
|
||||
struct xfs_attr_list_context;
|
||||
struct xfs_dabuf;
|
||||
struct xfs_da_args;
|
||||
struct xfs_da_state;
|
||||
struct xfs_da_state_blk;
|
||||
|
@ -215,7 +214,7 @@ int xfs_attr_shortform_getvalue(struct xfs_da_args *args);
|
|||
int xfs_attr_shortform_to_leaf(struct xfs_da_args *args);
|
||||
int xfs_attr_shortform_remove(struct xfs_da_args *args);
|
||||
int xfs_attr_shortform_list(struct xfs_attr_list_context *context);
|
||||
int xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp);
|
||||
int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp);
|
||||
int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes);
|
||||
|
||||
|
||||
|
@ -223,7 +222,7 @@ int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes);
|
|||
* Internal routines when attribute fork size == XFS_LBSIZE(mp).
|
||||
*/
|
||||
int xfs_attr_leaf_to_node(struct xfs_da_args *args);
|
||||
int xfs_attr_leaf_to_shortform(struct xfs_dabuf *bp,
|
||||
int xfs_attr_leaf_to_shortform(struct xfs_buf *bp,
|
||||
struct xfs_da_args *args, int forkoff);
|
||||
int xfs_attr_leaf_clearflag(struct xfs_da_args *args);
|
||||
int xfs_attr_leaf_setflag(struct xfs_da_args *args);
|
||||
|
@ -235,14 +234,14 @@ int xfs_attr_leaf_flipflags(xfs_da_args_t *args);
|
|||
int xfs_attr_leaf_split(struct xfs_da_state *state,
|
||||
struct xfs_da_state_blk *oldblk,
|
||||
struct xfs_da_state_blk *newblk);
|
||||
int xfs_attr_leaf_lookup_int(struct xfs_dabuf *leaf,
|
||||
int xfs_attr_leaf_lookup_int(struct xfs_buf *leaf,
|
||||
struct xfs_da_args *args);
|
||||
int xfs_attr_leaf_getvalue(struct xfs_dabuf *bp, struct xfs_da_args *args);
|
||||
int xfs_attr_leaf_add(struct xfs_dabuf *leaf_buffer,
|
||||
int xfs_attr_leaf_getvalue(struct xfs_buf *bp, struct xfs_da_args *args);
|
||||
int xfs_attr_leaf_add(struct xfs_buf *leaf_buffer,
|
||||
struct xfs_da_args *args);
|
||||
int xfs_attr_leaf_remove(struct xfs_dabuf *leaf_buffer,
|
||||
int xfs_attr_leaf_remove(struct xfs_buf *leaf_buffer,
|
||||
struct xfs_da_args *args);
|
||||
int xfs_attr_leaf_list_int(struct xfs_dabuf *bp,
|
||||
int xfs_attr_leaf_list_int(struct xfs_buf *bp,
|
||||
struct xfs_attr_list_context *context);
|
||||
|
||||
/*
|
||||
|
@ -257,9 +256,9 @@ int xfs_attr_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp);
|
|||
/*
|
||||
* Utility routines.
|
||||
*/
|
||||
xfs_dahash_t xfs_attr_leaf_lasthash(struct xfs_dabuf *bp, int *count);
|
||||
int xfs_attr_leaf_order(struct xfs_dabuf *leaf1_bp,
|
||||
struct xfs_dabuf *leaf2_bp);
|
||||
xfs_dahash_t xfs_attr_leaf_lasthash(struct xfs_buf *bp, int *count);
|
||||
int xfs_attr_leaf_order(struct xfs_buf *leaf1_bp,
|
||||
struct xfs_buf *leaf2_bp);
|
||||
int xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize,
|
||||
int *local);
|
||||
#endif /* __XFS_ATTR_LEAF_H__ */
|
||||
|
|
|
@ -5517,7 +5517,7 @@ xfs_getbmap(
|
|||
if (xfs_get_extsz_hint(ip) ||
|
||||
ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
|
||||
prealloced = 1;
|
||||
fixlen = XFS_MAXIOFFSET(mp);
|
||||
fixlen = mp->m_super->s_maxbytes;
|
||||
} else {
|
||||
prealloced = 0;
|
||||
fixlen = XFS_ISIZE(ip);
|
||||
|
|
240
fs/xfs/xfs_buf.c
240
fs/xfs/xfs_buf.c
|
@ -164,14 +164,49 @@ xfs_buf_stale(
|
|||
ASSERT(atomic_read(&bp->b_hold) >= 1);
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_buf_get_maps(
|
||||
struct xfs_buf *bp,
|
||||
int map_count)
|
||||
{
|
||||
ASSERT(bp->b_maps == NULL);
|
||||
bp->b_map_count = map_count;
|
||||
|
||||
if (map_count == 1) {
|
||||
bp->b_maps = &bp->b_map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bp->b_maps = kmem_zalloc(map_count * sizeof(struct xfs_buf_map),
|
||||
KM_NOFS);
|
||||
if (!bp->b_maps)
|
||||
return ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees b_pages if it was allocated.
|
||||
*/
|
||||
static void
|
||||
xfs_buf_free_maps(
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
if (bp->b_maps != &bp->b_map) {
|
||||
kmem_free(bp->b_maps);
|
||||
bp->b_maps = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct xfs_buf *
|
||||
xfs_buf_alloc(
|
||||
_xfs_buf_alloc(
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps,
|
||||
xfs_buf_flags_t flags)
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
bp = kmem_zone_zalloc(xfs_buf_zone, KM_NOFS);
|
||||
if (unlikely(!bp))
|
||||
|
@ -192,16 +227,28 @@ xfs_buf_alloc(
|
|||
sema_init(&bp->b_sema, 0); /* held, no waiters */
|
||||
XB_SET_OWNER(bp);
|
||||
bp->b_target = target;
|
||||
bp->b_flags = flags;
|
||||
|
||||
/*
|
||||
* Set length and io_length to the same value initially.
|
||||
* I/O routines should use io_length, which will be the same in
|
||||
* most cases but may be reset (e.g. XFS recovery).
|
||||
*/
|
||||
bp->b_length = numblks;
|
||||
bp->b_io_length = numblks;
|
||||
bp->b_flags = flags;
|
||||
bp->b_bn = blkno;
|
||||
error = xfs_buf_get_maps(bp, nmaps);
|
||||
if (error) {
|
||||
kmem_zone_free(xfs_buf_zone, bp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bp->b_bn = map[0].bm_bn;
|
||||
bp->b_length = 0;
|
||||
for (i = 0; i < nmaps; i++) {
|
||||
bp->b_maps[i].bm_bn = map[i].bm_bn;
|
||||
bp->b_maps[i].bm_len = map[i].bm_len;
|
||||
bp->b_length += map[i].bm_len;
|
||||
}
|
||||
bp->b_io_length = bp->b_length;
|
||||
|
||||
atomic_set(&bp->b_pin_count, 0);
|
||||
init_waitqueue_head(&bp->b_waiters);
|
||||
|
||||
|
@ -280,6 +327,7 @@ xfs_buf_free(
|
|||
} else if (bp->b_flags & _XBF_KMEM)
|
||||
kmem_free(bp->b_addr);
|
||||
_xfs_buf_free_pages(bp);
|
||||
xfs_buf_free_maps(bp);
|
||||
kmem_zone_free(xfs_buf_zone, bp);
|
||||
}
|
||||
|
||||
|
@ -327,8 +375,9 @@ xfs_buf_allocate_memory(
|
|||
}
|
||||
|
||||
use_alloc_page:
|
||||
start = BBTOB(bp->b_bn) >> PAGE_SHIFT;
|
||||
end = (BBTOB(bp->b_bn + bp->b_length) + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
start = BBTOB(bp->b_map.bm_bn) >> PAGE_SHIFT;
|
||||
end = (BBTOB(bp->b_map.bm_bn + bp->b_length) + PAGE_SIZE - 1)
|
||||
>> PAGE_SHIFT;
|
||||
page_count = end - start;
|
||||
error = _xfs_buf_get_pages(bp, page_count, flags);
|
||||
if (unlikely(error))
|
||||
|
@ -425,8 +474,8 @@ _xfs_buf_map_pages(
|
|||
xfs_buf_t *
|
||||
_xfs_buf_find(
|
||||
struct xfs_buftarg *btp,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps,
|
||||
xfs_buf_flags_t flags,
|
||||
xfs_buf_t *new_bp)
|
||||
{
|
||||
|
@ -435,7 +484,12 @@ _xfs_buf_find(
|
|||
struct rb_node **rbp;
|
||||
struct rb_node *parent;
|
||||
xfs_buf_t *bp;
|
||||
xfs_daddr_t blkno = map[0].bm_bn;
|
||||
int numblks = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nmaps; i++)
|
||||
numblks += map[i].bm_len;
|
||||
numbytes = BBTOB(numblks);
|
||||
|
||||
/* Check for IOs smaller than the sector size / not sector aligned */
|
||||
|
@ -527,31 +581,31 @@ found:
|
|||
* more hits than misses.
|
||||
*/
|
||||
struct xfs_buf *
|
||||
xfs_buf_get(
|
||||
xfs_buftarg_t *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks,
|
||||
xfs_buf_get_map(
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps,
|
||||
xfs_buf_flags_t flags)
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
struct xfs_buf *new_bp;
|
||||
int error = 0;
|
||||
|
||||
bp = _xfs_buf_find(target, blkno, numblks, flags, NULL);
|
||||
bp = _xfs_buf_find(target, map, nmaps, flags, NULL);
|
||||
if (likely(bp))
|
||||
goto found;
|
||||
|
||||
new_bp = xfs_buf_alloc(target, blkno, numblks, flags);
|
||||
new_bp = _xfs_buf_alloc(target, map, nmaps, flags);
|
||||
if (unlikely(!new_bp))
|
||||
return NULL;
|
||||
|
||||
error = xfs_buf_allocate_memory(new_bp, flags);
|
||||
if (error) {
|
||||
kmem_zone_free(xfs_buf_zone, new_bp);
|
||||
xfs_buf_free(new_bp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bp = _xfs_buf_find(target, blkno, numblks, flags, new_bp);
|
||||
bp = _xfs_buf_find(target, map, nmaps, flags, new_bp);
|
||||
if (!bp) {
|
||||
xfs_buf_free(new_bp);
|
||||
return NULL;
|
||||
|
@ -560,8 +614,6 @@ xfs_buf_get(
|
|||
if (bp != new_bp)
|
||||
xfs_buf_free(new_bp);
|
||||
|
||||
bp->b_io_length = bp->b_length;
|
||||
|
||||
found:
|
||||
if (!bp->b_addr) {
|
||||
error = _xfs_buf_map_pages(bp, flags);
|
||||
|
@ -584,7 +636,7 @@ _xfs_buf_read(
|
|||
xfs_buf_flags_t flags)
|
||||
{
|
||||
ASSERT(!(flags & XBF_WRITE));
|
||||
ASSERT(bp->b_bn != XFS_BUF_DADDR_NULL);
|
||||
ASSERT(bp->b_map.bm_bn != XFS_BUF_DADDR_NULL);
|
||||
|
||||
bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD);
|
||||
bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD);
|
||||
|
@ -596,17 +648,17 @@ _xfs_buf_read(
|
|||
}
|
||||
|
||||
xfs_buf_t *
|
||||
xfs_buf_read(
|
||||
xfs_buftarg_t *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks,
|
||||
xfs_buf_read_map(
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps,
|
||||
xfs_buf_flags_t flags)
|
||||
{
|
||||
xfs_buf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
|
||||
flags |= XBF_READ;
|
||||
|
||||
bp = xfs_buf_get(target, blkno, numblks, flags);
|
||||
bp = xfs_buf_get_map(target, map, nmaps, flags);
|
||||
if (bp) {
|
||||
trace_xfs_buf_read(bp, flags, _RET_IP_);
|
||||
|
||||
|
@ -634,15 +686,15 @@ xfs_buf_read(
|
|||
* safe manner.
|
||||
*/
|
||||
void
|
||||
xfs_buf_readahead(
|
||||
xfs_buftarg_t *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks)
|
||||
xfs_buf_readahead_map(
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps)
|
||||
{
|
||||
if (bdi_read_congested(target->bt_bdi))
|
||||
return;
|
||||
|
||||
xfs_buf_read(target, blkno, numblks,
|
||||
xfs_buf_read_map(target, map, nmaps,
|
||||
XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD);
|
||||
}
|
||||
|
||||
|
@ -665,8 +717,10 @@ xfs_buf_read_uncached(
|
|||
return NULL;
|
||||
|
||||
/* set up the buffer for a read IO */
|
||||
XFS_BUF_SET_ADDR(bp, daddr);
|
||||
XFS_BUF_READ(bp);
|
||||
ASSERT(bp->b_map_count == 1);
|
||||
bp->b_bn = daddr;
|
||||
bp->b_maps[0].bm_bn = daddr;
|
||||
bp->b_flags |= XBF_READ;
|
||||
|
||||
xfsbdstrat(target->bt_mount, bp);
|
||||
error = xfs_buf_iowait(bp);
|
||||
|
@ -694,7 +748,11 @@ xfs_buf_set_empty(
|
|||
bp->b_addr = NULL;
|
||||
bp->b_length = numblks;
|
||||
bp->b_io_length = numblks;
|
||||
|
||||
ASSERT(bp->b_map_count == 1);
|
||||
bp->b_bn = XFS_BUF_DADDR_NULL;
|
||||
bp->b_maps[0].bm_bn = XFS_BUF_DADDR_NULL;
|
||||
bp->b_maps[0].bm_len = bp->b_length;
|
||||
}
|
||||
|
||||
static inline struct page *
|
||||
|
@ -758,9 +816,10 @@ xfs_buf_get_uncached(
|
|||
{
|
||||
unsigned long page_count;
|
||||
int error, i;
|
||||
xfs_buf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
DEFINE_SINGLE_BUF_MAP(map, XFS_BUF_DADDR_NULL, numblks);
|
||||
|
||||
bp = xfs_buf_alloc(target, XFS_BUF_DADDR_NULL, numblks, 0);
|
||||
bp = _xfs_buf_alloc(target, &map, 1, 0);
|
||||
if (unlikely(bp == NULL))
|
||||
goto fail;
|
||||
|
||||
|
@ -791,6 +850,7 @@ xfs_buf_get_uncached(
|
|||
__free_page(bp->b_pages[i]);
|
||||
_xfs_buf_free_pages(bp);
|
||||
fail_free_buf:
|
||||
xfs_buf_free_maps(bp);
|
||||
kmem_zone_free(xfs_buf_zone, bp);
|
||||
fail:
|
||||
return NULL;
|
||||
|
@ -1144,36 +1204,39 @@ xfs_buf_bio_end_io(
|
|||
bio_put(bio);
|
||||
}
|
||||
|
||||
STATIC void
|
||||
_xfs_buf_ioapply(
|
||||
xfs_buf_t *bp)
|
||||
static void
|
||||
xfs_buf_ioapply_map(
|
||||
struct xfs_buf *bp,
|
||||
int map,
|
||||
int *buf_offset,
|
||||
int *count,
|
||||
int rw)
|
||||
{
|
||||
int rw, map_i, total_nr_pages, nr_pages;
|
||||
struct bio *bio;
|
||||
int offset = bp->b_offset;
|
||||
int size = BBTOB(bp->b_io_length);
|
||||
sector_t sector = bp->b_bn;
|
||||
int page_index;
|
||||
int total_nr_pages = bp->b_page_count;
|
||||
int nr_pages;
|
||||
struct bio *bio;
|
||||
sector_t sector = bp->b_maps[map].bm_bn;
|
||||
int size;
|
||||
int offset;
|
||||
|
||||
total_nr_pages = bp->b_page_count;
|
||||
map_i = 0;
|
||||
|
||||
if (bp->b_flags & XBF_WRITE) {
|
||||
if (bp->b_flags & XBF_SYNCIO)
|
||||
rw = WRITE_SYNC;
|
||||
else
|
||||
rw = WRITE;
|
||||
if (bp->b_flags & XBF_FUA)
|
||||
rw |= REQ_FUA;
|
||||
if (bp->b_flags & XBF_FLUSH)
|
||||
rw |= REQ_FLUSH;
|
||||
} else if (bp->b_flags & XBF_READ_AHEAD) {
|
||||
rw = READA;
|
||||
} else {
|
||||
rw = READ;
|
||||
/* skip the pages in the buffer before the start offset */
|
||||
page_index = 0;
|
||||
offset = *buf_offset;
|
||||
while (offset >= PAGE_SIZE) {
|
||||
page_index++;
|
||||
offset -= PAGE_SIZE;
|
||||
}
|
||||
|
||||
/* we only use the buffer cache for meta-data */
|
||||
rw |= REQ_META;
|
||||
/*
|
||||
* Limit the IO size to the length of the current vector, and update the
|
||||
* remaining IO count for the next time around.
|
||||
*/
|
||||
size = min_t(int, BBTOB(bp->b_maps[map].bm_len), *count);
|
||||
*count -= size;
|
||||
*buf_offset += size;
|
||||
|
||||
next_chunk:
|
||||
atomic_inc(&bp->b_io_remaining);
|
||||
|
@ -1188,13 +1251,14 @@ next_chunk:
|
|||
bio->bi_private = bp;
|
||||
|
||||
|
||||
for (; size && nr_pages; nr_pages--, map_i++) {
|
||||
for (; size && nr_pages; nr_pages--, page_index++) {
|
||||
int rbytes, nbytes = PAGE_SIZE - offset;
|
||||
|
||||
if (nbytes > size)
|
||||
nbytes = size;
|
||||
|
||||
rbytes = bio_add_page(bio, bp->b_pages[map_i], nbytes, offset);
|
||||
rbytes = bio_add_page(bio, bp->b_pages[page_index], nbytes,
|
||||
offset);
|
||||
if (rbytes < nbytes)
|
||||
break;
|
||||
|
||||
|
@ -1216,6 +1280,54 @@ next_chunk:
|
|||
xfs_buf_ioerror(bp, EIO);
|
||||
bio_put(bio);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
STATIC void
|
||||
_xfs_buf_ioapply(
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
struct blk_plug plug;
|
||||
int rw;
|
||||
int offset;
|
||||
int size;
|
||||
int i;
|
||||
|
||||
if (bp->b_flags & XBF_WRITE) {
|
||||
if (bp->b_flags & XBF_SYNCIO)
|
||||
rw = WRITE_SYNC;
|
||||
else
|
||||
rw = WRITE;
|
||||
if (bp->b_flags & XBF_FUA)
|
||||
rw |= REQ_FUA;
|
||||
if (bp->b_flags & XBF_FLUSH)
|
||||
rw |= REQ_FLUSH;
|
||||
} else if (bp->b_flags & XBF_READ_AHEAD) {
|
||||
rw = READA;
|
||||
} else {
|
||||
rw = READ;
|
||||
}
|
||||
|
||||
/* we only use the buffer cache for meta-data */
|
||||
rw |= REQ_META;
|
||||
|
||||
/*
|
||||
* Walk all the vectors issuing IO on them. Set up the initial offset
|
||||
* into the buffer and the desired IO size before we start -
|
||||
* _xfs_buf_ioapply_vec() will modify them appropriately for each
|
||||
* subsequent call.
|
||||
*/
|
||||
offset = bp->b_offset;
|
||||
size = BBTOB(bp->b_io_length);
|
||||
blk_start_plug(&plug);
|
||||
for (i = 0; i < bp->b_map_count; i++) {
|
||||
xfs_buf_ioapply_map(bp, i, &offset, &size, rw);
|
||||
if (bp->b_error)
|
||||
break;
|
||||
if (size <= 0)
|
||||
break; /* all done */
|
||||
}
|
||||
blk_finish_plug(&plug);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1557,7 +1669,7 @@ xfs_buf_cmp(
|
|||
struct xfs_buf *bp = container_of(b, struct xfs_buf, b_list);
|
||||
xfs_daddr_t diff;
|
||||
|
||||
diff = ap->b_bn - bp->b_bn;
|
||||
diff = ap->b_map.bm_bn - bp->b_map.bm_bn;
|
||||
if (diff < 0)
|
||||
return -1;
|
||||
if (diff > 0)
|
||||
|
|
114
fs/xfs/xfs_buf.h
114
fs/xfs/xfs_buf.h
|
@ -58,6 +58,7 @@ typedef enum {
|
|||
#define _XBF_PAGES (1 << 20)/* backed by refcounted pages */
|
||||
#define _XBF_KMEM (1 << 21)/* backed by heap memory */
|
||||
#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */
|
||||
#define _XBF_COMPOUND (1 << 23)/* compound buffer */
|
||||
|
||||
typedef unsigned int xfs_buf_flags_t;
|
||||
|
||||
|
@ -75,7 +76,8 @@ typedef unsigned int xfs_buf_flags_t;
|
|||
{ XBF_UNMAPPED, "UNMAPPED" }, /* ditto */\
|
||||
{ _XBF_PAGES, "PAGES" }, \
|
||||
{ _XBF_KMEM, "KMEM" }, \
|
||||
{ _XBF_DELWRI_Q, "DELWRI_Q" }
|
||||
{ _XBF_DELWRI_Q, "DELWRI_Q" }, \
|
||||
{ _XBF_COMPOUND, "COMPOUND" }
|
||||
|
||||
typedef struct xfs_buftarg {
|
||||
dev_t bt_dev;
|
||||
|
@ -98,6 +100,14 @@ typedef void (*xfs_buf_iodone_t)(struct xfs_buf *);
|
|||
|
||||
#define XB_PAGES 2
|
||||
|
||||
struct xfs_buf_map {
|
||||
xfs_daddr_t bm_bn; /* block number for I/O */
|
||||
int bm_len; /* size of I/O */
|
||||
};
|
||||
|
||||
#define DEFINE_SINGLE_BUF_MAP(map, blkno, numblk) \
|
||||
struct xfs_buf_map (map) = { .bm_bn = (blkno), .bm_len = (numblk) };
|
||||
|
||||
typedef struct xfs_buf {
|
||||
/*
|
||||
* first cacheline holds all the fields needed for an uncontended cache
|
||||
|
@ -107,7 +117,7 @@ typedef struct xfs_buf {
|
|||
* fast-path on locking.
|
||||
*/
|
||||
struct rb_node b_rbnode; /* rbtree node */
|
||||
xfs_daddr_t b_bn; /* block number for I/O */
|
||||
xfs_daddr_t b_bn; /* block number of buffer */
|
||||
int b_length; /* size of buffer in BBs */
|
||||
atomic_t b_hold; /* reference count */
|
||||
atomic_t b_lru_ref; /* lru reclaim ref count */
|
||||
|
@ -127,12 +137,16 @@ typedef struct xfs_buf {
|
|||
struct xfs_trans *b_transp;
|
||||
struct page **b_pages; /* array of page pointers */
|
||||
struct page *b_page_array[XB_PAGES]; /* inline pages */
|
||||
struct xfs_buf_map *b_maps; /* compound buffer map */
|
||||
struct xfs_buf_map b_map; /* inline compound buffer map */
|
||||
int b_map_count;
|
||||
int b_io_length; /* IO size in BBs */
|
||||
atomic_t b_pin_count; /* pin count */
|
||||
atomic_t b_io_remaining; /* #outstanding I/O requests */
|
||||
unsigned int b_page_count; /* size of page array */
|
||||
unsigned int b_offset; /* page offset in first page */
|
||||
unsigned short b_error; /* error code on I/O */
|
||||
|
||||
#ifdef XFS_BUF_LOCK_TRACKING
|
||||
int b_last_holder;
|
||||
#endif
|
||||
|
@ -140,22 +154,78 @@ typedef struct xfs_buf {
|
|||
|
||||
|
||||
/* Finding and Reading Buffers */
|
||||
struct xfs_buf *_xfs_buf_find(struct xfs_buftarg *target, xfs_daddr_t blkno,
|
||||
size_t numblks, xfs_buf_flags_t flags,
|
||||
struct xfs_buf *new_bp);
|
||||
#define xfs_incore(buftarg,blkno,len,lockit) \
|
||||
_xfs_buf_find(buftarg, blkno ,len, lockit, NULL)
|
||||
struct xfs_buf *_xfs_buf_find(struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps,
|
||||
xfs_buf_flags_t flags, struct xfs_buf *new_bp);
|
||||
|
||||
struct xfs_buf *xfs_buf_get(struct xfs_buftarg *target, xfs_daddr_t blkno,
|
||||
size_t numblks, xfs_buf_flags_t flags);
|
||||
struct xfs_buf *xfs_buf_read(struct xfs_buftarg *target, xfs_daddr_t blkno,
|
||||
size_t numblks, xfs_buf_flags_t flags);
|
||||
void xfs_buf_readahead(struct xfs_buftarg *target, xfs_daddr_t blkno,
|
||||
size_t numblks);
|
||||
static inline struct xfs_buf *
|
||||
xfs_incore(
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks,
|
||||
xfs_buf_flags_t flags)
|
||||
{
|
||||
DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
|
||||
return _xfs_buf_find(target, &map, 1, flags, NULL);
|
||||
}
|
||||
|
||||
struct xfs_buf *_xfs_buf_alloc(struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps,
|
||||
xfs_buf_flags_t flags);
|
||||
|
||||
static inline struct xfs_buf *
|
||||
xfs_buf_alloc(
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks,
|
||||
xfs_buf_flags_t flags)
|
||||
{
|
||||
DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
|
||||
return _xfs_buf_alloc(target, &map, 1, flags);
|
||||
}
|
||||
|
||||
struct xfs_buf *xfs_buf_get_map(struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps,
|
||||
xfs_buf_flags_t flags);
|
||||
struct xfs_buf *xfs_buf_read_map(struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps,
|
||||
xfs_buf_flags_t flags);
|
||||
void xfs_buf_readahead_map(struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps);
|
||||
|
||||
static inline struct xfs_buf *
|
||||
xfs_buf_get(
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks,
|
||||
xfs_buf_flags_t flags)
|
||||
{
|
||||
DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
|
||||
return xfs_buf_get_map(target, &map, 1, flags);
|
||||
}
|
||||
|
||||
static inline struct xfs_buf *
|
||||
xfs_buf_read(
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks,
|
||||
xfs_buf_flags_t flags)
|
||||
{
|
||||
DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
|
||||
return xfs_buf_read_map(target, &map, 1, flags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
xfs_buf_readahead(
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks)
|
||||
{
|
||||
DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
|
||||
return xfs_buf_readahead_map(target, &map, 1);
|
||||
}
|
||||
|
||||
struct xfs_buf *xfs_buf_get_empty(struct xfs_buftarg *target, size_t numblks);
|
||||
struct xfs_buf *xfs_buf_alloc(struct xfs_buftarg *target, xfs_daddr_t blkno,
|
||||
size_t numblks, xfs_buf_flags_t flags);
|
||||
void xfs_buf_set_empty(struct xfs_buf *bp, size_t numblks);
|
||||
int xfs_buf_associate_memory(struct xfs_buf *bp, void *mem, size_t length);
|
||||
|
||||
|
@ -232,8 +302,18 @@ void xfs_buf_stale(struct xfs_buf *bp);
|
|||
#define XFS_BUF_UNWRITE(bp) ((bp)->b_flags &= ~XBF_WRITE)
|
||||
#define XFS_BUF_ISWRITE(bp) ((bp)->b_flags & XBF_WRITE)
|
||||
|
||||
#define XFS_BUF_ADDR(bp) ((bp)->b_bn)
|
||||
#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_bn = (xfs_daddr_t)(bno))
|
||||
/*
|
||||
* These macros use the IO block map rather than b_bn. b_bn is now really
|
||||
* just for the buffer cache index for cached buffers. As IO does not use b_bn
|
||||
* anymore, uncached buffers do not use b_bn at all and hence must modify the IO
|
||||
* map directly. Uncached buffers are not allowed to be discontiguous, so this
|
||||
* is safe to do.
|
||||
*
|
||||
* In future, uncached buffers will pass the block number directly to the io
|
||||
* request function and hence these macros will go away at that point.
|
||||
*/
|
||||
#define XFS_BUF_ADDR(bp) ((bp)->b_map.bm_bn)
|
||||
#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_map.bm_bn = (xfs_daddr_t)(bno))
|
||||
|
||||
static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref)
|
||||
{
|
||||
|
|
|
@ -153,33 +153,25 @@ STATIC void xfs_buf_do_callbacks(struct xfs_buf *bp);
|
|||
* If the XFS_BLI_STALE flag has been set, then log nothing.
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_buf_item_size(
|
||||
struct xfs_log_item *lip)
|
||||
xfs_buf_item_size_segment(
|
||||
struct xfs_buf_log_item *bip,
|
||||
struct xfs_buf_log_format *blfp)
|
||||
{
|
||||
struct xfs_buf_log_item *bip = BUF_ITEM(lip);
|
||||
struct xfs_buf *bp = bip->bli_buf;
|
||||
uint nvecs;
|
||||
int next_bit;
|
||||
int last_bit;
|
||||
|
||||
ASSERT(atomic_read(&bip->bli_refcount) > 0);
|
||||
if (bip->bli_flags & XFS_BLI_STALE) {
|
||||
/*
|
||||
* The buffer is stale, so all we need to log
|
||||
* is the buf log format structure with the
|
||||
* cancel flag in it.
|
||||
*/
|
||||
trace_xfs_buf_item_size_stale(bip);
|
||||
ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
|
||||
return 1;
|
||||
}
|
||||
last_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0);
|
||||
if (last_bit == -1)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* initial count for a dirty buffer is 2 vectors - the format structure
|
||||
* and the first dirty region.
|
||||
*/
|
||||
nvecs = 2;
|
||||
|
||||
ASSERT(bip->bli_flags & XFS_BLI_LOGGED);
|
||||
nvecs = 1;
|
||||
last_bit = xfs_next_bit(bip->bli_format.blf_data_map,
|
||||
bip->bli_format.blf_map_size, 0);
|
||||
ASSERT(last_bit != -1);
|
||||
nvecs++;
|
||||
while (last_bit != -1) {
|
||||
/*
|
||||
* This takes the bit number to start looking from and
|
||||
|
@ -187,16 +179,15 @@ xfs_buf_item_size(
|
|||
* if there are no more bits set or the start bit is
|
||||
* beyond the end of the bitmap.
|
||||
*/
|
||||
next_bit = xfs_next_bit(bip->bli_format.blf_data_map,
|
||||
bip->bli_format.blf_map_size,
|
||||
last_bit + 1);
|
||||
next_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size,
|
||||
last_bit + 1);
|
||||
/*
|
||||
* If we run out of bits, leave the loop,
|
||||
* else if we find a new set of bits bump the number of vecs,
|
||||
* else keep scanning the current set of bits.
|
||||
*/
|
||||
if (next_bit == -1) {
|
||||
last_bit = -1;
|
||||
break;
|
||||
} else if (next_bit != last_bit + 1) {
|
||||
last_bit = next_bit;
|
||||
nvecs++;
|
||||
|
@ -210,10 +201,180 @@ xfs_buf_item_size(
|
|||
}
|
||||
}
|
||||
|
||||
return nvecs;
|
||||
}
|
||||
|
||||
/*
|
||||
* This returns the number of log iovecs needed to log the given buf log item.
|
||||
*
|
||||
* It calculates this as 1 iovec for the buf log format structure and 1 for each
|
||||
* stretch of non-contiguous chunks to be logged. Contiguous chunks are logged
|
||||
* in a single iovec.
|
||||
*
|
||||
* Discontiguous buffers need a format structure per region that that is being
|
||||
* logged. This makes the changes in the buffer appear to log recovery as though
|
||||
* they came from separate buffers, just like would occur if multiple buffers
|
||||
* were used instead of a single discontiguous buffer. This enables
|
||||
* discontiguous buffers to be in-memory constructs, completely transparent to
|
||||
* what ends up on disk.
|
||||
*
|
||||
* If the XFS_BLI_STALE flag has been set, then log nothing but the buf log
|
||||
* format structures.
|
||||
*/
|
||||
STATIC uint
|
||||
xfs_buf_item_size(
|
||||
struct xfs_log_item *lip)
|
||||
{
|
||||
struct xfs_buf_log_item *bip = BUF_ITEM(lip);
|
||||
uint nvecs;
|
||||
int i;
|
||||
|
||||
ASSERT(atomic_read(&bip->bli_refcount) > 0);
|
||||
if (bip->bli_flags & XFS_BLI_STALE) {
|
||||
/*
|
||||
* The buffer is stale, so all we need to log
|
||||
* is the buf log format structure with the
|
||||
* cancel flag in it.
|
||||
*/
|
||||
trace_xfs_buf_item_size_stale(bip);
|
||||
ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
|
||||
return bip->bli_format_count;
|
||||
}
|
||||
|
||||
ASSERT(bip->bli_flags & XFS_BLI_LOGGED);
|
||||
|
||||
/*
|
||||
* the vector count is based on the number of buffer vectors we have
|
||||
* dirty bits in. This will only be greater than one when we have a
|
||||
* compound buffer with more than one segment dirty. Hence for compound
|
||||
* buffers we need to track which segment the dirty bits correspond to,
|
||||
* and when we move from one segment to the next increment the vector
|
||||
* count for the extra buf log format structure that will need to be
|
||||
* written.
|
||||
*/
|
||||
nvecs = 0;
|
||||
for (i = 0; i < bip->bli_format_count; i++) {
|
||||
nvecs += xfs_buf_item_size_segment(bip, &bip->bli_formats[i]);
|
||||
}
|
||||
|
||||
trace_xfs_buf_item_size(bip);
|
||||
return nvecs;
|
||||
}
|
||||
|
||||
static struct xfs_log_iovec *
|
||||
xfs_buf_item_format_segment(
|
||||
struct xfs_buf_log_item *bip,
|
||||
struct xfs_log_iovec *vecp,
|
||||
uint offset,
|
||||
struct xfs_buf_log_format *blfp)
|
||||
{
|
||||
struct xfs_buf *bp = bip->bli_buf;
|
||||
uint base_size;
|
||||
uint nvecs;
|
||||
int first_bit;
|
||||
int last_bit;
|
||||
int next_bit;
|
||||
uint nbits;
|
||||
uint buffer_offset;
|
||||
|
||||
/* copy the flags across from the base format item */
|
||||
blfp->blf_flags = bip->bli_format.blf_flags;
|
||||
|
||||
/*
|
||||
* Base size is the actual size of the ondisk structure - it reflects
|
||||
* the actual size of the dirty bitmap rather than the size of the in
|
||||
* memory structure.
|
||||
*/
|
||||
base_size = offsetof(struct xfs_buf_log_format, blf_data_map) +
|
||||
(blfp->blf_map_size * sizeof(blfp->blf_data_map[0]));
|
||||
vecp->i_addr = blfp;
|
||||
vecp->i_len = base_size;
|
||||
vecp->i_type = XLOG_REG_TYPE_BFORMAT;
|
||||
vecp++;
|
||||
nvecs = 1;
|
||||
|
||||
if (bip->bli_flags & XFS_BLI_STALE) {
|
||||
/*
|
||||
* The buffer is stale, so all we need to log
|
||||
* is the buf log format structure with the
|
||||
* cancel flag in it.
|
||||
*/
|
||||
trace_xfs_buf_item_format_stale(bip);
|
||||
ASSERT(blfp->blf_flags & XFS_BLF_CANCEL);
|
||||
blfp->blf_size = nvecs;
|
||||
return vecp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in an iovec for each set of contiguous chunks.
|
||||
*/
|
||||
first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0);
|
||||
ASSERT(first_bit != -1);
|
||||
last_bit = first_bit;
|
||||
nbits = 1;
|
||||
for (;;) {
|
||||
/*
|
||||
* This takes the bit number to start looking from and
|
||||
* returns the next set bit from there. It returns -1
|
||||
* if there are no more bits set or the start bit is
|
||||
* beyond the end of the bitmap.
|
||||
*/
|
||||
next_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size,
|
||||
(uint)last_bit + 1);
|
||||
/*
|
||||
* If we run out of bits fill in the last iovec and get
|
||||
* out of the loop.
|
||||
* Else if we start a new set of bits then fill in the
|
||||
* iovec for the series we were looking at and start
|
||||
* counting the bits in the new one.
|
||||
* Else we're still in the same set of bits so just
|
||||
* keep counting and scanning.
|
||||
*/
|
||||
if (next_bit == -1) {
|
||||
buffer_offset = offset + first_bit * XFS_BLF_CHUNK;
|
||||
vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
|
||||
vecp->i_len = nbits * XFS_BLF_CHUNK;
|
||||
vecp->i_type = XLOG_REG_TYPE_BCHUNK;
|
||||
nvecs++;
|
||||
break;
|
||||
} else if (next_bit != last_bit + 1) {
|
||||
buffer_offset = offset + first_bit * XFS_BLF_CHUNK;
|
||||
vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
|
||||
vecp->i_len = nbits * XFS_BLF_CHUNK;
|
||||
vecp->i_type = XLOG_REG_TYPE_BCHUNK;
|
||||
nvecs++;
|
||||
vecp++;
|
||||
first_bit = next_bit;
|
||||
last_bit = next_bit;
|
||||
nbits = 1;
|
||||
} else if (xfs_buf_offset(bp, offset +
|
||||
(next_bit << XFS_BLF_SHIFT)) !=
|
||||
(xfs_buf_offset(bp, offset +
|
||||
(last_bit << XFS_BLF_SHIFT)) +
|
||||
XFS_BLF_CHUNK)) {
|
||||
buffer_offset = offset + first_bit * XFS_BLF_CHUNK;
|
||||
vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
|
||||
vecp->i_len = nbits * XFS_BLF_CHUNK;
|
||||
vecp->i_type = XLOG_REG_TYPE_BCHUNK;
|
||||
/*
|
||||
* You would think we need to bump the nvecs here too, but we do not
|
||||
* this number is used by recovery, and it gets confused by the boundary
|
||||
* split here
|
||||
* nvecs++;
|
||||
*/
|
||||
vecp++;
|
||||
first_bit = next_bit;
|
||||
last_bit = next_bit;
|
||||
nbits = 1;
|
||||
} else {
|
||||
last_bit++;
|
||||
nbits++;
|
||||
}
|
||||
}
|
||||
bip->bli_format.blf_size = nvecs;
|
||||
return vecp;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called to fill in the vector of log iovecs for the
|
||||
* given log buf item. It fills the first entry with a buf log
|
||||
|
@ -226,35 +387,14 @@ xfs_buf_item_format(
|
|||
struct xfs_log_iovec *vecp)
|
||||
{
|
||||
struct xfs_buf_log_item *bip = BUF_ITEM(lip);
|
||||
struct xfs_buf *bp = bip->bli_buf;
|
||||
uint base_size;
|
||||
uint nvecs;
|
||||
int first_bit;
|
||||
int last_bit;
|
||||
int next_bit;
|
||||
uint nbits;
|
||||
uint buffer_offset;
|
||||
struct xfs_buf *bp = bip->bli_buf;
|
||||
uint offset = 0;
|
||||
int i;
|
||||
|
||||
ASSERT(atomic_read(&bip->bli_refcount) > 0);
|
||||
ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||
|
||||
(bip->bli_flags & XFS_BLI_STALE));
|
||||
|
||||
/*
|
||||
* The size of the base structure is the size of the
|
||||
* declared structure plus the space for the extra words
|
||||
* of the bitmap. We subtract one from the map size, because
|
||||
* the first element of the bitmap is accounted for in the
|
||||
* size of the base structure.
|
||||
*/
|
||||
base_size =
|
||||
(uint)(sizeof(xfs_buf_log_format_t) +
|
||||
((bip->bli_format.blf_map_size - 1) * sizeof(uint)));
|
||||
vecp->i_addr = &bip->bli_format;
|
||||
vecp->i_len = base_size;
|
||||
vecp->i_type = XLOG_REG_TYPE_BFORMAT;
|
||||
vecp++;
|
||||
nvecs = 1;
|
||||
|
||||
/*
|
||||
* If it is an inode buffer, transfer the in-memory state to the
|
||||
* format flags and clear the in-memory state. We do not transfer
|
||||
|
@ -269,85 +409,12 @@ xfs_buf_item_format(
|
|||
bip->bli_flags &= ~XFS_BLI_INODE_BUF;
|
||||
}
|
||||
|
||||
if (bip->bli_flags & XFS_BLI_STALE) {
|
||||
/*
|
||||
* The buffer is stale, so all we need to log
|
||||
* is the buf log format structure with the
|
||||
* cancel flag in it.
|
||||
*/
|
||||
trace_xfs_buf_item_format_stale(bip);
|
||||
ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
|
||||
bip->bli_format.blf_size = nvecs;
|
||||
return;
|
||||
for (i = 0; i < bip->bli_format_count; i++) {
|
||||
vecp = xfs_buf_item_format_segment(bip, vecp, offset,
|
||||
&bip->bli_formats[i]);
|
||||
offset += bp->b_maps[i].bm_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in an iovec for each set of contiguous chunks.
|
||||
*/
|
||||
first_bit = xfs_next_bit(bip->bli_format.blf_data_map,
|
||||
bip->bli_format.blf_map_size, 0);
|
||||
ASSERT(first_bit != -1);
|
||||
last_bit = first_bit;
|
||||
nbits = 1;
|
||||
for (;;) {
|
||||
/*
|
||||
* This takes the bit number to start looking from and
|
||||
* returns the next set bit from there. It returns -1
|
||||
* if there are no more bits set or the start bit is
|
||||
* beyond the end of the bitmap.
|
||||
*/
|
||||
next_bit = xfs_next_bit(bip->bli_format.blf_data_map,
|
||||
bip->bli_format.blf_map_size,
|
||||
(uint)last_bit + 1);
|
||||
/*
|
||||
* If we run out of bits fill in the last iovec and get
|
||||
* out of the loop.
|
||||
* Else if we start a new set of bits then fill in the
|
||||
* iovec for the series we were looking at and start
|
||||
* counting the bits in the new one.
|
||||
* Else we're still in the same set of bits so just
|
||||
* keep counting and scanning.
|
||||
*/
|
||||
if (next_bit == -1) {
|
||||
buffer_offset = first_bit * XFS_BLF_CHUNK;
|
||||
vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
|
||||
vecp->i_len = nbits * XFS_BLF_CHUNK;
|
||||
vecp->i_type = XLOG_REG_TYPE_BCHUNK;
|
||||
nvecs++;
|
||||
break;
|
||||
} else if (next_bit != last_bit + 1) {
|
||||
buffer_offset = first_bit * XFS_BLF_CHUNK;
|
||||
vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
|
||||
vecp->i_len = nbits * XFS_BLF_CHUNK;
|
||||
vecp->i_type = XLOG_REG_TYPE_BCHUNK;
|
||||
nvecs++;
|
||||
vecp++;
|
||||
first_bit = next_bit;
|
||||
last_bit = next_bit;
|
||||
nbits = 1;
|
||||
} else if (xfs_buf_offset(bp, next_bit << XFS_BLF_SHIFT) !=
|
||||
(xfs_buf_offset(bp, last_bit << XFS_BLF_SHIFT) +
|
||||
XFS_BLF_CHUNK)) {
|
||||
buffer_offset = first_bit * XFS_BLF_CHUNK;
|
||||
vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
|
||||
vecp->i_len = nbits * XFS_BLF_CHUNK;
|
||||
vecp->i_type = XLOG_REG_TYPE_BCHUNK;
|
||||
/* You would think we need to bump the nvecs here too, but we do not
|
||||
* this number is used by recovery, and it gets confused by the boundary
|
||||
* split here
|
||||
* nvecs++;
|
||||
*/
|
||||
vecp++;
|
||||
first_bit = next_bit;
|
||||
last_bit = next_bit;
|
||||
nbits = 1;
|
||||
} else {
|
||||
last_bit++;
|
||||
nbits++;
|
||||
}
|
||||
}
|
||||
bip->bli_format.blf_size = nvecs;
|
||||
|
||||
/*
|
||||
* Check to make sure everything is consistent.
|
||||
*/
|
||||
|
@ -622,6 +689,35 @@ static const struct xfs_item_ops xfs_buf_item_ops = {
|
|||
.iop_committing = xfs_buf_item_committing
|
||||
};
|
||||
|
||||
STATIC int
|
||||
xfs_buf_item_get_format(
|
||||
struct xfs_buf_log_item *bip,
|
||||
int count)
|
||||
{
|
||||
ASSERT(bip->bli_formats == NULL);
|
||||
bip->bli_format_count = count;
|
||||
|
||||
if (count == 1) {
|
||||
bip->bli_formats = &bip->bli_format;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bip->bli_formats = kmem_zalloc(count * sizeof(struct xfs_buf_log_format),
|
||||
KM_SLEEP);
|
||||
if (!bip->bli_formats)
|
||||
return ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC void
|
||||
xfs_buf_item_free_format(
|
||||
struct xfs_buf_log_item *bip)
|
||||
{
|
||||
if (bip->bli_formats != &bip->bli_format) {
|
||||
kmem_free(bip->bli_formats);
|
||||
bip->bli_formats = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new buf log item to go with the given buffer.
|
||||
|
@ -639,6 +735,8 @@ xfs_buf_item_init(
|
|||
xfs_buf_log_item_t *bip;
|
||||
int chunks;
|
||||
int map_size;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Check to see if there is already a buf log item for
|
||||
|
@ -650,25 +748,33 @@ xfs_buf_item_init(
|
|||
if (lip != NULL && lip->li_type == XFS_LI_BUF)
|
||||
return;
|
||||
|
||||
/*
|
||||
* chunks is the number of XFS_BLF_CHUNK size pieces
|
||||
* the buffer can be divided into. Make sure not to
|
||||
* truncate any pieces. map_size is the size of the
|
||||
* bitmap needed to describe the chunks of the buffer.
|
||||
*/
|
||||
chunks = (int)((BBTOB(bp->b_length) + (XFS_BLF_CHUNK - 1)) >>
|
||||
XFS_BLF_SHIFT);
|
||||
map_size = (int)((chunks + NBWORD) >> BIT_TO_WORD_SHIFT);
|
||||
|
||||
bip = (xfs_buf_log_item_t*)kmem_zone_zalloc(xfs_buf_item_zone,
|
||||
KM_SLEEP);
|
||||
bip = kmem_zone_zalloc(xfs_buf_item_zone, KM_SLEEP);
|
||||
xfs_log_item_init(mp, &bip->bli_item, XFS_LI_BUF, &xfs_buf_item_ops);
|
||||
bip->bli_buf = bp;
|
||||
xfs_buf_hold(bp);
|
||||
bip->bli_format.blf_type = XFS_LI_BUF;
|
||||
bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp);
|
||||
bip->bli_format.blf_len = (ushort)bp->b_length;
|
||||
bip->bli_format.blf_map_size = map_size;
|
||||
|
||||
/*
|
||||
* chunks is the number of XFS_BLF_CHUNK size pieces the buffer
|
||||
* can be divided into. Make sure not to truncate any pieces.
|
||||
* map_size is the size of the bitmap needed to describe the
|
||||
* chunks of the buffer.
|
||||
*
|
||||
* Discontiguous buffer support follows the layout of the underlying
|
||||
* buffer. This makes the implementation as simple as possible.
|
||||
*/
|
||||
error = xfs_buf_item_get_format(bip, bp->b_map_count);
|
||||
ASSERT(error == 0);
|
||||
|
||||
for (i = 0; i < bip->bli_format_count; i++) {
|
||||
chunks = DIV_ROUND_UP(BBTOB(bp->b_maps[i].bm_len),
|
||||
XFS_BLF_CHUNK);
|
||||
map_size = DIV_ROUND_UP(chunks, NBWORD);
|
||||
|
||||
bip->bli_formats[i].blf_type = XFS_LI_BUF;
|
||||
bip->bli_formats[i].blf_blkno = bp->b_maps[i].bm_bn;
|
||||
bip->bli_formats[i].blf_len = bp->b_maps[i].bm_len;
|
||||
bip->bli_formats[i].blf_map_size = map_size;
|
||||
}
|
||||
|
||||
#ifdef XFS_TRANS_DEBUG
|
||||
/*
|
||||
|
@ -699,10 +805,11 @@ xfs_buf_item_init(
|
|||
* item's bitmap.
|
||||
*/
|
||||
void
|
||||
xfs_buf_item_log(
|
||||
xfs_buf_log_item_t *bip,
|
||||
xfs_buf_item_log_segment(
|
||||
struct xfs_buf_log_item *bip,
|
||||
uint first,
|
||||
uint last)
|
||||
uint last,
|
||||
uint *map)
|
||||
{
|
||||
uint first_bit;
|
||||
uint last_bit;
|
||||
|
@ -714,12 +821,6 @@ xfs_buf_item_log(
|
|||
uint end_bit;
|
||||
uint mask;
|
||||
|
||||
/*
|
||||
* Mark the item as having some dirty data for
|
||||
* quick reference in xfs_buf_item_dirty.
|
||||
*/
|
||||
bip->bli_flags |= XFS_BLI_DIRTY;
|
||||
|
||||
/*
|
||||
* Convert byte offsets to bit numbers.
|
||||
*/
|
||||
|
@ -736,7 +837,7 @@ xfs_buf_item_log(
|
|||
* to set a bit in.
|
||||
*/
|
||||
word_num = first_bit >> BIT_TO_WORD_SHIFT;
|
||||
wordp = &(bip->bli_format.blf_data_map[word_num]);
|
||||
wordp = &map[word_num];
|
||||
|
||||
/*
|
||||
* Calculate the starting bit in the first word.
|
||||
|
@ -783,6 +884,51 @@ xfs_buf_item_log(
|
|||
xfs_buf_item_log_debug(bip, first, last);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark bytes first through last inclusive as dirty in the buf
|
||||
* item's bitmap.
|
||||
*/
|
||||
void
|
||||
xfs_buf_item_log(
|
||||
xfs_buf_log_item_t *bip,
|
||||
uint first,
|
||||
uint last)
|
||||
{
|
||||
int i;
|
||||
uint start;
|
||||
uint end;
|
||||
struct xfs_buf *bp = bip->bli_buf;
|
||||
|
||||
/*
|
||||
* Mark the item as having some dirty data for
|
||||
* quick reference in xfs_buf_item_dirty.
|
||||
*/
|
||||
bip->bli_flags |= XFS_BLI_DIRTY;
|
||||
|
||||
/*
|
||||
* walk each buffer segment and mark them dirty appropriately.
|
||||
*/
|
||||
start = 0;
|
||||
for (i = 0; i < bip->bli_format_count; i++) {
|
||||
if (start > last)
|
||||
break;
|
||||
end = start + BBTOB(bp->b_maps[i].bm_len);
|
||||
if (first > end) {
|
||||
start += BBTOB(bp->b_maps[i].bm_len);
|
||||
continue;
|
||||
}
|
||||
if (first < start)
|
||||
first = start;
|
||||
if (end > last)
|
||||
end = last;
|
||||
|
||||
xfs_buf_item_log_segment(bip, first, end,
|
||||
&bip->bli_formats[i].blf_data_map[0]);
|
||||
|
||||
start += bp->b_maps[i].bm_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return 1 if the buffer has some data that has been logged (at any
|
||||
|
@ -804,6 +950,7 @@ xfs_buf_item_free(
|
|||
kmem_free(bip->bli_logged);
|
||||
#endif /* XFS_TRANS_DEBUG */
|
||||
|
||||
xfs_buf_item_free_format(bip);
|
||||
kmem_zone_free(xfs_buf_item_zone, bip);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,23 +20,6 @@
|
|||
|
||||
extern kmem_zone_t *xfs_buf_item_zone;
|
||||
|
||||
/*
|
||||
* This is the structure used to lay out a buf log item in the
|
||||
* log. The data map describes which 128 byte chunks of the buffer
|
||||
* have been logged.
|
||||
* For 6.2 and beyond, this is XFS_LI_BUF. We use this to log everything.
|
||||
*/
|
||||
typedef struct xfs_buf_log_format {
|
||||
unsigned short blf_type; /* buf log item type indicator */
|
||||
unsigned short blf_size; /* size of this item */
|
||||
ushort blf_flags; /* misc state */
|
||||
ushort blf_len; /* number of blocks in this buf */
|
||||
__int64_t blf_blkno; /* starting blkno of this buf */
|
||||
unsigned int blf_map_size; /* size of data bitmap in words */
|
||||
unsigned int blf_data_map[1];/* variable size bitmap of */
|
||||
/* regions of buffer in this item */
|
||||
} xfs_buf_log_format_t;
|
||||
|
||||
/*
|
||||
* This flag indicates that the buffer contains on disk inodes
|
||||
* and requires special recovery handling.
|
||||
|
@ -60,6 +43,23 @@ typedef struct xfs_buf_log_format {
|
|||
#define BIT_TO_WORD_SHIFT 5
|
||||
#define NBWORD (NBBY * sizeof(unsigned int))
|
||||
|
||||
/*
|
||||
* This is the structure used to lay out a buf log item in the
|
||||
* log. The data map describes which 128 byte chunks of the buffer
|
||||
* have been logged.
|
||||
*/
|
||||
#define XFS_BLF_DATAMAP_SIZE ((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) / NBWORD)
|
||||
|
||||
typedef struct xfs_buf_log_format {
|
||||
unsigned short blf_type; /* buf log item type indicator */
|
||||
unsigned short blf_size; /* size of this item */
|
||||
ushort blf_flags; /* misc state */
|
||||
ushort blf_len; /* number of blocks in this buf */
|
||||
__int64_t blf_blkno; /* starting blkno of this buf */
|
||||
unsigned int blf_map_size; /* used size of data bitmap in words */
|
||||
unsigned int blf_data_map[XFS_BLF_DATAMAP_SIZE]; /* dirty bitmap */
|
||||
} xfs_buf_log_format_t;
|
||||
|
||||
/*
|
||||
* buf log item flags
|
||||
*/
|
||||
|
@ -102,7 +102,9 @@ typedef struct xfs_buf_log_item {
|
|||
char *bli_orig; /* original buffer copy */
|
||||
char *bli_logged; /* bytes logged (bitmap) */
|
||||
#endif
|
||||
xfs_buf_log_format_t bli_format; /* in-log header */
|
||||
int bli_format_count; /* count of headers */
|
||||
struct xfs_buf_log_format *bli_formats; /* array of in-log header ptrs */
|
||||
struct xfs_buf_log_format bli_format; /* embedded in-log header */
|
||||
} xfs_buf_log_item_t;
|
||||
|
||||
void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -32,7 +32,7 @@ struct zone;
|
|||
/*
|
||||
* This structure is common to both leaf nodes and non-leaf nodes in the Btree.
|
||||
*
|
||||
* Is is used to manage a doubly linked list of all blocks at the same
|
||||
* It is used to manage a doubly linked list of all blocks at the same
|
||||
* level in the Btree, and to identify which type of block this is.
|
||||
*/
|
||||
#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */
|
||||
|
@ -132,24 +132,6 @@ typedef struct xfs_da_args {
|
|||
{ XFS_DA_OP_OKNOENT, "OKNOENT" }, \
|
||||
{ XFS_DA_OP_CILOOKUP, "CILOOKUP" }
|
||||
|
||||
/*
|
||||
* Structure to describe buffer(s) for a block.
|
||||
* This is needed in the directory version 2 format case, when
|
||||
* multiple non-contiguous fsblocks might be needed to cover one
|
||||
* logical directory block.
|
||||
* If the buffer count is 1 then the data pointer points to the
|
||||
* same place as the b_addr field for the buffer, else to kmem_alloced memory.
|
||||
*/
|
||||
typedef struct xfs_dabuf {
|
||||
int nbuf; /* number of buffer pointers present */
|
||||
short dirty; /* data needs to be copied back */
|
||||
short bbcount; /* how large is data in bbs */
|
||||
void *data; /* pointer for buffers' data */
|
||||
struct xfs_buf *bps[1]; /* actually nbuf of these */
|
||||
} xfs_dabuf_t;
|
||||
#define XFS_DA_BUF_SIZE(n) \
|
||||
(sizeof(xfs_dabuf_t) + sizeof(struct xfs_buf *) * ((n) - 1))
|
||||
|
||||
/*
|
||||
* Storage for holding state during Btree searches and split/join ops.
|
||||
*
|
||||
|
@ -158,7 +140,7 @@ typedef struct xfs_dabuf {
|
|||
* which is slightly more than enough.
|
||||
*/
|
||||
typedef struct xfs_da_state_blk {
|
||||
xfs_dabuf_t *bp; /* buffer containing block */
|
||||
struct xfs_buf *bp; /* buffer containing block */
|
||||
xfs_dablk_t blkno; /* filesystem blkno of buffer */
|
||||
xfs_daddr_t disk_blkno; /* on-disk blkno (in BBs) of buffer */
|
||||
int index; /* relevant index into block */
|
||||
|
@ -211,7 +193,7 @@ struct xfs_nameops {
|
|||
* Routines used for growing the Btree.
|
||||
*/
|
||||
int xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,
|
||||
xfs_dabuf_t **bpp, int whichfork);
|
||||
struct xfs_buf **bpp, int whichfork);
|
||||
int xfs_da_split(xfs_da_state_t *state);
|
||||
|
||||
/*
|
||||
|
@ -241,14 +223,14 @@ int xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno,
|
|||
int count);
|
||||
int xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp,
|
||||
xfs_dablk_t bno, xfs_daddr_t mappedbno,
|
||||
xfs_dabuf_t **bp, int whichfork);
|
||||
struct xfs_buf **bp, int whichfork);
|
||||
int xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp,
|
||||
xfs_dablk_t bno, xfs_daddr_t mappedbno,
|
||||
xfs_dabuf_t **bpp, int whichfork);
|
||||
struct xfs_buf **bpp, int whichfork);
|
||||
xfs_daddr_t xfs_da_reada_buf(struct xfs_trans *trans, struct xfs_inode *dp,
|
||||
xfs_dablk_t bno, int whichfork);
|
||||
int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
|
||||
xfs_dabuf_t *dead_buf);
|
||||
struct xfs_buf *dead_buf);
|
||||
|
||||
uint xfs_da_hashname(const __uint8_t *name_string, int name_length);
|
||||
enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args,
|
||||
|
@ -258,15 +240,7 @@ enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args,
|
|||
xfs_da_state_t *xfs_da_state_alloc(void);
|
||||
void xfs_da_state_free(xfs_da_state_t *state);
|
||||
|
||||
void xfs_da_buf_done(xfs_dabuf_t *dabuf);
|
||||
void xfs_da_log_buf(struct xfs_trans *tp, xfs_dabuf_t *dabuf, uint first,
|
||||
uint last);
|
||||
void xfs_da_brelse(struct xfs_trans *tp, xfs_dabuf_t *dabuf);
|
||||
void xfs_da_binval(struct xfs_trans *tp, xfs_dabuf_t *dabuf);
|
||||
xfs_daddr_t xfs_da_blkno(xfs_dabuf_t *dabuf);
|
||||
|
||||
extern struct kmem_zone *xfs_da_state_zone;
|
||||
extern struct kmem_zone *xfs_dabuf_zone;
|
||||
extern const struct xfs_nameops xfs_default_nameops;
|
||||
|
||||
#endif /* __XFS_DA_BTREE_H__ */
|
||||
|
|
|
@ -33,7 +33,7 @@ typedef struct xfs_timestamp {
|
|||
* variable size the leftover area split into a data and an attribute fork.
|
||||
* The format of the data and attribute fork depends on the format of the
|
||||
* inode as indicated by di_format and di_aformat. To access the data and
|
||||
* attribute use the XFS_DFORK_PTR, XFS_DFORK_DPTR, and XFS_DFORK_PTR macros
|
||||
* attribute use the XFS_DFORK_DPTR, XFS_DFORK_APTR, and XFS_DFORK_PTR macros
|
||||
* below.
|
||||
*
|
||||
* There is a very similar struct icdinode in xfs_inode which matches the
|
||||
|
|
|
@ -592,7 +592,7 @@ int
|
|||
xfs_dir2_shrink_inode(
|
||||
xfs_da_args_t *args,
|
||||
xfs_dir2_db_t db,
|
||||
xfs_dabuf_t *bp)
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
xfs_fileoff_t bno; /* directory file offset */
|
||||
xfs_dablk_t da; /* directory file offset */
|
||||
|
@ -634,7 +634,7 @@ xfs_dir2_shrink_inode(
|
|||
/*
|
||||
* Invalidate the buffer from the transaction.
|
||||
*/
|
||||
xfs_da_binval(tp, bp);
|
||||
xfs_trans_binval(tp, bp);
|
||||
/*
|
||||
* If it's not a data block, we're done.
|
||||
*/
|
||||
|
|
|
@ -37,10 +37,10 @@
|
|||
/*
|
||||
* Local function prototypes.
|
||||
*/
|
||||
static void xfs_dir2_block_log_leaf(xfs_trans_t *tp, xfs_dabuf_t *bp, int first,
|
||||
int last);
|
||||
static void xfs_dir2_block_log_tail(xfs_trans_t *tp, xfs_dabuf_t *bp);
|
||||
static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **bpp,
|
||||
static void xfs_dir2_block_log_leaf(xfs_trans_t *tp, struct xfs_buf *bp,
|
||||
int first, int last);
|
||||
static void xfs_dir2_block_log_tail(xfs_trans_t *tp, struct xfs_buf *bp);
|
||||
static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, struct xfs_buf **bpp,
|
||||
int *entno);
|
||||
static int xfs_dir2_block_sort(const void *a, const void *b);
|
||||
|
||||
|
@ -66,7 +66,7 @@ xfs_dir2_block_addname(
|
|||
xfs_dir2_data_free_t *bf; /* bestfree table in block */
|
||||
xfs_dir2_data_hdr_t *hdr; /* block header */
|
||||
xfs_dir2_leaf_entry_t *blp; /* block leaf entries */
|
||||
xfs_dabuf_t *bp; /* buffer for block */
|
||||
struct xfs_buf *bp; /* buffer for block */
|
||||
xfs_dir2_block_tail_t *btp; /* block tail */
|
||||
int compact; /* need to compact leaf ents */
|
||||
xfs_dir2_data_entry_t *dep; /* block data entry */
|
||||
|
@ -102,14 +102,14 @@ xfs_dir2_block_addname(
|
|||
return error;
|
||||
}
|
||||
ASSERT(bp != NULL);
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
/*
|
||||
* Check the magic number, corrupted if wrong.
|
||||
*/
|
||||
if (unlikely(hdr->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))) {
|
||||
XFS_CORRUPTION_ERROR("xfs_dir2_block_addname",
|
||||
XFS_ERRLEVEL_LOW, mp, hdr);
|
||||
xfs_da_brelse(tp, bp);
|
||||
xfs_trans_brelse(tp, bp);
|
||||
return XFS_ERROR(EFSCORRUPTED);
|
||||
}
|
||||
len = xfs_dir2_data_entsize(args->namelen);
|
||||
|
@ -212,7 +212,7 @@ xfs_dir2_block_addname(
|
|||
* If this isn't a real add, we're done with the buffer.
|
||||
*/
|
||||
if (args->op_flags & XFS_DA_OP_JUSTCHECK)
|
||||
xfs_da_brelse(tp, bp);
|
||||
xfs_trans_brelse(tp, bp);
|
||||
/*
|
||||
* If we don't have space for the new entry & leaf ...
|
||||
*/
|
||||
|
@ -228,7 +228,6 @@ xfs_dir2_block_addname(
|
|||
* Then add the new entry in that format.
|
||||
*/
|
||||
error = xfs_dir2_block_to_leaf(args, bp);
|
||||
xfs_da_buf_done(bp);
|
||||
if (error)
|
||||
return error;
|
||||
return xfs_dir2_leaf_addname(args);
|
||||
|
@ -422,7 +421,6 @@ xfs_dir2_block_addname(
|
|||
xfs_dir2_block_log_tail(tp, bp);
|
||||
xfs_dir2_data_log_entry(tp, bp, dep);
|
||||
xfs_dir2_data_check(dp, bp);
|
||||
xfs_da_buf_done(bp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -437,7 +435,7 @@ xfs_dir2_block_getdents(
|
|||
filldir_t filldir)
|
||||
{
|
||||
xfs_dir2_data_hdr_t *hdr; /* block header */
|
||||
xfs_dabuf_t *bp; /* buffer for block */
|
||||
struct xfs_buf *bp; /* buffer for block */
|
||||
xfs_dir2_block_tail_t *btp; /* block tail */
|
||||
xfs_dir2_data_entry_t *dep; /* block data entry */
|
||||
xfs_dir2_data_unused_t *dup; /* block unused entry */
|
||||
|
@ -469,7 +467,7 @@ xfs_dir2_block_getdents(
|
|||
* We'll skip entries before this.
|
||||
*/
|
||||
wantoff = xfs_dir2_dataptr_to_off(mp, *offset);
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
xfs_dir2_data_check(dp, bp);
|
||||
/*
|
||||
* Set up values for the loop.
|
||||
|
@ -514,7 +512,7 @@ xfs_dir2_block_getdents(
|
|||
cook & 0x7fffffff, be64_to_cpu(dep->inumber),
|
||||
DT_UNKNOWN)) {
|
||||
*offset = cook & 0x7fffffff;
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -525,7 +523,7 @@ xfs_dir2_block_getdents(
|
|||
*/
|
||||
*offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
|
||||
0x7fffffff;
|
||||
xfs_da_brelse(NULL, bp);
|
||||
xfs_trans_brelse(NULL, bp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -535,17 +533,17 @@ xfs_dir2_block_getdents(
|
|||
static void
|
||||
xfs_dir2_block_log_leaf(
|
||||
xfs_trans_t *tp, /* transaction structure */
|
||||
xfs_dabuf_t *bp, /* block buffer */
|
||||
struct xfs_buf *bp, /* block buffer */
|
||||
int first, /* index of first logged leaf */
|
||||
int last) /* index of last logged leaf */
|
||||
{
|
||||
xfs_dir2_data_hdr_t *hdr = bp->data;
|
||||
xfs_dir2_data_hdr_t *hdr = bp->b_addr;
|
||||
xfs_dir2_leaf_entry_t *blp;
|
||||
xfs_dir2_block_tail_t *btp;
|
||||
|
||||
btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
xfs_da_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr),
|
||||
xfs_trans_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr),
|
||||
(uint)((char *)&blp[last + 1] - (char *)hdr - 1));
|
||||
}
|
||||
|
||||
|
@ -555,13 +553,13 @@ xfs_dir2_block_log_leaf(
|
|||
static void
|
||||
xfs_dir2_block_log_tail(
|
||||
xfs_trans_t *tp, /* transaction structure */
|
||||
xfs_dabuf_t *bp) /* block buffer */
|
||||
struct xfs_buf *bp) /* block buffer */
|
||||
{
|
||||
xfs_dir2_data_hdr_t *hdr = bp->data;
|
||||
xfs_dir2_data_hdr_t *hdr = bp->b_addr;
|
||||
xfs_dir2_block_tail_t *btp;
|
||||
|
||||
btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr);
|
||||
xfs_da_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr),
|
||||
xfs_trans_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr),
|
||||
(uint)((char *)(btp + 1) - (char *)hdr - 1));
|
||||
}
|
||||
|
||||
|
@ -575,7 +573,7 @@ xfs_dir2_block_lookup(
|
|||
{
|
||||
xfs_dir2_data_hdr_t *hdr; /* block header */
|
||||
xfs_dir2_leaf_entry_t *blp; /* block leaf entries */
|
||||
xfs_dabuf_t *bp; /* block buffer */
|
||||
struct xfs_buf *bp; /* block buffer */
|
||||
xfs_dir2_block_tail_t *btp; /* block tail */
|
||||
xfs_dir2_data_entry_t *dep; /* block data entry */
|
||||
xfs_inode_t *dp; /* incore inode */
|
||||
|
@ -593,7 +591,7 @@ xfs_dir2_block_lookup(
|
|||
return error;
|
||||
dp = args->dp;
|
||||
mp = dp->i_mount;
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
xfs_dir2_data_check(dp, bp);
|
||||
btp = xfs_dir2_block_tail_p(mp, hdr);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
|
@ -607,7 +605,7 @@ xfs_dir2_block_lookup(
|
|||
*/
|
||||
args->inumber = be64_to_cpu(dep->inumber);
|
||||
error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
|
||||
xfs_da_brelse(args->trans, bp);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
return XFS_ERROR(error);
|
||||
}
|
||||
|
||||
|
@ -617,13 +615,13 @@ xfs_dir2_block_lookup(
|
|||
static int /* error */
|
||||
xfs_dir2_block_lookup_int(
|
||||
xfs_da_args_t *args, /* dir lookup arguments */
|
||||
xfs_dabuf_t **bpp, /* returned block buffer */
|
||||
struct xfs_buf **bpp, /* returned block buffer */
|
||||
int *entno) /* returned entry number */
|
||||
{
|
||||
xfs_dir2_dataptr_t addr; /* data entry address */
|
||||
xfs_dir2_data_hdr_t *hdr; /* block header */
|
||||
xfs_dir2_leaf_entry_t *blp; /* block leaf entries */
|
||||
xfs_dabuf_t *bp; /* block buffer */
|
||||
struct xfs_buf *bp; /* block buffer */
|
||||
xfs_dir2_block_tail_t *btp; /* block tail */
|
||||
xfs_dir2_data_entry_t *dep; /* block data entry */
|
||||
xfs_inode_t *dp; /* incore inode */
|
||||
|
@ -647,7 +645,7 @@ xfs_dir2_block_lookup_int(
|
|||
return error;
|
||||
}
|
||||
ASSERT(bp != NULL);
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
xfs_dir2_data_check(dp, bp);
|
||||
btp = xfs_dir2_block_tail_p(mp, hdr);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
|
@ -666,7 +664,7 @@ xfs_dir2_block_lookup_int(
|
|||
high = mid - 1;
|
||||
if (low > high) {
|
||||
ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
|
||||
xfs_da_brelse(tp, bp);
|
||||
xfs_trans_brelse(tp, bp);
|
||||
return XFS_ERROR(ENOENT);
|
||||
}
|
||||
}
|
||||
|
@ -714,7 +712,7 @@ xfs_dir2_block_lookup_int(
|
|||
/*
|
||||
* No match, release the buffer and return ENOENT.
|
||||
*/
|
||||
xfs_da_brelse(tp, bp);
|
||||
xfs_trans_brelse(tp, bp);
|
||||
return XFS_ERROR(ENOENT);
|
||||
}
|
||||
|
||||
|
@ -728,7 +726,7 @@ xfs_dir2_block_removename(
|
|||
{
|
||||
xfs_dir2_data_hdr_t *hdr; /* block header */
|
||||
xfs_dir2_leaf_entry_t *blp; /* block leaf pointer */
|
||||
xfs_dabuf_t *bp; /* block buffer */
|
||||
struct xfs_buf *bp; /* block buffer */
|
||||
xfs_dir2_block_tail_t *btp; /* block tail */
|
||||
xfs_dir2_data_entry_t *dep; /* block data entry */
|
||||
xfs_inode_t *dp; /* incore inode */
|
||||
|
@ -753,7 +751,7 @@ xfs_dir2_block_removename(
|
|||
dp = args->dp;
|
||||
tp = args->trans;
|
||||
mp = dp->i_mount;
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
btp = xfs_dir2_block_tail_p(mp, hdr);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
/*
|
||||
|
@ -790,10 +788,9 @@ xfs_dir2_block_removename(
|
|||
* See if the size as a shortform is good enough.
|
||||
*/
|
||||
size = xfs_dir2_block_sfsize(dp, hdr, &sfh);
|
||||
if (size > XFS_IFORK_DSIZE(dp)) {
|
||||
xfs_da_buf_done(bp);
|
||||
if (size > XFS_IFORK_DSIZE(dp))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it works, do the conversion.
|
||||
*/
|
||||
|
@ -810,7 +807,7 @@ xfs_dir2_block_replace(
|
|||
{
|
||||
xfs_dir2_data_hdr_t *hdr; /* block header */
|
||||
xfs_dir2_leaf_entry_t *blp; /* block leaf entries */
|
||||
xfs_dabuf_t *bp; /* block buffer */
|
||||
struct xfs_buf *bp; /* block buffer */
|
||||
xfs_dir2_block_tail_t *btp; /* block tail */
|
||||
xfs_dir2_data_entry_t *dep; /* block data entry */
|
||||
xfs_inode_t *dp; /* incore inode */
|
||||
|
@ -829,7 +826,7 @@ xfs_dir2_block_replace(
|
|||
}
|
||||
dp = args->dp;
|
||||
mp = dp->i_mount;
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
btp = xfs_dir2_block_tail_p(mp, hdr);
|
||||
blp = xfs_dir2_block_leaf_p(btp);
|
||||
/*
|
||||
|
@ -844,7 +841,6 @@ xfs_dir2_block_replace(
|
|||
dep->inumber = cpu_to_be64(args->inumber);
|
||||
xfs_dir2_data_log_entry(args->trans, bp, dep);
|
||||
xfs_dir2_data_check(dp, bp);
|
||||
xfs_da_buf_done(bp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -871,8 +867,8 @@ xfs_dir2_block_sort(
|
|||
int /* error */
|
||||
xfs_dir2_leaf_to_block(
|
||||
xfs_da_args_t *args, /* operation arguments */
|
||||
xfs_dabuf_t *lbp, /* leaf buffer */
|
||||
xfs_dabuf_t *dbp) /* data buffer */
|
||||
struct xfs_buf *lbp, /* leaf buffer */
|
||||
struct xfs_buf *dbp) /* data buffer */
|
||||
{
|
||||
__be16 *bestsp; /* leaf bests table */
|
||||
xfs_dir2_data_hdr_t *hdr; /* block header */
|
||||
|
@ -898,7 +894,7 @@ xfs_dir2_leaf_to_block(
|
|||
dp = args->dp;
|
||||
tp = args->trans;
|
||||
mp = dp->i_mount;
|
||||
leaf = lbp->data;
|
||||
leaf = lbp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC));
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
/*
|
||||
|
@ -914,11 +910,9 @@ xfs_dir2_leaf_to_block(
|
|||
if ((error =
|
||||
xfs_dir2_leaf_trim_data(args, lbp,
|
||||
(xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1))))
|
||||
goto out;
|
||||
} else {
|
||||
error = 0;
|
||||
goto out;
|
||||
}
|
||||
return error;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Read the data block if we don't already have it, give up if it fails.
|
||||
|
@ -926,9 +920,9 @@ xfs_dir2_leaf_to_block(
|
|||
if (dbp == NULL &&
|
||||
(error = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &dbp,
|
||||
XFS_DATA_FORK))) {
|
||||
goto out;
|
||||
return error;
|
||||
}
|
||||
hdr = dbp->data;
|
||||
hdr = dbp->b_addr;
|
||||
ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
|
||||
/*
|
||||
* Size of the "leaf" area in the block.
|
||||
|
@ -944,10 +938,9 @@ xfs_dir2_leaf_to_block(
|
|||
* If it's not free or is too short we can't do it.
|
||||
*/
|
||||
if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG ||
|
||||
be16_to_cpu(dup->length) < size) {
|
||||
error = 0;
|
||||
goto out;
|
||||
}
|
||||
be16_to_cpu(dup->length) < size)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Start converting it to block form.
|
||||
*/
|
||||
|
@ -989,25 +982,17 @@ xfs_dir2_leaf_to_block(
|
|||
* Pitch the old leaf block.
|
||||
*/
|
||||
error = xfs_da_shrink_inode(args, mp->m_dirleafblk, lbp);
|
||||
lbp = NULL;
|
||||
if (error) {
|
||||
goto out;
|
||||
}
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* Now see if the resulting block can be shrunken to shortform.
|
||||
*/
|
||||
size = xfs_dir2_block_sfsize(dp, hdr, &sfh);
|
||||
if (size > XFS_IFORK_DSIZE(dp)) {
|
||||
error = 0;
|
||||
goto out;
|
||||
}
|
||||
if (size > XFS_IFORK_DSIZE(dp))
|
||||
return 0;
|
||||
|
||||
return xfs_dir2_block_to_sf(args, dbp, size, &sfh);
|
||||
out:
|
||||
if (lbp)
|
||||
xfs_da_buf_done(lbp);
|
||||
if (dbp)
|
||||
xfs_da_buf_done(dbp);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1020,7 +1005,7 @@ xfs_dir2_sf_to_block(
|
|||
xfs_dir2_db_t blkno; /* dir-relative block # (0) */
|
||||
xfs_dir2_data_hdr_t *hdr; /* block header */
|
||||
xfs_dir2_leaf_entry_t *blp; /* block leaf entries */
|
||||
xfs_dabuf_t *bp; /* block buffer */
|
||||
struct xfs_buf *bp; /* block buffer */
|
||||
xfs_dir2_block_tail_t *btp; /* block tail pointer */
|
||||
xfs_dir2_data_entry_t *dep; /* data entry pointer */
|
||||
xfs_inode_t *dp; /* incore directory inode */
|
||||
|
@ -1088,7 +1073,7 @@ xfs_dir2_sf_to_block(
|
|||
kmem_free(sfp);
|
||||
return error;
|
||||
}
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
hdr->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
|
||||
/*
|
||||
* Compute size of block "tail" area.
|
||||
|
@ -1217,6 +1202,5 @@ xfs_dir2_sf_to_block(
|
|||
xfs_dir2_block_log_leaf(tp, bp, 0, be32_to_cpu(btp->count) - 1);
|
||||
xfs_dir2_block_log_tail(tp, bp);
|
||||
xfs_dir2_data_check(dp, bp);
|
||||
xfs_da_buf_done(bp);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup);
|
|||
*/
|
||||
void
|
||||
xfs_dir2_data_check(
|
||||
xfs_inode_t *dp, /* incore inode pointer */
|
||||
xfs_dabuf_t *bp) /* data block's buffer */
|
||||
struct xfs_inode *dp, /* incore inode pointer */
|
||||
struct xfs_buf *bp) /* data block's buffer */
|
||||
{
|
||||
xfs_dir2_dataptr_t addr; /* addr for leaf lookup */
|
||||
xfs_dir2_data_free_t *bf; /* bestfree table */
|
||||
|
@ -65,7 +65,7 @@ xfs_dir2_data_check(
|
|||
struct xfs_name name;
|
||||
|
||||
mp = dp->i_mount;
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
bf = hdr->bestfree;
|
||||
p = (char *)(hdr + 1);
|
||||
|
||||
|
@ -389,9 +389,9 @@ int /* error */
|
|||
xfs_dir2_data_init(
|
||||
xfs_da_args_t *args, /* directory operation args */
|
||||
xfs_dir2_db_t blkno, /* logical dir block number */
|
||||
xfs_dabuf_t **bpp) /* output block buffer */
|
||||
struct xfs_buf **bpp) /* output block buffer */
|
||||
{
|
||||
xfs_dabuf_t *bp; /* block buffer */
|
||||
struct xfs_buf *bp; /* block buffer */
|
||||
xfs_dir2_data_hdr_t *hdr; /* data block header */
|
||||
xfs_inode_t *dp; /* incore directory inode */
|
||||
xfs_dir2_data_unused_t *dup; /* unused entry pointer */
|
||||
|
@ -417,7 +417,7 @@ xfs_dir2_data_init(
|
|||
/*
|
||||
* Initialize the header.
|
||||
*/
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
|
||||
hdr->bestfree[0].offset = cpu_to_be16(sizeof(*hdr));
|
||||
for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
|
||||
|
@ -449,16 +449,16 @@ xfs_dir2_data_init(
|
|||
*/
|
||||
void
|
||||
xfs_dir2_data_log_entry(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_dabuf_t *bp, /* block buffer */
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *bp,
|
||||
xfs_dir2_data_entry_t *dep) /* data entry pointer */
|
||||
{
|
||||
xfs_dir2_data_hdr_t *hdr = bp->data;
|
||||
xfs_dir2_data_hdr_t *hdr = bp->b_addr;
|
||||
|
||||
ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
|
||||
hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
|
||||
|
||||
xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr),
|
||||
xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr),
|
||||
(uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) -
|
||||
(char *)hdr - 1));
|
||||
}
|
||||
|
@ -468,15 +468,15 @@ xfs_dir2_data_log_entry(
|
|||
*/
|
||||
void
|
||||
xfs_dir2_data_log_header(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_dabuf_t *bp) /* block buffer */
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
xfs_dir2_data_hdr_t *hdr = bp->data;
|
||||
xfs_dir2_data_hdr_t *hdr = bp->b_addr;
|
||||
|
||||
ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
|
||||
hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
|
||||
|
||||
xfs_da_log_buf(tp, bp, 0, sizeof(*hdr) - 1);
|
||||
xfs_trans_log_buf(tp, bp, 0, sizeof(*hdr) - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -484,11 +484,11 @@ xfs_dir2_data_log_header(
|
|||
*/
|
||||
void
|
||||
xfs_dir2_data_log_unused(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_dabuf_t *bp, /* block buffer */
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *bp,
|
||||
xfs_dir2_data_unused_t *dup) /* data unused pointer */
|
||||
{
|
||||
xfs_dir2_data_hdr_t *hdr = bp->data;
|
||||
xfs_dir2_data_hdr_t *hdr = bp->b_addr;
|
||||
|
||||
ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
|
||||
hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
|
||||
|
@ -496,13 +496,13 @@ xfs_dir2_data_log_unused(
|
|||
/*
|
||||
* Log the first part of the unused entry.
|
||||
*/
|
||||
xfs_da_log_buf(tp, bp, (uint)((char *)dup - (char *)hdr),
|
||||
xfs_trans_log_buf(tp, bp, (uint)((char *)dup - (char *)hdr),
|
||||
(uint)((char *)&dup->length + sizeof(dup->length) -
|
||||
1 - (char *)hdr));
|
||||
/*
|
||||
* Log the end (tag) of the unused entry.
|
||||
*/
|
||||
xfs_da_log_buf(tp, bp,
|
||||
xfs_trans_log_buf(tp, bp,
|
||||
(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr),
|
||||
(uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr +
|
||||
sizeof(xfs_dir2_data_off_t) - 1));
|
||||
|
@ -514,8 +514,8 @@ xfs_dir2_data_log_unused(
|
|||
*/
|
||||
void
|
||||
xfs_dir2_data_make_free(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_dabuf_t *bp, /* block buffer */
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *bp,
|
||||
xfs_dir2_data_aoff_t offset, /* starting byte offset */
|
||||
xfs_dir2_data_aoff_t len, /* length in bytes */
|
||||
int *needlogp, /* out: log header */
|
||||
|
@ -531,7 +531,7 @@ xfs_dir2_data_make_free(
|
|||
xfs_dir2_data_unused_t *prevdup; /* unused entry before us */
|
||||
|
||||
mp = tp->t_mountp;
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
|
||||
/*
|
||||
* Figure out where the end of the data area is.
|
||||
|
@ -696,8 +696,8 @@ xfs_dir2_data_make_free(
|
|||
*/
|
||||
void
|
||||
xfs_dir2_data_use_free(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_dabuf_t *bp, /* data block buffer */
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *bp,
|
||||
xfs_dir2_data_unused_t *dup, /* unused entry */
|
||||
xfs_dir2_data_aoff_t offset, /* starting offset to use */
|
||||
xfs_dir2_data_aoff_t len, /* length to use */
|
||||
|
@ -713,7 +713,7 @@ xfs_dir2_data_use_free(
|
|||
xfs_dir2_data_unused_t *newdup2; /* another new unused entry */
|
||||
int oldlen; /* old unused entry's length */
|
||||
|
||||
hdr = bp->data;
|
||||
hdr = bp->b_addr;
|
||||
ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
|
||||
hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC));
|
||||
ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -36,20 +36,20 @@
|
|||
/*
|
||||
* Function declarations.
|
||||
*/
|
||||
static void xfs_dir2_free_log_header(xfs_trans_t *tp, xfs_dabuf_t *bp);
|
||||
static int xfs_dir2_leafn_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index);
|
||||
static int xfs_dir2_leafn_add(struct xfs_buf *bp, xfs_da_args_t *args,
|
||||
int index);
|
||||
#ifdef DEBUG
|
||||
static void xfs_dir2_leafn_check(xfs_inode_t *dp, xfs_dabuf_t *bp);
|
||||
static void xfs_dir2_leafn_check(struct xfs_inode *dp, struct xfs_buf *bp);
|
||||
#else
|
||||
#define xfs_dir2_leafn_check(dp, bp)
|
||||
#endif
|
||||
static void xfs_dir2_leafn_moveents(xfs_da_args_t *args, xfs_dabuf_t *bp_s,
|
||||
int start_s, xfs_dabuf_t *bp_d, int start_d,
|
||||
int count);
|
||||
static void xfs_dir2_leafn_moveents(xfs_da_args_t *args, struct xfs_buf *bp_s,
|
||||
int start_s, struct xfs_buf *bp_d,
|
||||
int start_d, int count);
|
||||
static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state,
|
||||
xfs_da_state_blk_t *blk1,
|
||||
xfs_da_state_blk_t *blk2);
|
||||
static int xfs_dir2_leafn_remove(xfs_da_args_t *args, xfs_dabuf_t *bp,
|
||||
static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp,
|
||||
int index, xfs_da_state_blk_t *dblk,
|
||||
int *rval);
|
||||
static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
|
||||
|
@ -60,16 +60,16 @@ static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
|
|||
*/
|
||||
STATIC void
|
||||
xfs_dir2_free_log_bests(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_dabuf_t *bp, /* freespace buffer */
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *bp,
|
||||
int first, /* first entry to log */
|
||||
int last) /* last entry to log */
|
||||
{
|
||||
xfs_dir2_free_t *free; /* freespace structure */
|
||||
|
||||
free = bp->data;
|
||||
free = bp->b_addr;
|
||||
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
|
||||
xfs_da_log_buf(tp, bp,
|
||||
xfs_trans_log_buf(tp, bp,
|
||||
(uint)((char *)&free->bests[first] - (char *)free),
|
||||
(uint)((char *)&free->bests[last] - (char *)free +
|
||||
sizeof(free->bests[0]) - 1));
|
||||
|
@ -80,14 +80,14 @@ xfs_dir2_free_log_bests(
|
|||
*/
|
||||
static void
|
||||
xfs_dir2_free_log_header(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_dabuf_t *bp) /* freespace buffer */
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
xfs_dir2_free_t *free; /* freespace structure */
|
||||
|
||||
free = bp->data;
|
||||
free = bp->b_addr;
|
||||
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
|
||||
xfs_da_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free),
|
||||
xfs_trans_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free),
|
||||
(uint)(sizeof(xfs_dir2_free_hdr_t) - 1));
|
||||
}
|
||||
|
||||
|
@ -99,11 +99,11 @@ xfs_dir2_free_log_header(
|
|||
int /* error */
|
||||
xfs_dir2_leaf_to_node(
|
||||
xfs_da_args_t *args, /* operation arguments */
|
||||
xfs_dabuf_t *lbp) /* leaf buffer */
|
||||
struct xfs_buf *lbp) /* leaf buffer */
|
||||
{
|
||||
xfs_inode_t *dp; /* incore directory inode */
|
||||
int error; /* error return value */
|
||||
xfs_dabuf_t *fbp; /* freespace buffer */
|
||||
struct xfs_buf *fbp; /* freespace buffer */
|
||||
xfs_dir2_db_t fdb; /* freespace block number */
|
||||
xfs_dir2_free_t *free; /* freespace structure */
|
||||
__be16 *from; /* pointer to freespace entry */
|
||||
|
@ -136,8 +136,8 @@ xfs_dir2_leaf_to_node(
|
|||
return error;
|
||||
}
|
||||
ASSERT(fbp != NULL);
|
||||
free = fbp->data;
|
||||
leaf = lbp->data;
|
||||
free = fbp->b_addr;
|
||||
leaf = lbp->b_addr;
|
||||
ltp = xfs_dir2_leaf_tail_p(mp, leaf);
|
||||
/*
|
||||
* Initialize the freespace block header.
|
||||
|
@ -164,7 +164,6 @@ xfs_dir2_leaf_to_node(
|
|||
xfs_dir2_leaf_log_header(tp, lbp);
|
||||
xfs_dir2_free_log_header(tp, fbp);
|
||||
xfs_dir2_free_log_bests(tp, fbp, 0, be32_to_cpu(free->hdr.nvalid) - 1);
|
||||
xfs_da_buf_done(fbp);
|
||||
xfs_dir2_leafn_check(dp, lbp);
|
||||
return 0;
|
||||
}
|
||||
|
@ -175,7 +174,7 @@ xfs_dir2_leaf_to_node(
|
|||
*/
|
||||
static int /* error */
|
||||
xfs_dir2_leafn_add(
|
||||
xfs_dabuf_t *bp, /* leaf buffer */
|
||||
struct xfs_buf *bp, /* leaf buffer */
|
||||
xfs_da_args_t *args, /* operation arguments */
|
||||
int index) /* insertion pt for new entry */
|
||||
{
|
||||
|
@ -195,7 +194,7 @@ xfs_dir2_leafn_add(
|
|||
dp = args->dp;
|
||||
mp = dp->i_mount;
|
||||
tp = args->trans;
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
|
||||
/*
|
||||
* Quick check just to make sure we are not going to index
|
||||
|
@ -261,15 +260,15 @@ xfs_dir2_leafn_add(
|
|||
*/
|
||||
void
|
||||
xfs_dir2_leafn_check(
|
||||
xfs_inode_t *dp, /* incore directory inode */
|
||||
xfs_dabuf_t *bp) /* leaf buffer */
|
||||
struct xfs_inode *dp,
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
int i; /* leaf index */
|
||||
xfs_dir2_leaf_t *leaf; /* leaf structure */
|
||||
xfs_mount_t *mp; /* filesystem mount point */
|
||||
int stale; /* count of stale leaves */
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
mp = dp->i_mount;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));
|
||||
|
@ -291,12 +290,12 @@ xfs_dir2_leafn_check(
|
|||
*/
|
||||
xfs_dahash_t /* hash value */
|
||||
xfs_dir2_leafn_lasthash(
|
||||
xfs_dabuf_t *bp, /* leaf buffer */
|
||||
struct xfs_buf *bp, /* leaf buffer */
|
||||
int *count) /* count of entries in leaf */
|
||||
{
|
||||
xfs_dir2_leaf_t *leaf; /* leaf structure */
|
||||
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
if (count)
|
||||
*count = be16_to_cpu(leaf->hdr.count);
|
||||
|
@ -311,12 +310,12 @@ xfs_dir2_leafn_lasthash(
|
|||
*/
|
||||
STATIC int
|
||||
xfs_dir2_leafn_lookup_for_addname(
|
||||
xfs_dabuf_t *bp, /* leaf buffer */
|
||||
struct xfs_buf *bp, /* leaf buffer */
|
||||
xfs_da_args_t *args, /* operation arguments */
|
||||
int *indexp, /* out: leaf entry index */
|
||||
xfs_da_state_t *state) /* state to fill in */
|
||||
{
|
||||
xfs_dabuf_t *curbp = NULL; /* current data/free buffer */
|
||||
struct xfs_buf *curbp = NULL; /* current data/free buffer */
|
||||
xfs_dir2_db_t curdb = -1; /* current data block number */
|
||||
xfs_dir2_db_t curfdb = -1; /* current free block number */
|
||||
xfs_inode_t *dp; /* incore directory inode */
|
||||
|
@ -335,7 +334,7 @@ xfs_dir2_leafn_lookup_for_addname(
|
|||
dp = args->dp;
|
||||
tp = args->trans;
|
||||
mp = dp->i_mount;
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
#ifdef __KERNEL__
|
||||
ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
|
||||
|
@ -352,7 +351,7 @@ xfs_dir2_leafn_lookup_for_addname(
|
|||
/* If so, it's a free block buffer, get the block number. */
|
||||
curbp = state->extrablk.bp;
|
||||
curfdb = state->extrablk.blkno;
|
||||
free = curbp->data;
|
||||
free = curbp->b_addr;
|
||||
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
|
||||
}
|
||||
length = xfs_dir2_data_entsize(args->namelen);
|
||||
|
@ -394,7 +393,7 @@ xfs_dir2_leafn_lookup_for_addname(
|
|||
* If we had one before, drop it.
|
||||
*/
|
||||
if (curbp)
|
||||
xfs_da_brelse(tp, curbp);
|
||||
xfs_trans_brelse(tp, curbp);
|
||||
/*
|
||||
* Read the free block.
|
||||
*/
|
||||
|
@ -403,7 +402,7 @@ xfs_dir2_leafn_lookup_for_addname(
|
|||
-1, &curbp, XFS_DATA_FORK);
|
||||
if (error)
|
||||
return error;
|
||||
free = curbp->data;
|
||||
free = curbp->b_addr;
|
||||
ASSERT(be32_to_cpu(free->hdr.magic) ==
|
||||
XFS_DIR2_FREE_MAGIC);
|
||||
ASSERT((be32_to_cpu(free->hdr.firstdb) %
|
||||
|
@ -424,7 +423,7 @@ xfs_dir2_leafn_lookup_for_addname(
|
|||
XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
|
||||
XFS_ERRLEVEL_LOW, mp);
|
||||
if (curfdb != newfdb)
|
||||
xfs_da_brelse(tp, curbp);
|
||||
xfs_trans_brelse(tp, curbp);
|
||||
return XFS_ERROR(EFSCORRUPTED);
|
||||
}
|
||||
curfdb = newfdb;
|
||||
|
@ -459,12 +458,12 @@ out:
|
|||
*/
|
||||
STATIC int
|
||||
xfs_dir2_leafn_lookup_for_entry(
|
||||
xfs_dabuf_t *bp, /* leaf buffer */
|
||||
struct xfs_buf *bp, /* leaf buffer */
|
||||
xfs_da_args_t *args, /* operation arguments */
|
||||
int *indexp, /* out: leaf entry index */
|
||||
xfs_da_state_t *state) /* state to fill in */
|
||||
{
|
||||
xfs_dabuf_t *curbp = NULL; /* current data/free buffer */
|
||||
struct xfs_buf *curbp = NULL; /* current data/free buffer */
|
||||
xfs_dir2_db_t curdb = -1; /* current data block number */
|
||||
xfs_dir2_data_entry_t *dep; /* data block entry */
|
||||
xfs_inode_t *dp; /* incore directory inode */
|
||||
|
@ -480,7 +479,7 @@ xfs_dir2_leafn_lookup_for_entry(
|
|||
dp = args->dp;
|
||||
tp = args->trans;
|
||||
mp = dp->i_mount;
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
#ifdef __KERNEL__
|
||||
ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
|
||||
|
@ -525,7 +524,7 @@ xfs_dir2_leafn_lookup_for_entry(
|
|||
*/
|
||||
if (curbp && (args->cmpresult == XFS_CMP_DIFFERENT ||
|
||||
curdb != state->extrablk.blkno))
|
||||
xfs_da_brelse(tp, curbp);
|
||||
xfs_trans_brelse(tp, curbp);
|
||||
/*
|
||||
* If needing the block that is saved with a CI match,
|
||||
* use it otherwise read in the new data block.
|
||||
|
@ -547,7 +546,7 @@ xfs_dir2_leafn_lookup_for_entry(
|
|||
/*
|
||||
* Point to the data entry.
|
||||
*/
|
||||
dep = (xfs_dir2_data_entry_t *)((char *)curbp->data +
|
||||
dep = (xfs_dir2_data_entry_t *)((char *)curbp->b_addr +
|
||||
xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
|
||||
/*
|
||||
* Compare the entry and if it's an exact match, return
|
||||
|
@ -559,7 +558,7 @@ xfs_dir2_leafn_lookup_for_entry(
|
|||
/* If there is a CI match block, drop it */
|
||||
if (args->cmpresult != XFS_CMP_DIFFERENT &&
|
||||
curdb != state->extrablk.blkno)
|
||||
xfs_da_brelse(tp, state->extrablk.bp);
|
||||
xfs_trans_brelse(tp, state->extrablk.bp);
|
||||
args->cmpresult = cmp;
|
||||
args->inumber = be64_to_cpu(dep->inumber);
|
||||
*indexp = index;
|
||||
|
@ -567,7 +566,7 @@ xfs_dir2_leafn_lookup_for_entry(
|
|||
state->extrablk.bp = curbp;
|
||||
state->extrablk.blkno = curdb;
|
||||
state->extrablk.index = (int)((char *)dep -
|
||||
(char *)curbp->data);
|
||||
(char *)curbp->b_addr);
|
||||
state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
|
||||
if (cmp == XFS_CMP_EXACT)
|
||||
return XFS_ERROR(EEXIST);
|
||||
|
@ -586,7 +585,7 @@ xfs_dir2_leafn_lookup_for_entry(
|
|||
} else {
|
||||
/* If the curbp is not the CI match block, drop it */
|
||||
if (state->extrablk.bp != curbp)
|
||||
xfs_da_brelse(tp, curbp);
|
||||
xfs_trans_brelse(tp, curbp);
|
||||
}
|
||||
} else {
|
||||
state->extravalid = 0;
|
||||
|
@ -602,7 +601,7 @@ xfs_dir2_leafn_lookup_for_entry(
|
|||
*/
|
||||
int
|
||||
xfs_dir2_leafn_lookup_int(
|
||||
xfs_dabuf_t *bp, /* leaf buffer */
|
||||
struct xfs_buf *bp, /* leaf buffer */
|
||||
xfs_da_args_t *args, /* operation arguments */
|
||||
int *indexp, /* out: leaf entry index */
|
||||
xfs_da_state_t *state) /* state to fill in */
|
||||
|
@ -620,9 +619,9 @@ xfs_dir2_leafn_lookup_int(
|
|||
static void
|
||||
xfs_dir2_leafn_moveents(
|
||||
xfs_da_args_t *args, /* operation arguments */
|
||||
xfs_dabuf_t *bp_s, /* source leaf buffer */
|
||||
struct xfs_buf *bp_s, /* source leaf buffer */
|
||||
int start_s, /* source leaf index */
|
||||
xfs_dabuf_t *bp_d, /* destination leaf buffer */
|
||||
struct xfs_buf *bp_d, /* destination leaf buffer */
|
||||
int start_d, /* destination leaf index */
|
||||
int count) /* count of leaves to copy */
|
||||
{
|
||||
|
@ -640,8 +639,8 @@ xfs_dir2_leafn_moveents(
|
|||
return;
|
||||
}
|
||||
tp = args->trans;
|
||||
leaf_s = bp_s->data;
|
||||
leaf_d = bp_d->data;
|
||||
leaf_s = bp_s->b_addr;
|
||||
leaf_d = bp_d->b_addr;
|
||||
/*
|
||||
* If the destination index is not the end of the current
|
||||
* destination leaf entries, open up a hole in the destination
|
||||
|
@ -702,14 +701,14 @@ xfs_dir2_leafn_moveents(
|
|||
*/
|
||||
int /* sort order */
|
||||
xfs_dir2_leafn_order(
|
||||
xfs_dabuf_t *leaf1_bp, /* leaf1 buffer */
|
||||
xfs_dabuf_t *leaf2_bp) /* leaf2 buffer */
|
||||
struct xfs_buf *leaf1_bp, /* leaf1 buffer */
|
||||
struct xfs_buf *leaf2_bp) /* leaf2 buffer */
|
||||
{
|
||||
xfs_dir2_leaf_t *leaf1; /* leaf1 structure */
|
||||
xfs_dir2_leaf_t *leaf2; /* leaf2 structure */
|
||||
|
||||
leaf1 = leaf1_bp->data;
|
||||
leaf2 = leaf2_bp->data;
|
||||
leaf1 = leaf1_bp->b_addr;
|
||||
leaf2 = leaf2_bp->b_addr;
|
||||
ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
if (be16_to_cpu(leaf1->hdr.count) > 0 &&
|
||||
|
@ -757,8 +756,8 @@ xfs_dir2_leafn_rebalance(
|
|||
blk1 = blk2;
|
||||
blk2 = tmp;
|
||||
}
|
||||
leaf1 = blk1->bp->data;
|
||||
leaf2 = blk2->bp->data;
|
||||
leaf1 = blk1->bp->b_addr;
|
||||
leaf2 = blk2->bp->b_addr;
|
||||
oldsum = be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count);
|
||||
#ifdef DEBUG
|
||||
oldstale = be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale);
|
||||
|
@ -834,14 +833,14 @@ xfs_dir2_leafn_rebalance(
|
|||
static int /* error */
|
||||
xfs_dir2_leafn_remove(
|
||||
xfs_da_args_t *args, /* operation arguments */
|
||||
xfs_dabuf_t *bp, /* leaf buffer */
|
||||
struct xfs_buf *bp, /* leaf buffer */
|
||||
int index, /* leaf entry index */
|
||||
xfs_da_state_blk_t *dblk, /* data block */
|
||||
int *rval) /* resulting block needs join */
|
||||
{
|
||||
xfs_dir2_data_hdr_t *hdr; /* data block header */
|
||||
xfs_dir2_db_t db; /* data block number */
|
||||
xfs_dabuf_t *dbp; /* data block buffer */
|
||||
struct xfs_buf *dbp; /* data block buffer */
|
||||
xfs_dir2_data_entry_t *dep; /* data block entry */
|
||||
xfs_inode_t *dp; /* incore directory inode */
|
||||
xfs_dir2_leaf_t *leaf; /* leaf structure */
|
||||
|
@ -858,7 +857,7 @@ xfs_dir2_leafn_remove(
|
|||
dp = args->dp;
|
||||
tp = args->trans;
|
||||
mp = dp->i_mount;
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
/*
|
||||
* Point to the entry we're removing.
|
||||
|
@ -884,7 +883,7 @@ xfs_dir2_leafn_remove(
|
|||
* in the data block in case it changes.
|
||||
*/
|
||||
dbp = dblk->bp;
|
||||
hdr = dbp->data;
|
||||
hdr = dbp->b_addr;
|
||||
dep = (xfs_dir2_data_entry_t *)((char *)hdr + off);
|
||||
longest = be16_to_cpu(hdr->bestfree[0].length);
|
||||
needlog = needscan = 0;
|
||||
|
@ -905,7 +904,7 @@ xfs_dir2_leafn_remove(
|
|||
*/
|
||||
if (longest < be16_to_cpu(hdr->bestfree[0].length)) {
|
||||
int error; /* error return value */
|
||||
xfs_dabuf_t *fbp; /* freeblock buffer */
|
||||
struct xfs_buf *fbp; /* freeblock buffer */
|
||||
xfs_dir2_db_t fdb; /* freeblock block number */
|
||||
int findex; /* index in freeblock entries */
|
||||
xfs_dir2_free_t *free; /* freeblock structure */
|
||||
|
@ -920,7 +919,7 @@ xfs_dir2_leafn_remove(
|
|||
-1, &fbp, XFS_DATA_FORK))) {
|
||||
return error;
|
||||
}
|
||||
free = fbp->data;
|
||||
free = fbp->b_addr;
|
||||
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
|
||||
ASSERT(be32_to_cpu(free->hdr.firstdb) ==
|
||||
xfs_dir2_free_max_bests(mp) *
|
||||
|
@ -948,9 +947,7 @@ xfs_dir2_leafn_remove(
|
|||
* In this case just drop the buffer and some one else
|
||||
* will eventually get rid of the empty block.
|
||||
*/
|
||||
else if (error == ENOSPC && args->total == 0)
|
||||
xfs_da_buf_done(dbp);
|
||||
else
|
||||
else if (!(error == ENOSPC && args->total == 0))
|
||||
return error;
|
||||
}
|
||||
/*
|
||||
|
@ -1018,11 +1015,6 @@ xfs_dir2_leafn_remove(
|
|||
*/
|
||||
if (logfree)
|
||||
xfs_dir2_free_log_bests(tp, fbp, findex, findex);
|
||||
/*
|
||||
* Drop the buffer if we still have it.
|
||||
*/
|
||||
if (fbp)
|
||||
xfs_da_buf_done(fbp);
|
||||
}
|
||||
xfs_dir2_leafn_check(dp, bp);
|
||||
/*
|
||||
|
@ -1114,7 +1106,7 @@ xfs_dir2_leafn_toosmall(
|
|||
{
|
||||
xfs_da_state_blk_t *blk; /* leaf block */
|
||||
xfs_dablk_t blkno; /* leaf block number */
|
||||
xfs_dabuf_t *bp; /* leaf buffer */
|
||||
struct xfs_buf *bp; /* leaf buffer */
|
||||
int bytes; /* bytes in use */
|
||||
int count; /* leaf live entry count */
|
||||
int error; /* error return value */
|
||||
|
@ -1130,7 +1122,7 @@ xfs_dir2_leafn_toosmall(
|
|||
* to coalesce with a sibling.
|
||||
*/
|
||||
blk = &state->path.blk[state->path.active - 1];
|
||||
info = blk->bp->data;
|
||||
info = blk->bp->b_addr;
|
||||
ASSERT(info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
leaf = (xfs_dir2_leaf_t *)info;
|
||||
count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
|
||||
|
@ -1189,7 +1181,7 @@ xfs_dir2_leafn_toosmall(
|
|||
leaf = (xfs_dir2_leaf_t *)info;
|
||||
count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
|
||||
bytes = state->blocksize - (state->blocksize >> 2);
|
||||
leaf = bp->data;
|
||||
leaf = bp->b_addr;
|
||||
ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
count += be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
|
||||
bytes -= count * (uint)sizeof(leaf->ents[0]);
|
||||
|
@ -1198,7 +1190,7 @@ xfs_dir2_leafn_toosmall(
|
|||
*/
|
||||
if (bytes >= 0)
|
||||
break;
|
||||
xfs_da_brelse(state->args->trans, bp);
|
||||
xfs_trans_brelse(state->args->trans, bp);
|
||||
}
|
||||
/*
|
||||
* Didn't like either block, give up.
|
||||
|
@ -1207,11 +1199,7 @@ xfs_dir2_leafn_toosmall(
|
|||
*action = 0;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Done with the sibling leaf block here, drop the dabuf
|
||||
* so path_shift can get it.
|
||||
*/
|
||||
xfs_da_buf_done(bp);
|
||||
|
||||
/*
|
||||
* Make altpath point to the block we want to keep (the lower
|
||||
* numbered block) and path point to the block we want to drop.
|
||||
|
@ -1247,8 +1235,8 @@ xfs_dir2_leafn_unbalance(
|
|||
args = state->args;
|
||||
ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
|
||||
ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC);
|
||||
drop_leaf = drop_blk->bp->data;
|
||||
save_leaf = save_blk->bp->data;
|
||||
drop_leaf = drop_blk->bp->b_addr;
|
||||
save_leaf = save_blk->bp->b_addr;
|
||||
ASSERT(drop_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
ASSERT(save_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
|
||||
/*
|
||||
|
@ -1356,13 +1344,13 @@ xfs_dir2_node_addname_int(
|
|||
{
|
||||
xfs_dir2_data_hdr_t *hdr; /* data block header */
|
||||
xfs_dir2_db_t dbno; /* data block number */
|
||||
xfs_dabuf_t *dbp; /* data block buffer */
|
||||
struct xfs_buf *dbp; /* data block buffer */
|
||||
xfs_dir2_data_entry_t *dep; /* data entry pointer */
|
||||
xfs_inode_t *dp; /* incore directory inode */
|
||||
xfs_dir2_data_unused_t *dup; /* data unused entry pointer */
|
||||
int error; /* error return value */
|
||||
xfs_dir2_db_t fbno; /* freespace block number */
|
||||
xfs_dabuf_t *fbp; /* freespace buffer */
|
||||
struct xfs_buf *fbp; /* freespace buffer */
|
||||
int findex; /* freespace entry index */
|
||||
xfs_dir2_free_t *free=NULL; /* freespace block structure */
|
||||
xfs_dir2_db_t ifbno; /* initial freespace block no */
|
||||
|
@ -1390,7 +1378,7 @@ xfs_dir2_node_addname_int(
|
|||
* Remember initial freespace block number.
|
||||
*/
|
||||
ifbno = fblk->blkno;
|
||||
free = fbp->data;
|
||||
free = fbp->b_addr;
|
||||
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
|
||||
findex = fblk->index;
|
||||
/*
|
||||
|
@ -1474,7 +1462,7 @@ xfs_dir2_node_addname_int(
|
|||
if (unlikely(fbp == NULL)) {
|
||||
continue;
|
||||
}
|
||||
free = fbp->data;
|
||||
free = fbp->b_addr;
|
||||
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
|
||||
findex = 0;
|
||||
}
|
||||
|
@ -1492,7 +1480,7 @@ xfs_dir2_node_addname_int(
|
|||
/*
|
||||
* Drop the block.
|
||||
*/
|
||||
xfs_da_brelse(tp, fbp);
|
||||
xfs_trans_brelse(tp, fbp);
|
||||
fbp = NULL;
|
||||
if (fblk && fblk->bp)
|
||||
fblk->bp = NULL;
|
||||
|
@ -1507,36 +1495,23 @@ xfs_dir2_node_addname_int(
|
|||
/*
|
||||
* Not allowed to allocate, return failure.
|
||||
*/
|
||||
if ((args->op_flags & XFS_DA_OP_JUSTCHECK) ||
|
||||
args->total == 0) {
|
||||
/*
|
||||
* Drop the freespace buffer unless it came from our
|
||||
* caller.
|
||||
*/
|
||||
if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
|
||||
xfs_da_buf_done(fbp);
|
||||
if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0)
|
||||
return XFS_ERROR(ENOSPC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and initialize the new data block.
|
||||
*/
|
||||
if (unlikely((error = xfs_dir2_grow_inode(args,
|
||||
XFS_DIR2_DATA_SPACE,
|
||||
&dbno)) ||
|
||||
(error = xfs_dir2_data_init(args, dbno, &dbp)))) {
|
||||
/*
|
||||
* Drop the freespace buffer unless it came from our
|
||||
* caller.
|
||||
*/
|
||||
if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
|
||||
xfs_da_buf_done(fbp);
|
||||
(error = xfs_dir2_data_init(args, dbno, &dbp))))
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* If (somehow) we have a freespace block, get rid of it.
|
||||
*/
|
||||
if (fbp)
|
||||
xfs_da_brelse(tp, fbp);
|
||||
xfs_trans_brelse(tp, fbp);
|
||||
if (fblk && fblk->bp)
|
||||
fblk->bp = NULL;
|
||||
|
||||
|
@ -1547,10 +1522,9 @@ xfs_dir2_node_addname_int(
|
|||
fbno = xfs_dir2_db_to_fdb(mp, dbno);
|
||||
if (unlikely(error = xfs_da_read_buf(tp, dp,
|
||||
xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
|
||||
XFS_DATA_FORK))) {
|
||||
xfs_da_buf_done(dbp);
|
||||
XFS_DATA_FORK)))
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there wasn't a freespace block, the read will
|
||||
* return a NULL fbp. Allocate and initialize a new one.
|
||||
|
@ -1598,7 +1572,7 @@ xfs_dir2_node_addname_int(
|
|||
* Initialize the new block to be empty, and remember
|
||||
* its first slot as our empty slot.
|
||||
*/
|
||||
free = fbp->data;
|
||||
free = fbp->b_addr;
|
||||
free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC);
|
||||
free->hdr.firstdb = cpu_to_be32(
|
||||
(fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
|
||||
|
@ -1606,7 +1580,7 @@ xfs_dir2_node_addname_int(
|
|||
free->hdr.nvalid = 0;
|
||||
free->hdr.nused = 0;
|
||||
} else {
|
||||
free = fbp->data;
|
||||
free = fbp->b_addr;
|
||||
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
|
||||
}
|
||||
|
||||
|
@ -1639,7 +1613,7 @@ xfs_dir2_node_addname_int(
|
|||
* We haven't allocated the data entry yet so this will
|
||||
* change again.
|
||||
*/
|
||||
hdr = dbp->data;
|
||||
hdr = dbp->b_addr;
|
||||
free->bests[findex] = hdr->bestfree[0].length;
|
||||
logfree = 1;
|
||||
}
|
||||
|
@ -1650,22 +1624,17 @@ xfs_dir2_node_addname_int(
|
|||
/*
|
||||
* If just checking, we succeeded.
|
||||
*/
|
||||
if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
|
||||
if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
|
||||
xfs_da_buf_done(fbp);
|
||||
if (args->op_flags & XFS_DA_OP_JUSTCHECK)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the data block in.
|
||||
*/
|
||||
if (unlikely(
|
||||
error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno),
|
||||
-1, &dbp, XFS_DATA_FORK))) {
|
||||
if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
|
||||
xfs_da_buf_done(fbp);
|
||||
error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno),
|
||||
-1, &dbp, XFS_DATA_FORK);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
hdr = dbp->data;
|
||||
hdr = dbp->b_addr;
|
||||
logfree = 0;
|
||||
}
|
||||
ASSERT(be16_to_cpu(hdr->bestfree[0].length) >= length);
|
||||
|
@ -1713,17 +1682,11 @@ xfs_dir2_node_addname_int(
|
|||
*/
|
||||
if (logfree)
|
||||
xfs_dir2_free_log_bests(tp, fbp, findex, findex);
|
||||
/*
|
||||
* If the caller didn't hand us the freespace block, drop it.
|
||||
*/
|
||||
if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
|
||||
xfs_da_buf_done(fbp);
|
||||
/*
|
||||
* Return the data block and offset in args, then drop the data block.
|
||||
*/
|
||||
args->blkno = (xfs_dablk_t)dbno;
|
||||
args->index = be16_to_cpu(*tagp);
|
||||
xfs_da_buf_done(dbp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1761,22 +1724,23 @@ xfs_dir2_node_lookup(
|
|||
/* If a CI match, dup the actual name and return EEXIST */
|
||||
xfs_dir2_data_entry_t *dep;
|
||||
|
||||
dep = (xfs_dir2_data_entry_t *)((char *)state->extrablk.bp->
|
||||
data + state->extrablk.index);
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)state->extrablk.bp->b_addr +
|
||||
state->extrablk.index);
|
||||
rval = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
|
||||
}
|
||||
/*
|
||||
* Release the btree blocks and leaf block.
|
||||
*/
|
||||
for (i = 0; i < state->path.active; i++) {
|
||||
xfs_da_brelse(args->trans, state->path.blk[i].bp);
|
||||
xfs_trans_brelse(args->trans, state->path.blk[i].bp);
|
||||
state->path.blk[i].bp = NULL;
|
||||
}
|
||||
/*
|
||||
* Release the data block if we have it.
|
||||
*/
|
||||
if (state->extravalid && state->extrablk.bp) {
|
||||
xfs_da_brelse(args->trans, state->extrablk.bp);
|
||||
xfs_trans_brelse(args->trans, state->extrablk.bp);
|
||||
state->extrablk.bp = NULL;
|
||||
}
|
||||
xfs_da_state_free(state);
|
||||
|
@ -1893,13 +1857,13 @@ xfs_dir2_node_replace(
|
|||
*/
|
||||
blk = &state->path.blk[state->path.active - 1];
|
||||
ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
|
||||
leaf = blk->bp->data;
|
||||
leaf = blk->bp->b_addr;
|
||||
lep = &leaf->ents[blk->index];
|
||||
ASSERT(state->extravalid);
|
||||
/*
|
||||
* Point to the data entry.
|
||||
*/
|
||||
hdr = state->extrablk.bp->data;
|
||||
hdr = state->extrablk.bp->b_addr;
|
||||
ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
|
||||
dep = (xfs_dir2_data_entry_t *)
|
||||
((char *)hdr +
|
||||
|
@ -1916,14 +1880,14 @@ xfs_dir2_node_replace(
|
|||
* Didn't find it, and we're holding a data block. Drop it.
|
||||
*/
|
||||
else if (state->extravalid) {
|
||||
xfs_da_brelse(args->trans, state->extrablk.bp);
|
||||
xfs_trans_brelse(args->trans, state->extrablk.bp);
|
||||
state->extrablk.bp = NULL;
|
||||
}
|
||||
/*
|
||||
* Release all the buffers in the cursor.
|
||||
*/
|
||||
for (i = 0; i < state->path.active; i++) {
|
||||
xfs_da_brelse(args->trans, state->path.blk[i].bp);
|
||||
xfs_trans_brelse(args->trans, state->path.blk[i].bp);
|
||||
state->path.blk[i].bp = NULL;
|
||||
}
|
||||
xfs_da_state_free(state);
|
||||
|
@ -1940,7 +1904,7 @@ xfs_dir2_node_trim_free(
|
|||
xfs_fileoff_t fo, /* free block number */
|
||||
int *rvalp) /* out: did something */
|
||||
{
|
||||
xfs_dabuf_t *bp; /* freespace buffer */
|
||||
struct xfs_buf *bp; /* freespace buffer */
|
||||
xfs_inode_t *dp; /* incore directory inode */
|
||||
int error; /* error return code */
|
||||
xfs_dir2_free_t *free; /* freespace structure */
|
||||
|
@ -1965,13 +1929,13 @@ xfs_dir2_node_trim_free(
|
|||
if (bp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
free = bp->data;
|
||||
free = bp->b_addr;
|
||||
ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
|
||||
/*
|
||||
* If there are used entries, there's nothing to do.
|
||||
*/
|
||||
if (be32_to_cpu(free->hdr.nused) > 0) {
|
||||
xfs_da_brelse(tp, bp);
|
||||
xfs_trans_brelse(tp, bp);
|
||||
*rvalp = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1987,7 +1951,7 @@ xfs_dir2_node_trim_free(
|
|||
* pieces. This is the last block of an extent.
|
||||
*/
|
||||
ASSERT(error != ENOSPC);
|
||||
xfs_da_brelse(tp, bp);
|
||||
xfs_trans_brelse(tp, bp);
|
||||
return error;
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -25,7 +25,7 @@ extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r);
|
|||
extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
|
||||
xfs_dir2_db_t *dbp);
|
||||
extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
|
||||
struct xfs_dabuf *bp);
|
||||
struct xfs_buf *bp);
|
||||
extern int xfs_dir_cilookup_result(struct xfs_da_args *args,
|
||||
const unsigned char *name, int len);
|
||||
|
||||
|
@ -37,11 +37,11 @@ extern int xfs_dir2_block_lookup(struct xfs_da_args *args);
|
|||
extern int xfs_dir2_block_removename(struct xfs_da_args *args);
|
||||
extern int xfs_dir2_block_replace(struct xfs_da_args *args);
|
||||
extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
|
||||
struct xfs_dabuf *lbp, struct xfs_dabuf *dbp);
|
||||
struct xfs_buf *lbp, struct xfs_buf *dbp);
|
||||
|
||||
/* xfs_dir2_data.c */
|
||||
#ifdef DEBUG
|
||||
extern void xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_dabuf *bp);
|
||||
extern void xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_buf *bp);
|
||||
#else
|
||||
#define xfs_dir2_data_check(dp,bp)
|
||||
#endif
|
||||
|
@ -51,43 +51,43 @@ xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr,
|
|||
extern void xfs_dir2_data_freescan(struct xfs_mount *mp,
|
||||
struct xfs_dir2_data_hdr *hdr, int *loghead);
|
||||
extern int xfs_dir2_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno,
|
||||
struct xfs_dabuf **bpp);
|
||||
extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_dabuf *bp,
|
||||
struct xfs_buf **bpp);
|
||||
extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_buf *bp,
|
||||
struct xfs_dir2_data_entry *dep);
|
||||
extern void xfs_dir2_data_log_header(struct xfs_trans *tp,
|
||||
struct xfs_dabuf *bp);
|
||||
extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_dabuf *bp,
|
||||
struct xfs_buf *bp);
|
||||
extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_buf *bp,
|
||||
struct xfs_dir2_data_unused *dup);
|
||||
extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_dabuf *bp,
|
||||
extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_buf *bp,
|
||||
xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len,
|
||||
int *needlogp, int *needscanp);
|
||||
extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_dabuf *bp,
|
||||
extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp,
|
||||
struct xfs_dir2_data_unused *dup, xfs_dir2_data_aoff_t offset,
|
||||
xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
|
||||
|
||||
/* xfs_dir2_leaf.c */
|
||||
extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args,
|
||||
struct xfs_dabuf *dbp);
|
||||
struct xfs_buf *dbp);
|
||||
extern int xfs_dir2_leaf_addname(struct xfs_da_args *args);
|
||||
extern void xfs_dir2_leaf_compact(struct xfs_da_args *args,
|
||||
struct xfs_dabuf *bp);
|
||||
extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp,
|
||||
struct xfs_buf *bp);
|
||||
extern void xfs_dir2_leaf_compact_x1(struct xfs_buf *bp, int *indexp,
|
||||
int *lowstalep, int *highstalep, int *lowlogp, int *highlogp);
|
||||
extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, void *dirent,
|
||||
size_t bufsize, xfs_off_t *offset, filldir_t filldir);
|
||||
extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno,
|
||||
struct xfs_dabuf **bpp, int magic);
|
||||
extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp,
|
||||
struct xfs_buf **bpp, int magic);
|
||||
extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp,
|
||||
int first, int last);
|
||||
extern void xfs_dir2_leaf_log_header(struct xfs_trans *tp,
|
||||
struct xfs_dabuf *bp);
|
||||
struct xfs_buf *bp);
|
||||
extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args);
|
||||
extern int xfs_dir2_leaf_removename(struct xfs_da_args *args);
|
||||
extern int xfs_dir2_leaf_replace(struct xfs_da_args *args);
|
||||
extern int xfs_dir2_leaf_search_hash(struct xfs_da_args *args,
|
||||
struct xfs_dabuf *lbp);
|
||||
struct xfs_buf *lbp);
|
||||
extern int xfs_dir2_leaf_trim_data(struct xfs_da_args *args,
|
||||
struct xfs_dabuf *lbp, xfs_dir2_db_t db);
|
||||
struct xfs_buf *lbp, xfs_dir2_db_t db);
|
||||
extern struct xfs_dir2_leaf_entry *
|
||||
xfs_dir2_leaf_find_entry(struct xfs_dir2_leaf *leaf, int index, int compact,
|
||||
int lowstale, int highstale,
|
||||
|
@ -96,13 +96,13 @@ extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state);
|
|||
|
||||
/* xfs_dir2_node.c */
|
||||
extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args,
|
||||
struct xfs_dabuf *lbp);
|
||||
extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_dabuf *bp, int *count);
|
||||
extern int xfs_dir2_leafn_lookup_int(struct xfs_dabuf *bp,
|
||||
struct xfs_buf *lbp);
|
||||
extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_buf *bp, int *count);
|
||||
extern int xfs_dir2_leafn_lookup_int(struct xfs_buf *bp,
|
||||
struct xfs_da_args *args, int *indexp,
|
||||
struct xfs_da_state *state);
|
||||
extern int xfs_dir2_leafn_order(struct xfs_dabuf *leaf1_bp,
|
||||
struct xfs_dabuf *leaf2_bp);
|
||||
extern int xfs_dir2_leafn_order(struct xfs_buf *leaf1_bp,
|
||||
struct xfs_buf *leaf2_bp);
|
||||
extern int xfs_dir2_leafn_split(struct xfs_da_state *state,
|
||||
struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk);
|
||||
extern int xfs_dir2_leafn_toosmall(struct xfs_da_state *state, int *action);
|
||||
|
@ -122,7 +122,7 @@ extern xfs_ino_t xfs_dir2_sfe_get_ino(struct xfs_dir2_sf_hdr *sfp,
|
|||
struct xfs_dir2_sf_entry *sfep);
|
||||
extern int xfs_dir2_block_sfsize(struct xfs_inode *dp,
|
||||
struct xfs_dir2_data_hdr *block, struct xfs_dir2_sf_hdr *sfhp);
|
||||
extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_dabuf *bp,
|
||||
extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_buf *bp,
|
||||
int size, xfs_dir2_sf_hdr_t *sfhp);
|
||||
extern int xfs_dir2_sf_addname(struct xfs_da_args *args);
|
||||
extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino);
|
||||
|
|
|
@ -222,7 +222,7 @@ xfs_dir2_block_sfsize(
|
|||
int /* error */
|
||||
xfs_dir2_block_to_sf(
|
||||
xfs_da_args_t *args, /* operation arguments */
|
||||
xfs_dabuf_t *bp, /* block buffer */
|
||||
struct xfs_buf *bp,
|
||||
int size, /* shortform directory size */
|
||||
xfs_dir2_sf_hdr_t *sfhp) /* shortform directory hdr */
|
||||
{
|
||||
|
@ -249,7 +249,7 @@ xfs_dir2_block_to_sf(
|
|||
* and add local data.
|
||||
*/
|
||||
hdr = kmem_alloc(mp->m_dirblksize, KM_SLEEP);
|
||||
memcpy(hdr, bp->data, mp->m_dirblksize);
|
||||
memcpy(hdr, bp->b_addr, mp->m_dirblksize);
|
||||
logflags = XFS_ILOG_CORE;
|
||||
if ((error = xfs_dir2_shrink_inode(args, mp->m_dirdatablk, bp))) {
|
||||
ASSERT(error != ENOSPC);
|
||||
|
|
|
@ -236,7 +236,6 @@ xfs_file_aio_read(
|
|||
ssize_t ret = 0;
|
||||
int ioflags = 0;
|
||||
xfs_fsize_t n;
|
||||
unsigned long seg;
|
||||
|
||||
XFS_STATS_INC(xs_read_calls);
|
||||
|
||||
|
@ -247,19 +246,9 @@ xfs_file_aio_read(
|
|||
if (file->f_mode & FMODE_NOCMTIME)
|
||||
ioflags |= IO_INVIS;
|
||||
|
||||
/* START copy & waste from filemap.c */
|
||||
for (seg = 0; seg < nr_segs; seg++) {
|
||||
const struct iovec *iv = &iovp[seg];
|
||||
|
||||
/*
|
||||
* If any segment has a negative length, or the cumulative
|
||||
* length ever wraps negative then return -EINVAL.
|
||||
*/
|
||||
size += iv->iov_len;
|
||||
if (unlikely((ssize_t)(size|iv->iov_len) < 0))
|
||||
return XFS_ERROR(-EINVAL);
|
||||
}
|
||||
/* END copy & waste from filemap.c */
|
||||
ret = generic_segment_checks(iovp, &nr_segs, &size, VERIFY_WRITE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (unlikely(ioflags & IO_ISDIRECT)) {
|
||||
xfs_buftarg_t *target =
|
||||
|
@ -273,7 +262,7 @@ xfs_file_aio_read(
|
|||
}
|
||||
}
|
||||
|
||||
n = XFS_MAXIOFFSET(mp) - iocb->ki_pos;
|
||||
n = mp->m_super->s_maxbytes - iocb->ki_pos;
|
||||
if (n <= 0 || size == 0)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -442,14 +442,13 @@ xfs_ialloc_next_ag(
|
|||
* Select an allocation group to look for a free inode in, based on the parent
|
||||
* inode and then mode. Return the allocation group buffer.
|
||||
*/
|
||||
STATIC xfs_buf_t * /* allocation group buffer */
|
||||
STATIC xfs_agnumber_t
|
||||
xfs_ialloc_ag_select(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_ino_t parent, /* parent directory inode number */
|
||||
umode_t mode, /* bits set to indicate file type */
|
||||
int okalloc) /* ok to allocate more space */
|
||||
{
|
||||
xfs_buf_t *agbp; /* allocation group header buffer */
|
||||
xfs_agnumber_t agcount; /* number of ag's in the filesystem */
|
||||
xfs_agnumber_t agno; /* current ag number */
|
||||
int flags; /* alloc buffer locking flags */
|
||||
|
@ -459,6 +458,7 @@ xfs_ialloc_ag_select(
|
|||
int needspace; /* file mode implies space allocated */
|
||||
xfs_perag_t *pag; /* per allocation group data */
|
||||
xfs_agnumber_t pagno; /* parent (starting) ag number */
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Files of these types need at least one block if length > 0
|
||||
|
@ -474,7 +474,9 @@ xfs_ialloc_ag_select(
|
|||
if (pagno >= agcount)
|
||||
pagno = 0;
|
||||
}
|
||||
|
||||
ASSERT(pagno < agcount);
|
||||
|
||||
/*
|
||||
* Loop through allocation groups, looking for one with a little
|
||||
* free space in it. Note we don't look for free inodes, exactly.
|
||||
|
@ -486,51 +488,45 @@ xfs_ialloc_ag_select(
|
|||
flags = XFS_ALLOC_FLAG_TRYLOCK;
|
||||
for (;;) {
|
||||
pag = xfs_perag_get(mp, agno);
|
||||
if (!pag->pagi_init) {
|
||||
if (xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
|
||||
agbp = NULL;
|
||||
goto nextag;
|
||||
}
|
||||
} else
|
||||
agbp = NULL;
|
||||
|
||||
if (!pag->pagi_inodeok) {
|
||||
xfs_ialloc_next_ag(mp);
|
||||
goto unlock_nextag;
|
||||
goto nextag;
|
||||
}
|
||||
|
||||
if (!pag->pagi_init) {
|
||||
error = xfs_ialloc_pagi_init(mp, tp, agno);
|
||||
if (error)
|
||||
goto nextag;
|
||||
}
|
||||
|
||||
if (pag->pagi_freecount) {
|
||||
xfs_perag_put(pag);
|
||||
return agno;
|
||||
}
|
||||
|
||||
if (!okalloc)
|
||||
goto nextag;
|
||||
|
||||
if (!pag->pagf_init) {
|
||||
error = xfs_alloc_pagf_init(mp, tp, agno, flags);
|
||||
if (error)
|
||||
goto nextag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is there enough free space for the file plus a block
|
||||
* of inodes (if we need to allocate some)?
|
||||
* Is there enough free space for the file plus a block of
|
||||
* inodes? (if we need to allocate some)?
|
||||
*/
|
||||
ineed = pag->pagi_freecount ? 0 : XFS_IALLOC_BLOCKS(mp);
|
||||
if (ineed && !pag->pagf_init) {
|
||||
if (agbp == NULL &&
|
||||
xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
|
||||
agbp = NULL;
|
||||
goto nextag;
|
||||
}
|
||||
(void)xfs_alloc_pagf_init(mp, tp, agno, flags);
|
||||
ineed = XFS_IALLOC_BLOCKS(mp);
|
||||
longest = pag->pagf_longest;
|
||||
if (!longest)
|
||||
longest = pag->pagf_flcount > 0;
|
||||
|
||||
if (pag->pagf_freeblks >= needspace + ineed &&
|
||||
longest >= ineed) {
|
||||
xfs_perag_put(pag);
|
||||
return agno;
|
||||
}
|
||||
if (!ineed || pag->pagf_init) {
|
||||
if (ineed && !(longest = pag->pagf_longest))
|
||||
longest = pag->pagf_flcount > 0;
|
||||
if (!ineed ||
|
||||
(pag->pagf_freeblks >= needspace + ineed &&
|
||||
longest >= ineed &&
|
||||
okalloc)) {
|
||||
if (agbp == NULL &&
|
||||
xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
|
||||
agbp = NULL;
|
||||
goto nextag;
|
||||
}
|
||||
xfs_perag_put(pag);
|
||||
return agbp;
|
||||
}
|
||||
}
|
||||
unlock_nextag:
|
||||
if (agbp)
|
||||
xfs_trans_brelse(tp, agbp);
|
||||
nextag:
|
||||
xfs_perag_put(pag);
|
||||
/*
|
||||
|
@ -538,13 +534,13 @@ nextag:
|
|||
* down.
|
||||
*/
|
||||
if (XFS_FORCED_SHUTDOWN(mp))
|
||||
return NULL;
|
||||
return NULLAGNUMBER;
|
||||
agno++;
|
||||
if (agno >= agcount)
|
||||
agno = 0;
|
||||
if (agno == pagno) {
|
||||
if (flags == 0)
|
||||
return NULL;
|
||||
return NULLAGNUMBER;
|
||||
flags = 0;
|
||||
}
|
||||
}
|
||||
|
@ -607,195 +603,39 @@ xfs_ialloc_get_rec(
|
|||
}
|
||||
|
||||
/*
|
||||
* Visible inode allocation functions.
|
||||
*/
|
||||
/*
|
||||
* Find a free (set) bit in the inode bitmask.
|
||||
*/
|
||||
static inline int xfs_ialloc_find_free(xfs_inofree_t *fp)
|
||||
{
|
||||
return xfs_lowbit64(*fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate an inode on disk.
|
||||
* Mode is used to tell whether the new inode will need space, and whether
|
||||
* it is a directory.
|
||||
* Allocate an inode.
|
||||
*
|
||||
* The arguments IO_agbp and alloc_done are defined to work within
|
||||
* the constraint of one allocation per transaction.
|
||||
* xfs_dialloc() is designed to be called twice if it has to do an
|
||||
* allocation to make more free inodes. On the first call,
|
||||
* IO_agbp should be set to NULL. If an inode is available,
|
||||
* i.e., xfs_dialloc() did not need to do an allocation, an inode
|
||||
* number is returned. In this case, IO_agbp would be set to the
|
||||
* current ag_buf and alloc_done set to false.
|
||||
* If an allocation needed to be done, xfs_dialloc would return
|
||||
* the current ag_buf in IO_agbp and set alloc_done to true.
|
||||
* The caller should then commit the current transaction, allocate a new
|
||||
* transaction, and call xfs_dialloc() again, passing in the previous
|
||||
* value of IO_agbp. IO_agbp should be held across the transactions.
|
||||
* Since the agbp is locked across the two calls, the second call is
|
||||
* guaranteed to have a free inode available.
|
||||
*
|
||||
* Once we successfully pick an inode its number is returned and the
|
||||
* on-disk data structures are updated. The inode itself is not read
|
||||
* in, since doing so would break ordering constraints with xfs_reclaim.
|
||||
* The caller selected an AG for us, and made sure that free inodes are
|
||||
* available.
|
||||
*/
|
||||
int
|
||||
xfs_dialloc(
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_ino_t parent, /* parent inode (directory) */
|
||||
umode_t mode, /* mode bits for new inode */
|
||||
int okalloc, /* ok to allocate more space */
|
||||
xfs_buf_t **IO_agbp, /* in/out ag header's buffer */
|
||||
boolean_t *alloc_done, /* true if we needed to replenish
|
||||
inode freelist */
|
||||
xfs_ino_t *inop) /* inode number allocated */
|
||||
STATIC int
|
||||
xfs_dialloc_ag(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *agbp,
|
||||
xfs_ino_t parent,
|
||||
xfs_ino_t *inop)
|
||||
{
|
||||
xfs_agnumber_t agcount; /* number of allocation groups */
|
||||
xfs_buf_t *agbp; /* allocation group header's buffer */
|
||||
xfs_agnumber_t agno; /* allocation group number */
|
||||
xfs_agi_t *agi; /* allocation group header structure */
|
||||
xfs_btree_cur_t *cur; /* inode allocation btree cursor */
|
||||
int error; /* error return value */
|
||||
int i; /* result code */
|
||||
int ialloced; /* inode allocation status */
|
||||
int noroom = 0; /* no space for inode blk allocation */
|
||||
xfs_ino_t ino; /* fs-relative inode to be returned */
|
||||
/* REFERENCED */
|
||||
int j; /* result code */
|
||||
xfs_mount_t *mp; /* file system mount structure */
|
||||
int offset; /* index of inode in chunk */
|
||||
xfs_agino_t pagino; /* parent's AG relative inode # */
|
||||
xfs_agnumber_t pagno; /* parent's AG number */
|
||||
xfs_inobt_rec_incore_t rec; /* inode allocation record */
|
||||
xfs_agnumber_t tagno; /* testing allocation group number */
|
||||
xfs_btree_cur_t *tcur; /* temp cursor */
|
||||
xfs_inobt_rec_incore_t trec; /* temp inode allocation record */
|
||||
struct xfs_perag *pag;
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp);
|
||||
xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno);
|
||||
xfs_agnumber_t pagno = XFS_INO_TO_AGNO(mp, parent);
|
||||
xfs_agino_t pagino = XFS_INO_TO_AGINO(mp, parent);
|
||||
struct xfs_perag *pag;
|
||||
struct xfs_btree_cur *cur, *tcur;
|
||||
struct xfs_inobt_rec_incore rec, trec;
|
||||
xfs_ino_t ino;
|
||||
int error;
|
||||
int offset;
|
||||
int i, j;
|
||||
|
||||
|
||||
if (*IO_agbp == NULL) {
|
||||
/*
|
||||
* We do not have an agbp, so select an initial allocation
|
||||
* group for inode allocation.
|
||||
*/
|
||||
agbp = xfs_ialloc_ag_select(tp, parent, mode, okalloc);
|
||||
/*
|
||||
* Couldn't find an allocation group satisfying the
|
||||
* criteria, give up.
|
||||
*/
|
||||
if (!agbp) {
|
||||
*inop = NULLFSINO;
|
||||
return 0;
|
||||
}
|
||||
agi = XFS_BUF_TO_AGI(agbp);
|
||||
ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
|
||||
} else {
|
||||
/*
|
||||
* Continue where we left off before. In this case, we
|
||||
* know that the allocation group has free inodes.
|
||||
*/
|
||||
agbp = *IO_agbp;
|
||||
agi = XFS_BUF_TO_AGI(agbp);
|
||||
ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
|
||||
ASSERT(be32_to_cpu(agi->agi_freecount) > 0);
|
||||
}
|
||||
mp = tp->t_mountp;
|
||||
agcount = mp->m_sb.sb_agcount;
|
||||
agno = be32_to_cpu(agi->agi_seqno);
|
||||
tagno = agno;
|
||||
pagno = XFS_INO_TO_AGNO(mp, parent);
|
||||
pagino = XFS_INO_TO_AGINO(mp, parent);
|
||||
|
||||
/*
|
||||
* If we have already hit the ceiling of inode blocks then clear
|
||||
* okalloc so we scan all available agi structures for a free
|
||||
* inode.
|
||||
*/
|
||||
|
||||
if (mp->m_maxicount &&
|
||||
mp->m_sb.sb_icount + XFS_IALLOC_INODES(mp) > mp->m_maxicount) {
|
||||
noroom = 1;
|
||||
okalloc = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop until we find an allocation group that either has free inodes
|
||||
* or in which we can allocate some inodes. Iterate through the
|
||||
* allocation groups upward, wrapping at the end.
|
||||
*/
|
||||
*alloc_done = B_FALSE;
|
||||
while (!agi->agi_freecount) {
|
||||
/*
|
||||
* Don't do anything if we're not supposed to allocate
|
||||
* any blocks, just go on to the next ag.
|
||||
*/
|
||||
if (okalloc) {
|
||||
/*
|
||||
* Try to allocate some new inodes in the allocation
|
||||
* group.
|
||||
*/
|
||||
if ((error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced))) {
|
||||
xfs_trans_brelse(tp, agbp);
|
||||
if (error == ENOSPC) {
|
||||
*inop = NULLFSINO;
|
||||
return 0;
|
||||
} else
|
||||
return error;
|
||||
}
|
||||
if (ialloced) {
|
||||
/*
|
||||
* We successfully allocated some inodes, return
|
||||
* the current context to the caller so that it
|
||||
* can commit the current transaction and call
|
||||
* us again where we left off.
|
||||
*/
|
||||
ASSERT(be32_to_cpu(agi->agi_freecount) > 0);
|
||||
*alloc_done = B_TRUE;
|
||||
*IO_agbp = agbp;
|
||||
*inop = NULLFSINO;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If it failed, give up on this ag.
|
||||
*/
|
||||
xfs_trans_brelse(tp, agbp);
|
||||
/*
|
||||
* Go on to the next ag: get its ag header.
|
||||
*/
|
||||
nextag:
|
||||
if (++tagno == agcount)
|
||||
tagno = 0;
|
||||
if (tagno == agno) {
|
||||
*inop = NULLFSINO;
|
||||
return noroom ? ENOSPC : 0;
|
||||
}
|
||||
pag = xfs_perag_get(mp, tagno);
|
||||
if (pag->pagi_inodeok == 0) {
|
||||
xfs_perag_put(pag);
|
||||
goto nextag;
|
||||
}
|
||||
error = xfs_ialloc_read_agi(mp, tp, tagno, &agbp);
|
||||
xfs_perag_put(pag);
|
||||
if (error)
|
||||
goto nextag;
|
||||
agi = XFS_BUF_TO_AGI(agbp);
|
||||
ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
|
||||
}
|
||||
/*
|
||||
* Here with an allocation group that has a free inode.
|
||||
* Reset agno since we may have chosen a new ag in the
|
||||
* loop above.
|
||||
*/
|
||||
agno = tagno;
|
||||
*IO_agbp = NULL;
|
||||
pag = xfs_perag_get(mp, agno);
|
||||
|
||||
ASSERT(pag->pagi_init);
|
||||
ASSERT(pag->pagi_inodeok);
|
||||
ASSERT(pag->pagi_freecount > 0);
|
||||
|
||||
restart_pagno:
|
||||
cur = xfs_inobt_init_cursor(mp, tp, agbp, be32_to_cpu(agi->agi_seqno));
|
||||
cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
|
||||
/*
|
||||
* If pagino is 0 (this is the root inode allocation) use newino.
|
||||
* This must work because we've just allocated some.
|
||||
|
@ -995,7 +835,7 @@ newino:
|
|||
}
|
||||
|
||||
alloc_inode:
|
||||
offset = xfs_ialloc_find_free(&rec.ir_free);
|
||||
offset = xfs_lowbit64(rec.ir_free);
|
||||
ASSERT(offset >= 0);
|
||||
ASSERT(offset < XFS_INODES_PER_CHUNK);
|
||||
ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) %
|
||||
|
@ -1027,6 +867,164 @@ error0:
|
|||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate an inode on disk.
|
||||
*
|
||||
* Mode is used to tell whether the new inode will need space, and whether it
|
||||
* is a directory.
|
||||
*
|
||||
* This function is designed to be called twice if it has to do an allocation
|
||||
* to make more free inodes. On the first call, *IO_agbp should be set to NULL.
|
||||
* If an inode is available without having to performn an allocation, an inode
|
||||
* number is returned. In this case, *IO_agbp would be NULL. If an allocation
|
||||
* needes to be done, xfs_dialloc would return the current AGI buffer in
|
||||
* *IO_agbp. The caller should then commit the current transaction, allocate a
|
||||
* new transaction, and call xfs_dialloc() again, passing in the previous value
|
||||
* of *IO_agbp. IO_agbp should be held across the transactions. Since the AGI
|
||||
* buffer is locked across the two calls, the second call is guaranteed to have
|
||||
* a free inode available.
|
||||
*
|
||||
* Once we successfully pick an inode its number is returned and the on-disk
|
||||
* data structures are updated. The inode itself is not read in, since doing so
|
||||
* would break ordering constraints with xfs_reclaim.
|
||||
*/
|
||||
int
|
||||
xfs_dialloc(
|
||||
struct xfs_trans *tp,
|
||||
xfs_ino_t parent,
|
||||
umode_t mode,
|
||||
int okalloc,
|
||||
struct xfs_buf **IO_agbp,
|
||||
xfs_ino_t *inop)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_buf *agbp;
|
||||
xfs_agnumber_t agno;
|
||||
int error;
|
||||
int ialloced;
|
||||
int noroom = 0;
|
||||
xfs_agnumber_t start_agno;
|
||||
struct xfs_perag *pag;
|
||||
|
||||
if (*IO_agbp) {
|
||||
/*
|
||||
* If the caller passes in a pointer to the AGI buffer,
|
||||
* continue where we left off before. In this case, we
|
||||
* know that the allocation group has free inodes.
|
||||
*/
|
||||
agbp = *IO_agbp;
|
||||
goto out_alloc;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do not have an agbp, so select an initial allocation
|
||||
* group for inode allocation.
|
||||
*/
|
||||
start_agno = xfs_ialloc_ag_select(tp, parent, mode, okalloc);
|
||||
if (start_agno == NULLAGNUMBER) {
|
||||
*inop = NULLFSINO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have already hit the ceiling of inode blocks then clear
|
||||
* okalloc so we scan all available agi structures for a free
|
||||
* inode.
|
||||
*/
|
||||
if (mp->m_maxicount &&
|
||||
mp->m_sb.sb_icount + XFS_IALLOC_INODES(mp) > mp->m_maxicount) {
|
||||
noroom = 1;
|
||||
okalloc = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop until we find an allocation group that either has free inodes
|
||||
* or in which we can allocate some inodes. Iterate through the
|
||||
* allocation groups upward, wrapping at the end.
|
||||
*/
|
||||
agno = start_agno;
|
||||
for (;;) {
|
||||
pag = xfs_perag_get(mp, agno);
|
||||
if (!pag->pagi_inodeok) {
|
||||
xfs_ialloc_next_ag(mp);
|
||||
goto nextag;
|
||||
}
|
||||
|
||||
if (!pag->pagi_init) {
|
||||
error = xfs_ialloc_pagi_init(mp, tp, agno);
|
||||
if (error)
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a first racy fast path check if this AG is usable.
|
||||
*/
|
||||
if (!pag->pagi_freecount && !okalloc)
|
||||
goto nextag;
|
||||
|
||||
error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
|
||||
if (error)
|
||||
goto out_error;
|
||||
|
||||
/*
|
||||
* Once the AGI has been read in we have to recheck
|
||||
* pagi_freecount with the AGI buffer lock held.
|
||||
*/
|
||||
if (pag->pagi_freecount) {
|
||||
xfs_perag_put(pag);
|
||||
goto out_alloc;
|
||||
}
|
||||
|
||||
if (!okalloc) {
|
||||
xfs_trans_brelse(tp, agbp);
|
||||
goto nextag;
|
||||
}
|
||||
|
||||
error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced);
|
||||
if (error) {
|
||||
xfs_trans_brelse(tp, agbp);
|
||||
|
||||
if (error != ENOSPC)
|
||||
goto out_error;
|
||||
|
||||
xfs_perag_put(pag);
|
||||
*inop = NULLFSINO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ialloced) {
|
||||
/*
|
||||
* We successfully allocated some inodes, return
|
||||
* the current context to the caller so that it
|
||||
* can commit the current transaction and call
|
||||
* us again where we left off.
|
||||
*/
|
||||
ASSERT(pag->pagi_freecount > 0);
|
||||
xfs_perag_put(pag);
|
||||
|
||||
*IO_agbp = agbp;
|
||||
*inop = NULLFSINO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nextag:
|
||||
xfs_perag_put(pag);
|
||||
if (++agno == mp->m_sb.sb_agcount)
|
||||
agno = 0;
|
||||
if (agno == start_agno) {
|
||||
*inop = NULLFSINO;
|
||||
return noroom ? ENOSPC : 0;
|
||||
}
|
||||
}
|
||||
|
||||
out_alloc:
|
||||
*IO_agbp = NULL;
|
||||
return xfs_dialloc_ag(tp, agbp, parent, inop);
|
||||
out_error:
|
||||
xfs_perag_put(pag);
|
||||
return XFS_ERROR(error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free disk inode. Carefully avoids touching the incore inode, all
|
||||
* manipulations incore are the caller's responsibility.
|
||||
|
|
|
@ -75,8 +75,6 @@ xfs_dialloc(
|
|||
umode_t mode, /* mode bits for new inode */
|
||||
int okalloc, /* ok to allocate more space */
|
||||
struct xfs_buf **agbp, /* buf for a.g. inode header */
|
||||
boolean_t *alloc_done, /* an allocation was done to replenish
|
||||
the free inodes */
|
||||
xfs_ino_t *inop); /* inode number allocated */
|
||||
|
||||
/*
|
||||
|
|
|
@ -40,17 +40,6 @@
|
|||
#include "xfs_trace.h"
|
||||
|
||||
|
||||
/*
|
||||
* Define xfs inode iolock lockdep classes. We need to ensure that all active
|
||||
* inodes are considered the same for lockdep purposes, including inodes that
|
||||
* are recycled through the XFS_IRECLAIMABLE state. This is the the only way to
|
||||
* guarantee the locks are considered the same when there are multiple lock
|
||||
* initialisation siteѕ. Also, define a reclaimable inode class so it is
|
||||
* obvious in lockdep reports which class the report is against.
|
||||
*/
|
||||
static struct lock_class_key xfs_iolock_active;
|
||||
struct lock_class_key xfs_iolock_reclaimable;
|
||||
|
||||
/*
|
||||
* Allocate and initialise an xfs_inode.
|
||||
*/
|
||||
|
@ -80,8 +69,6 @@ xfs_inode_alloc(
|
|||
ASSERT(ip->i_ino == 0);
|
||||
|
||||
mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
|
||||
lockdep_set_class_and_name(&ip->i_iolock.mr_lock,
|
||||
&xfs_iolock_active, "xfs_iolock_active");
|
||||
|
||||
/* initialise the xfs inode */
|
||||
ip->i_ino = ino;
|
||||
|
@ -250,8 +237,6 @@ xfs_iget_cache_hit(
|
|||
|
||||
ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
|
||||
mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
|
||||
lockdep_set_class_and_name(&ip->i_iolock.mr_lock,
|
||||
&xfs_iolock_active, "xfs_iolock_active");
|
||||
|
||||
spin_unlock(&ip->i_flags_lock);
|
||||
spin_unlock(&pag->pag_ici_lock);
|
||||
|
|
|
@ -132,23 +132,28 @@ xfs_inobp_check(
|
|||
#endif
|
||||
|
||||
/*
|
||||
* Find the buffer associated with the given inode map
|
||||
* We do basic validation checks on the buffer once it has been
|
||||
* retrieved from disk.
|
||||
* This routine is called to map an inode to the buffer containing the on-disk
|
||||
* version of the inode. It returns a pointer to the buffer containing the
|
||||
* on-disk inode in the bpp parameter, and in the dipp parameter it returns a
|
||||
* pointer to the on-disk inode within that buffer.
|
||||
*
|
||||
* If a non-zero error is returned, then the contents of bpp and dipp are
|
||||
* undefined.
|
||||
*/
|
||||
STATIC int
|
||||
int
|
||||
xfs_imap_to_bp(
|
||||
xfs_mount_t *mp,
|
||||
xfs_trans_t *tp,
|
||||
struct xfs_imap *imap,
|
||||
xfs_buf_t **bpp,
|
||||
uint buf_flags,
|
||||
uint iget_flags)
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_imap *imap,
|
||||
struct xfs_dinode **dipp,
|
||||
struct xfs_buf **bpp,
|
||||
uint buf_flags,
|
||||
uint iget_flags)
|
||||
{
|
||||
int error;
|
||||
int i;
|
||||
int ni;
|
||||
xfs_buf_t *bp;
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
int i;
|
||||
int ni;
|
||||
|
||||
buf_flags |= XBF_UNMAPPED;
|
||||
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno,
|
||||
|
@ -189,8 +194,8 @@ xfs_imap_to_bp(
|
|||
xfs_trans_brelse(tp, bp);
|
||||
return XFS_ERROR(EINVAL);
|
||||
}
|
||||
XFS_CORRUPTION_ERROR("xfs_imap_to_bp",
|
||||
XFS_ERRLEVEL_HIGH, mp, dip);
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH,
|
||||
mp, dip);
|
||||
#ifdef DEBUG
|
||||
xfs_emerg(mp,
|
||||
"bad inode magic/vsn daddr %lld #%d (magic=%x)",
|
||||
|
@ -204,96 +209,9 @@ xfs_imap_to_bp(
|
|||
}
|
||||
|
||||
xfs_inobp_check(mp, bp);
|
||||
|
||||
*bpp = bp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called to map an inode number within a file
|
||||
* system to the buffer containing the on-disk version of the
|
||||
* inode. It returns a pointer to the buffer containing the
|
||||
* on-disk inode in the bpp parameter, and in the dip parameter
|
||||
* it returns a pointer to the on-disk inode within that buffer.
|
||||
*
|
||||
* If a non-zero error is returned, then the contents of bpp and
|
||||
* dipp are undefined.
|
||||
*
|
||||
* Use xfs_imap() to determine the size and location of the
|
||||
* buffer to read from disk.
|
||||
*/
|
||||
int
|
||||
xfs_inotobp(
|
||||
xfs_mount_t *mp,
|
||||
xfs_trans_t *tp,
|
||||
xfs_ino_t ino,
|
||||
xfs_dinode_t **dipp,
|
||||
xfs_buf_t **bpp,
|
||||
int *offset,
|
||||
uint imap_flags)
|
||||
{
|
||||
struct xfs_imap imap;
|
||||
xfs_buf_t *bp;
|
||||
int error;
|
||||
|
||||
imap.im_blkno = 0;
|
||||
error = xfs_imap(mp, tp, ino, &imap, imap_flags);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = xfs_imap_to_bp(mp, tp, &imap, &bp, 0, imap_flags);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
*dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
|
||||
*bpp = bp;
|
||||
*offset = imap.im_boffset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine is called to map an inode to the buffer containing
|
||||
* the on-disk version of the inode. It returns a pointer to the
|
||||
* buffer containing the on-disk inode in the bpp parameter, and in
|
||||
* the dip parameter it returns a pointer to the on-disk inode within
|
||||
* that buffer.
|
||||
*
|
||||
* If a non-zero error is returned, then the contents of bpp and
|
||||
* dipp are undefined.
|
||||
*
|
||||
* The inode is expected to already been mapped to its buffer and read
|
||||
* in once, thus we can use the mapping information stored in the inode
|
||||
* rather than calling xfs_imap(). This allows us to avoid the overhead
|
||||
* of looking at the inode btree for small block file systems
|
||||
* (see xfs_imap()).
|
||||
*/
|
||||
int
|
||||
xfs_itobp(
|
||||
xfs_mount_t *mp,
|
||||
xfs_trans_t *tp,
|
||||
xfs_inode_t *ip,
|
||||
xfs_dinode_t **dipp,
|
||||
xfs_buf_t **bpp,
|
||||
uint buf_flags)
|
||||
{
|
||||
xfs_buf_t *bp;
|
||||
int error;
|
||||
|
||||
ASSERT(ip->i_imap.im_blkno != 0);
|
||||
|
||||
error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp, buf_flags, 0);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!bp) {
|
||||
ASSERT(buf_flags & XBF_TRYLOCK);
|
||||
ASSERT(tp == NULL);
|
||||
*bpp = NULL;
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
*dipp = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset);
|
||||
*bpp = bp;
|
||||
*dipp = (struct xfs_dinode *)xfs_buf_offset(bp, imap->im_boffset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -796,10 +714,9 @@ xfs_iread(
|
|||
/*
|
||||
* Get pointers to the on-disk inode and the buffer containing it.
|
||||
*/
|
||||
error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp, 0, iget_flags);
|
||||
error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &bp, 0, iget_flags);
|
||||
if (error)
|
||||
return error;
|
||||
dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset);
|
||||
|
||||
/*
|
||||
* If we got something that isn't an inode it means someone
|
||||
|
@ -876,7 +793,7 @@ xfs_iread(
|
|||
/*
|
||||
* Use xfs_trans_brelse() to release the buffer containing the
|
||||
* on-disk inode, because it was acquired with xfs_trans_read_buf()
|
||||
* in xfs_itobp() above. If tp is NULL, this is just a normal
|
||||
* in xfs_imap_to_bp() above. If tp is NULL, this is just a normal
|
||||
* brelse(). If we're within a transaction, then xfs_trans_brelse()
|
||||
* will only release the buffer if it is not dirty within the
|
||||
* transaction. It will be OK to release the buffer in this case,
|
||||
|
@ -970,7 +887,6 @@ xfs_ialloc(
|
|||
prid_t prid,
|
||||
int okalloc,
|
||||
xfs_buf_t **ialloc_context,
|
||||
boolean_t *call_again,
|
||||
xfs_inode_t **ipp)
|
||||
{
|
||||
xfs_ino_t ino;
|
||||
|
@ -985,10 +901,10 @@ xfs_ialloc(
|
|||
* the on-disk inode to be allocated.
|
||||
*/
|
||||
error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc,
|
||||
ialloc_context, call_again, &ino);
|
||||
ialloc_context, &ino);
|
||||
if (error)
|
||||
return error;
|
||||
if (*call_again || ino == NULLFSINO) {
|
||||
if (*ialloc_context || ino == NULLFSINO) {
|
||||
*ipp = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1207,7 +1123,9 @@ xfs_itruncate_extents(
|
|||
int error = 0;
|
||||
int done = 0;
|
||||
|
||||
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
|
||||
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
|
||||
ASSERT(!atomic_read(&VFS_I(ip)->i_count) ||
|
||||
xfs_isilocked(ip, XFS_IOLOCK_EXCL));
|
||||
ASSERT(new_size <= XFS_ISIZE(ip));
|
||||
ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
|
||||
ASSERT(ip->i_itemp != NULL);
|
||||
|
@ -1226,7 +1144,7 @@ xfs_itruncate_extents(
|
|||
* then there is nothing to do.
|
||||
*/
|
||||
first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
|
||||
last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
|
||||
last_block = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
|
||||
if (first_unmap_block == last_block)
|
||||
return 0;
|
||||
|
||||
|
@ -1355,7 +1273,8 @@ xfs_iunlink(
|
|||
* Here we put the head pointer into our next pointer,
|
||||
* and then we fall through to point the head at us.
|
||||
*/
|
||||
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0);
|
||||
error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &ibp,
|
||||
0, 0);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -1429,16 +1348,16 @@ xfs_iunlink_remove(
|
|||
|
||||
if (be32_to_cpu(agi->agi_unlinked[bucket_index]) == agino) {
|
||||
/*
|
||||
* We're at the head of the list. Get the inode's
|
||||
* on-disk buffer to see if there is anyone after us
|
||||
* on the list. Only modify our next pointer if it
|
||||
* is not already NULLAGINO. This saves us the overhead
|
||||
* of dealing with the buffer when there is no need to
|
||||
* change it.
|
||||
* We're at the head of the list. Get the inode's on-disk
|
||||
* buffer to see if there is anyone after us on the list.
|
||||
* Only modify our next pointer if it is not already NULLAGINO.
|
||||
* This saves us the overhead of dealing with the buffer when
|
||||
* there is no need to change it.
|
||||
*/
|
||||
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0);
|
||||
error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &ibp,
|
||||
0, 0);
|
||||
if (error) {
|
||||
xfs_warn(mp, "%s: xfs_itobp() returned error %d.",
|
||||
xfs_warn(mp, "%s: xfs_imap_to_bp returned error %d.",
|
||||
__func__, error);
|
||||
return error;
|
||||
}
|
||||
|
@ -1472,34 +1391,45 @@ xfs_iunlink_remove(
|
|||
next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
|
||||
last_ibp = NULL;
|
||||
while (next_agino != agino) {
|
||||
/*
|
||||
* If the last inode wasn't the one pointing to
|
||||
* us, then release its buffer since we're not
|
||||
* going to do anything with it.
|
||||
*/
|
||||
if (last_ibp != NULL) {
|
||||
struct xfs_imap imap;
|
||||
|
||||
if (last_ibp)
|
||||
xfs_trans_brelse(tp, last_ibp);
|
||||
}
|
||||
|
||||
imap.im_blkno = 0;
|
||||
next_ino = XFS_AGINO_TO_INO(mp, agno, next_agino);
|
||||
error = xfs_inotobp(mp, tp, next_ino, &last_dip,
|
||||
&last_ibp, &last_offset, 0);
|
||||
|
||||
error = xfs_imap(mp, tp, next_ino, &imap, 0);
|
||||
if (error) {
|
||||
xfs_warn(mp,
|
||||
"%s: xfs_inotobp() returned error %d.",
|
||||
"%s: xfs_imap returned error %d.",
|
||||
__func__, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = xfs_imap_to_bp(mp, tp, &imap, &last_dip,
|
||||
&last_ibp, 0, 0);
|
||||
if (error) {
|
||||
xfs_warn(mp,
|
||||
"%s: xfs_imap_to_bp returned error %d.",
|
||||
__func__, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
last_offset = imap.im_boffset;
|
||||
next_agino = be32_to_cpu(last_dip->di_next_unlinked);
|
||||
ASSERT(next_agino != NULLAGINO);
|
||||
ASSERT(next_agino != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now last_ibp points to the buffer previous to us on
|
||||
* the unlinked list. Pull us from the list.
|
||||
* Now last_ibp points to the buffer previous to us on the
|
||||
* unlinked list. Pull us from the list.
|
||||
*/
|
||||
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0);
|
||||
error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &ibp,
|
||||
0, 0);
|
||||
if (error) {
|
||||
xfs_warn(mp, "%s: xfs_itobp(2) returned error %d.",
|
||||
xfs_warn(mp, "%s: xfs_imap_to_bp(2) returned error %d.",
|
||||
__func__, error);
|
||||
return error;
|
||||
}
|
||||
|
@ -1749,7 +1679,8 @@ xfs_ifree(
|
|||
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||
|
||||
error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0);
|
||||
error = xfs_imap_to_bp(ip->i_mount, tp, &ip->i_imap, &dip, &ibp,
|
||||
0, 0);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -2428,7 +2359,7 @@ xfs_iflush(
|
|||
/*
|
||||
* For stale inodes we cannot rely on the backing buffer remaining
|
||||
* stale in cache for the remaining life of the stale inode and so
|
||||
* xfs_itobp() below may give us a buffer that no longer contains
|
||||
* xfs_imap_to_bp() below may give us a buffer that no longer contains
|
||||
* inodes below. We have to check this after ensuring the inode is
|
||||
* unpinned so that it is safe to reclaim the stale inode after the
|
||||
* flush call.
|
||||
|
@ -2454,7 +2385,8 @@ xfs_iflush(
|
|||
/*
|
||||
* Get the buffer containing the on-disk inode.
|
||||
*/
|
||||
error = xfs_itobp(mp, NULL, ip, &dip, &bp, XBF_TRYLOCK);
|
||||
error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK,
|
||||
0);
|
||||
if (error || !bp) {
|
||||
xfs_ifunlock(ip);
|
||||
return error;
|
||||
|
|
|
@ -487,8 +487,6 @@ static inline int xfs_isiflocked(struct xfs_inode *ip)
|
|||
#define XFS_IOLOCK_DEP(flags) (((flags) & XFS_IOLOCK_DEP_MASK) >> XFS_IOLOCK_SHIFT)
|
||||
#define XFS_ILOCK_DEP(flags) (((flags) & XFS_ILOCK_DEP_MASK) >> XFS_ILOCK_SHIFT)
|
||||
|
||||
extern struct lock_class_key xfs_iolock_reclaimable;
|
||||
|
||||
/*
|
||||
* For multiple groups support: if S_ISGID bit is set in the parent
|
||||
* directory, group of new file is set to that of the parent, and
|
||||
|
@ -517,7 +515,7 @@ void xfs_inode_free(struct xfs_inode *ip);
|
|||
*/
|
||||
int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, umode_t,
|
||||
xfs_nlink_t, xfs_dev_t, prid_t, int,
|
||||
struct xfs_buf **, boolean_t *, xfs_inode_t **);
|
||||
struct xfs_buf **, xfs_inode_t **);
|
||||
|
||||
uint xfs_ip2xflags(struct xfs_inode *);
|
||||
uint xfs_dic2xflags(struct xfs_dinode *);
|
||||
|
@ -557,12 +555,9 @@ do { \
|
|||
#define XFS_IGET_UNTRUSTED 0x2
|
||||
#define XFS_IGET_DONTCACHE 0x4
|
||||
|
||||
int xfs_inotobp(struct xfs_mount *, struct xfs_trans *,
|
||||
xfs_ino_t, struct xfs_dinode **,
|
||||
struct xfs_buf **, int *, uint);
|
||||
int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
|
||||
struct xfs_inode *, struct xfs_dinode **,
|
||||
struct xfs_buf **, uint);
|
||||
int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *,
|
||||
struct xfs_imap *, struct xfs_dinode **,
|
||||
struct xfs_buf **, uint, uint);
|
||||
int xfs_iread(struct xfs_mount *, struct xfs_trans *,
|
||||
struct xfs_inode *, uint);
|
||||
void xfs_dinode_to_disk(struct xfs_dinode *,
|
||||
|
|
|
@ -285,7 +285,7 @@ xfs_iomap_eof_want_preallocate(
|
|||
* do any speculative allocation.
|
||||
*/
|
||||
start_fsb = XFS_B_TO_FSBT(mp, ((xfs_ufsize_t)(offset + count - 1)));
|
||||
count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
|
||||
count_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
|
||||
while (count_fsb > 0) {
|
||||
imaps = nimaps;
|
||||
firstblock = NULLFSBLOCK;
|
||||
|
@ -416,8 +416,8 @@ retry:
|
|||
* Make sure preallocation does not create extents beyond the range we
|
||||
* actually support in this filesystem.
|
||||
*/
|
||||
if (last_fsb > XFS_B_TO_FSB(mp, mp->m_maxioffset))
|
||||
last_fsb = XFS_B_TO_FSB(mp, mp->m_maxioffset);
|
||||
if (last_fsb > XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes))
|
||||
last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
|
||||
|
||||
ASSERT(last_fsb > offset_fsb);
|
||||
|
||||
|
|
|
@ -897,6 +897,47 @@ xfs_vn_setattr(
|
|||
return -xfs_setattr_nonsize(XFS_I(dentry->d_inode), iattr, 0);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_vn_update_time(
|
||||
struct inode *inode,
|
||||
struct timespec *now,
|
||||
int flags)
|
||||
{
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
struct xfs_trans *tp;
|
||||
int error;
|
||||
|
||||
trace_xfs_update_time(ip);
|
||||
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);
|
||||
error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0);
|
||||
if (error) {
|
||||
xfs_trans_cancel(tp, 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
if (flags & S_CTIME) {
|
||||
inode->i_ctime = *now;
|
||||
ip->i_d.di_ctime.t_sec = (__int32_t)now->tv_sec;
|
||||
ip->i_d.di_ctime.t_nsec = (__int32_t)now->tv_nsec;
|
||||
}
|
||||
if (flags & S_MTIME) {
|
||||
inode->i_mtime = *now;
|
||||
ip->i_d.di_mtime.t_sec = (__int32_t)now->tv_sec;
|
||||
ip->i_d.di_mtime.t_nsec = (__int32_t)now->tv_nsec;
|
||||
}
|
||||
if (flags & S_ATIME) {
|
||||
inode->i_atime = *now;
|
||||
ip->i_d.di_atime.t_sec = (__int32_t)now->tv_sec;
|
||||
ip->i_d.di_atime.t_nsec = (__int32_t)now->tv_nsec;
|
||||
}
|
||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP);
|
||||
return -xfs_trans_commit(tp, 0);
|
||||
}
|
||||
|
||||
#define XFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR)
|
||||
|
||||
/*
|
||||
|
@ -991,6 +1032,7 @@ static const struct inode_operations xfs_inode_operations = {
|
|||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.fiemap = xfs_vn_fiemap,
|
||||
.update_time = xfs_vn_update_time,
|
||||
};
|
||||
|
||||
static const struct inode_operations xfs_dir_inode_operations = {
|
||||
|
@ -1016,6 +1058,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
|
|||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
};
|
||||
|
||||
static const struct inode_operations xfs_dir_ci_inode_operations = {
|
||||
|
@ -1041,6 +1084,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
|
|||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
};
|
||||
|
||||
static const struct inode_operations xfs_symlink_inode_operations = {
|
||||
|
@ -1054,6 +1098,7 @@ static const struct inode_operations xfs_symlink_inode_operations = {
|
|||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
};
|
||||
|
||||
STATIC void
|
||||
|
|
|
@ -555,7 +555,7 @@ xfs_bulkstat_single(
|
|||
|
||||
/*
|
||||
* note that requesting valid inode numbers which are not allocated
|
||||
* to inodes will most likely cause xfs_itobp to generate warning
|
||||
* to inodes will most likely cause xfs_imap_to_bp to generate warning
|
||||
* messages about bad magic numbers. This is ok. The fact that
|
||||
* the inode isn't actually an inode is handled by the
|
||||
* error check below. Done this way to make the usual case faster
|
||||
|
|
223
fs/xfs/xfs_log.c
223
fs/xfs/xfs_log.c
|
@ -45,51 +45,85 @@ xlog_commit_record(
|
|||
struct xlog_in_core **iclog,
|
||||
xfs_lsn_t *commitlsnp);
|
||||
|
||||
STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp,
|
||||
xfs_buftarg_t *log_target,
|
||||
xfs_daddr_t blk_offset,
|
||||
int num_bblks);
|
||||
STATIC struct xlog *
|
||||
xlog_alloc_log(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_buftarg *log_target,
|
||||
xfs_daddr_t blk_offset,
|
||||
int num_bblks);
|
||||
STATIC int
|
||||
xlog_space_left(
|
||||
struct xlog *log,
|
||||
atomic64_t *head);
|
||||
STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog);
|
||||
STATIC void xlog_dealloc_log(xlog_t *log);
|
||||
STATIC int
|
||||
xlog_sync(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog);
|
||||
STATIC void
|
||||
xlog_dealloc_log(
|
||||
struct xlog *log);
|
||||
|
||||
/* local state machine functions */
|
||||
STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int);
|
||||
STATIC void xlog_state_do_callback(xlog_t *log,int aborted, xlog_in_core_t *iclog);
|
||||
STATIC int xlog_state_get_iclog_space(xlog_t *log,
|
||||
int len,
|
||||
xlog_in_core_t **iclog,
|
||||
xlog_ticket_t *ticket,
|
||||
int *continued_write,
|
||||
int *logoffsetp);
|
||||
STATIC int xlog_state_release_iclog(xlog_t *log,
|
||||
xlog_in_core_t *iclog);
|
||||
STATIC void xlog_state_switch_iclogs(xlog_t *log,
|
||||
xlog_in_core_t *iclog,
|
||||
int eventual_size);
|
||||
STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog);
|
||||
STATIC void
|
||||
xlog_state_do_callback(
|
||||
struct xlog *log,
|
||||
int aborted,
|
||||
struct xlog_in_core *iclog);
|
||||
STATIC int
|
||||
xlog_state_get_iclog_space(
|
||||
struct xlog *log,
|
||||
int len,
|
||||
struct xlog_in_core **iclog,
|
||||
struct xlog_ticket *ticket,
|
||||
int *continued_write,
|
||||
int *logoffsetp);
|
||||
STATIC int
|
||||
xlog_state_release_iclog(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog);
|
||||
STATIC void
|
||||
xlog_state_switch_iclogs(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog,
|
||||
int eventual_size);
|
||||
STATIC void
|
||||
xlog_state_want_sync(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog);
|
||||
|
||||
STATIC void
|
||||
xlog_grant_push_ail(
|
||||
struct xlog *log,
|
||||
int need_bytes);
|
||||
STATIC void xlog_regrant_reserve_log_space(xlog_t *log,
|
||||
xlog_ticket_t *ticket);
|
||||
STATIC void xlog_ungrant_log_space(xlog_t *log,
|
||||
xlog_ticket_t *ticket);
|
||||
struct xlog *log,
|
||||
int need_bytes);
|
||||
STATIC void
|
||||
xlog_regrant_reserve_log_space(
|
||||
struct xlog *log,
|
||||
struct xlog_ticket *ticket);
|
||||
STATIC void
|
||||
xlog_ungrant_log_space(
|
||||
struct xlog *log,
|
||||
struct xlog_ticket *ticket);
|
||||
|
||||
#if defined(DEBUG)
|
||||
STATIC void xlog_verify_dest_ptr(xlog_t *log, char *ptr);
|
||||
STATIC void
|
||||
xlog_verify_dest_ptr(
|
||||
struct xlog *log,
|
||||
char *ptr);
|
||||
STATIC void
|
||||
xlog_verify_grant_tail(
|
||||
struct xlog *log);
|
||||
STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog,
|
||||
int count, boolean_t syncing);
|
||||
STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog,
|
||||
xfs_lsn_t tail_lsn);
|
||||
struct xlog *log);
|
||||
STATIC void
|
||||
xlog_verify_iclog(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog,
|
||||
int count,
|
||||
boolean_t syncing);
|
||||
STATIC void
|
||||
xlog_verify_tail_lsn(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog,
|
||||
xfs_lsn_t tail_lsn);
|
||||
#else
|
||||
#define xlog_verify_dest_ptr(a,b)
|
||||
#define xlog_verify_grant_tail(a)
|
||||
|
@ -97,7 +131,9 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog,
|
|||
#define xlog_verify_tail_lsn(a,b,c)
|
||||
#endif
|
||||
|
||||
STATIC int xlog_iclogs_empty(xlog_t *log);
|
||||
STATIC int
|
||||
xlog_iclogs_empty(
|
||||
struct xlog *log);
|
||||
|
||||
static void
|
||||
xlog_grant_sub_space(
|
||||
|
@ -684,7 +720,7 @@ xfs_log_mount_finish(xfs_mount_t *mp)
|
|||
int
|
||||
xfs_log_unmount_write(xfs_mount_t *mp)
|
||||
{
|
||||
xlog_t *log = mp->m_log;
|
||||
struct xlog *log = mp->m_log;
|
||||
xlog_in_core_t *iclog;
|
||||
#ifdef DEBUG
|
||||
xlog_in_core_t *first_iclog;
|
||||
|
@ -893,7 +929,7 @@ int
|
|||
xfs_log_need_covered(xfs_mount_t *mp)
|
||||
{
|
||||
int needed = 0;
|
||||
xlog_t *log = mp->m_log;
|
||||
struct xlog *log = mp->m_log;
|
||||
|
||||
if (!xfs_fs_writable(mp))
|
||||
return 0;
|
||||
|
@ -1024,9 +1060,9 @@ xlog_space_left(
|
|||
void
|
||||
xlog_iodone(xfs_buf_t *bp)
|
||||
{
|
||||
xlog_in_core_t *iclog = bp->b_fspriv;
|
||||
xlog_t *l = iclog->ic_log;
|
||||
int aborted = 0;
|
||||
struct xlog_in_core *iclog = bp->b_fspriv;
|
||||
struct xlog *l = iclog->ic_log;
|
||||
int aborted = 0;
|
||||
|
||||
/*
|
||||
* Race to shutdown the filesystem if we see an error.
|
||||
|
@ -1067,8 +1103,9 @@ xlog_iodone(xfs_buf_t *bp)
|
|||
*/
|
||||
|
||||
STATIC void
|
||||
xlog_get_iclog_buffer_size(xfs_mount_t *mp,
|
||||
xlog_t *log)
|
||||
xlog_get_iclog_buffer_size(
|
||||
struct xfs_mount *mp,
|
||||
struct xlog *log)
|
||||
{
|
||||
int size;
|
||||
int xhdrs;
|
||||
|
@ -1129,13 +1166,14 @@ done:
|
|||
* Its primary purpose is to fill in enough, so recovery can occur. However,
|
||||
* some other stuff may be filled in too.
|
||||
*/
|
||||
STATIC xlog_t *
|
||||
xlog_alloc_log(xfs_mount_t *mp,
|
||||
xfs_buftarg_t *log_target,
|
||||
xfs_daddr_t blk_offset,
|
||||
int num_bblks)
|
||||
STATIC struct xlog *
|
||||
xlog_alloc_log(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_buftarg *log_target,
|
||||
xfs_daddr_t blk_offset,
|
||||
int num_bblks)
|
||||
{
|
||||
xlog_t *log;
|
||||
struct xlog *log;
|
||||
xlog_rec_header_t *head;
|
||||
xlog_in_core_t **iclogp;
|
||||
xlog_in_core_t *iclog, *prev_iclog=NULL;
|
||||
|
@ -1144,7 +1182,7 @@ xlog_alloc_log(xfs_mount_t *mp,
|
|||
int error = ENOMEM;
|
||||
uint log2_size = 0;
|
||||
|
||||
log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL);
|
||||
log = kmem_zalloc(sizeof(struct xlog), KM_MAYFAIL);
|
||||
if (!log) {
|
||||
xfs_warn(mp, "Log allocation failed: No memory!");
|
||||
goto out;
|
||||
|
@ -1434,8 +1472,9 @@ xlog_bdstrat(
|
|||
*/
|
||||
|
||||
STATIC int
|
||||
xlog_sync(xlog_t *log,
|
||||
xlog_in_core_t *iclog)
|
||||
xlog_sync(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog)
|
||||
{
|
||||
xfs_caddr_t dptr; /* pointer to byte sized element */
|
||||
xfs_buf_t *bp;
|
||||
|
@ -1584,7 +1623,8 @@ xlog_sync(xlog_t *log,
|
|||
* Deallocate a log structure
|
||||
*/
|
||||
STATIC void
|
||||
xlog_dealloc_log(xlog_t *log)
|
||||
xlog_dealloc_log(
|
||||
struct xlog *log)
|
||||
{
|
||||
xlog_in_core_t *iclog, *next_iclog;
|
||||
int i;
|
||||
|
@ -1616,10 +1656,11 @@ xlog_dealloc_log(xlog_t *log)
|
|||
*/
|
||||
/* ARGSUSED */
|
||||
static inline void
|
||||
xlog_state_finish_copy(xlog_t *log,
|
||||
xlog_in_core_t *iclog,
|
||||
int record_cnt,
|
||||
int copy_bytes)
|
||||
xlog_state_finish_copy(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog,
|
||||
int record_cnt,
|
||||
int copy_bytes)
|
||||
{
|
||||
spin_lock(&log->l_icloglock);
|
||||
|
||||
|
@ -2142,7 +2183,8 @@ xlog_write(
|
|||
* State Change: DIRTY -> ACTIVE
|
||||
*/
|
||||
STATIC void
|
||||
xlog_state_clean_log(xlog_t *log)
|
||||
xlog_state_clean_log(
|
||||
struct xlog *log)
|
||||
{
|
||||
xlog_in_core_t *iclog;
|
||||
int changed = 0;
|
||||
|
@ -2222,7 +2264,7 @@ xlog_state_clean_log(xlog_t *log)
|
|||
|
||||
STATIC xfs_lsn_t
|
||||
xlog_get_lowest_lsn(
|
||||
xlog_t *log)
|
||||
struct xlog *log)
|
||||
{
|
||||
xlog_in_core_t *lsn_log;
|
||||
xfs_lsn_t lowest_lsn, lsn;
|
||||
|
@ -2245,9 +2287,9 @@ xlog_get_lowest_lsn(
|
|||
|
||||
STATIC void
|
||||
xlog_state_do_callback(
|
||||
xlog_t *log,
|
||||
int aborted,
|
||||
xlog_in_core_t *ciclog)
|
||||
struct xlog *log,
|
||||
int aborted,
|
||||
struct xlog_in_core *ciclog)
|
||||
{
|
||||
xlog_in_core_t *iclog;
|
||||
xlog_in_core_t *first_iclog; /* used to know when we've
|
||||
|
@ -2467,7 +2509,7 @@ xlog_state_done_syncing(
|
|||
xlog_in_core_t *iclog,
|
||||
int aborted)
|
||||
{
|
||||
xlog_t *log = iclog->ic_log;
|
||||
struct xlog *log = iclog->ic_log;
|
||||
|
||||
spin_lock(&log->l_icloglock);
|
||||
|
||||
|
@ -2521,12 +2563,13 @@ xlog_state_done_syncing(
|
|||
* is copied.
|
||||
*/
|
||||
STATIC int
|
||||
xlog_state_get_iclog_space(xlog_t *log,
|
||||
int len,
|
||||
xlog_in_core_t **iclogp,
|
||||
xlog_ticket_t *ticket,
|
||||
int *continued_write,
|
||||
int *logoffsetp)
|
||||
xlog_state_get_iclog_space(
|
||||
struct xlog *log,
|
||||
int len,
|
||||
struct xlog_in_core **iclogp,
|
||||
struct xlog_ticket *ticket,
|
||||
int *continued_write,
|
||||
int *logoffsetp)
|
||||
{
|
||||
int log_offset;
|
||||
xlog_rec_header_t *head;
|
||||
|
@ -2631,8 +2674,9 @@ restart:
|
|||
* move grant reservation head forward.
|
||||
*/
|
||||
STATIC void
|
||||
xlog_regrant_reserve_log_space(xlog_t *log,
|
||||
xlog_ticket_t *ticket)
|
||||
xlog_regrant_reserve_log_space(
|
||||
struct xlog *log,
|
||||
struct xlog_ticket *ticket)
|
||||
{
|
||||
trace_xfs_log_regrant_reserve_enter(log, ticket);
|
||||
|
||||
|
@ -2677,8 +2721,9 @@ xlog_regrant_reserve_log_space(xlog_t *log,
|
|||
* in the current reservation field.
|
||||
*/
|
||||
STATIC void
|
||||
xlog_ungrant_log_space(xlog_t *log,
|
||||
xlog_ticket_t *ticket)
|
||||
xlog_ungrant_log_space(
|
||||
struct xlog *log,
|
||||
struct xlog_ticket *ticket)
|
||||
{
|
||||
int bytes;
|
||||
|
||||
|
@ -2717,8 +2762,8 @@ xlog_ungrant_log_space(xlog_t *log,
|
|||
*/
|
||||
STATIC int
|
||||
xlog_state_release_iclog(
|
||||
xlog_t *log,
|
||||
xlog_in_core_t *iclog)
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog)
|
||||
{
|
||||
int sync = 0; /* do we sync? */
|
||||
|
||||
|
@ -2768,9 +2813,10 @@ xlog_state_release_iclog(
|
|||
* that every data block. We have run out of space in this log record.
|
||||
*/
|
||||
STATIC void
|
||||
xlog_state_switch_iclogs(xlog_t *log,
|
||||
xlog_in_core_t *iclog,
|
||||
int eventual_size)
|
||||
xlog_state_switch_iclogs(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog,
|
||||
int eventual_size)
|
||||
{
|
||||
ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE);
|
||||
if (!eventual_size)
|
||||
|
@ -3114,7 +3160,9 @@ xfs_log_force_lsn(
|
|||
* disk.
|
||||
*/
|
||||
STATIC void
|
||||
xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
|
||||
xlog_state_want_sync(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog)
|
||||
{
|
||||
assert_spin_locked(&log->l_icloglock);
|
||||
|
||||
|
@ -3158,7 +3206,7 @@ xfs_log_ticket_get(
|
|||
/*
|
||||
* Allocate and initialise a new log ticket.
|
||||
*/
|
||||
xlog_ticket_t *
|
||||
struct xlog_ticket *
|
||||
xlog_ticket_alloc(
|
||||
struct xlog *log,
|
||||
int unit_bytes,
|
||||
|
@ -3346,9 +3394,10 @@ xlog_verify_grant_tail(
|
|||
|
||||
/* check if it will fit */
|
||||
STATIC void
|
||||
xlog_verify_tail_lsn(xlog_t *log,
|
||||
xlog_in_core_t *iclog,
|
||||
xfs_lsn_t tail_lsn)
|
||||
xlog_verify_tail_lsn(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog,
|
||||
xfs_lsn_t tail_lsn)
|
||||
{
|
||||
int blocks;
|
||||
|
||||
|
@ -3385,10 +3434,11 @@ xlog_verify_tail_lsn(xlog_t *log,
|
|||
* the cycle numbers agree with the current cycle number.
|
||||
*/
|
||||
STATIC void
|
||||
xlog_verify_iclog(xlog_t *log,
|
||||
xlog_in_core_t *iclog,
|
||||
int count,
|
||||
boolean_t syncing)
|
||||
xlog_verify_iclog(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog,
|
||||
int count,
|
||||
boolean_t syncing)
|
||||
{
|
||||
xlog_op_header_t *ophead;
|
||||
xlog_in_core_t *icptr;
|
||||
|
@ -3482,7 +3532,7 @@ xlog_verify_iclog(xlog_t *log,
|
|||
*/
|
||||
STATIC int
|
||||
xlog_state_ioerror(
|
||||
xlog_t *log)
|
||||
struct xlog *log)
|
||||
{
|
||||
xlog_in_core_t *iclog, *ic;
|
||||
|
||||
|
@ -3527,7 +3577,7 @@ xfs_log_force_umount(
|
|||
struct xfs_mount *mp,
|
||||
int logerror)
|
||||
{
|
||||
xlog_t *log;
|
||||
struct xlog *log;
|
||||
int retval;
|
||||
|
||||
log = mp->m_log;
|
||||
|
@ -3634,7 +3684,8 @@ xfs_log_force_umount(
|
|||
}
|
||||
|
||||
STATIC int
|
||||
xlog_iclogs_empty(xlog_t *log)
|
||||
xlog_iclogs_empty(
|
||||
struct xlog *log)
|
||||
{
|
||||
xlog_in_core_t *iclog;
|
||||
|
||||
|
|
|
@ -487,7 +487,7 @@ struct xlog_grant_head {
|
|||
* overflow 31 bits worth of byte offset, so using a byte number will mean
|
||||
* that round off problems won't occur when releasing partial reservations.
|
||||
*/
|
||||
typedef struct xlog {
|
||||
struct xlog {
|
||||
/* The following fields don't need locking */
|
||||
struct xfs_mount *l_mp; /* mount point */
|
||||
struct xfs_ail *l_ailp; /* AIL log is working with */
|
||||
|
@ -540,7 +540,7 @@ typedef struct xlog {
|
|||
char *l_iclog_bak[XLOG_MAX_ICLOGS];
|
||||
#endif
|
||||
|
||||
} xlog_t;
|
||||
};
|
||||
|
||||
#define XLOG_BUF_CANCEL_BUCKET(log, blkno) \
|
||||
((log)->l_buf_cancel_table + ((__uint64_t)blkno % XLOG_BC_TABLE_SIZE))
|
||||
|
@ -548,9 +548,17 @@ typedef struct xlog {
|
|||
#define XLOG_FORCED_SHUTDOWN(log) ((log)->l_flags & XLOG_IO_ERROR)
|
||||
|
||||
/* common routines */
|
||||
extern int xlog_recover(xlog_t *log);
|
||||
extern int xlog_recover_finish(xlog_t *log);
|
||||
extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int);
|
||||
extern int
|
||||
xlog_recover(
|
||||
struct xlog *log);
|
||||
extern int
|
||||
xlog_recover_finish(
|
||||
struct xlog *log);
|
||||
extern void
|
||||
xlog_pack_data(
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog,
|
||||
int);
|
||||
|
||||
extern kmem_zone_t *xfs_log_ticket_zone;
|
||||
struct xlog_ticket *
|
||||
|
|
|
@ -43,10 +43,18 @@
|
|||
#include "xfs_utils.h"
|
||||
#include "xfs_trace.h"
|
||||
|
||||
STATIC int xlog_find_zeroed(xlog_t *, xfs_daddr_t *);
|
||||
STATIC int xlog_clear_stale_blocks(xlog_t *, xfs_lsn_t);
|
||||
STATIC int
|
||||
xlog_find_zeroed(
|
||||
struct xlog *,
|
||||
xfs_daddr_t *);
|
||||
STATIC int
|
||||
xlog_clear_stale_blocks(
|
||||
struct xlog *,
|
||||
xfs_lsn_t);
|
||||
#if defined(DEBUG)
|
||||
STATIC void xlog_recover_check_summary(xlog_t *);
|
||||
STATIC void
|
||||
xlog_recover_check_summary(
|
||||
struct xlog *);
|
||||
#else
|
||||
#define xlog_recover_check_summary(log)
|
||||
#endif
|
||||
|
@ -74,7 +82,7 @@ struct xfs_buf_cancel {
|
|||
|
||||
static inline int
|
||||
xlog_buf_bbcount_valid(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
int bbcount)
|
||||
{
|
||||
return bbcount > 0 && bbcount <= log->l_logBBsize;
|
||||
|
@ -87,7 +95,7 @@ xlog_buf_bbcount_valid(
|
|||
*/
|
||||
STATIC xfs_buf_t *
|
||||
xlog_get_bp(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
int nbblks)
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
|
@ -138,10 +146,10 @@ xlog_put_bp(
|
|||
*/
|
||||
STATIC xfs_caddr_t
|
||||
xlog_align(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t blk_no,
|
||||
int nbblks,
|
||||
xfs_buf_t *bp)
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
xfs_daddr_t offset = blk_no & ((xfs_daddr_t)log->l_sectBBsize - 1);
|
||||
|
||||
|
@ -155,10 +163,10 @@ xlog_align(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_bread_noalign(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t blk_no,
|
||||
int nbblks,
|
||||
xfs_buf_t *bp)
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
int error;
|
||||
|
||||
|
@ -189,10 +197,10 @@ xlog_bread_noalign(
|
|||
|
||||
STATIC int
|
||||
xlog_bread(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t blk_no,
|
||||
int nbblks,
|
||||
xfs_buf_t *bp,
|
||||
struct xfs_buf *bp,
|
||||
xfs_caddr_t *offset)
|
||||
{
|
||||
int error;
|
||||
|
@ -211,10 +219,10 @@ xlog_bread(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_bread_offset(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t blk_no, /* block to read from */
|
||||
int nbblks, /* blocks to read */
|
||||
xfs_buf_t *bp,
|
||||
struct xfs_buf *bp,
|
||||
xfs_caddr_t offset)
|
||||
{
|
||||
xfs_caddr_t orig_offset = bp->b_addr;
|
||||
|
@ -241,10 +249,10 @@ xlog_bread_offset(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_bwrite(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t blk_no,
|
||||
int nbblks,
|
||||
xfs_buf_t *bp)
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
int error;
|
||||
|
||||
|
@ -378,8 +386,8 @@ xlog_recover_iodone(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_find_cycle_start(
|
||||
xlog_t *log,
|
||||
xfs_buf_t *bp,
|
||||
struct xlog *log,
|
||||
struct xfs_buf *bp,
|
||||
xfs_daddr_t first_blk,
|
||||
xfs_daddr_t *last_blk,
|
||||
uint cycle)
|
||||
|
@ -421,7 +429,7 @@ xlog_find_cycle_start(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_find_verify_cycle(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t start_blk,
|
||||
int nbblks,
|
||||
uint stop_on_cycle_no,
|
||||
|
@ -490,7 +498,7 @@ out:
|
|||
*/
|
||||
STATIC int
|
||||
xlog_find_verify_log_record(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t start_blk,
|
||||
xfs_daddr_t *last_blk,
|
||||
int extra_bblks)
|
||||
|
@ -600,7 +608,7 @@ out:
|
|||
*/
|
||||
STATIC int
|
||||
xlog_find_head(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t *return_head_blk)
|
||||
{
|
||||
xfs_buf_t *bp;
|
||||
|
@ -871,7 +879,7 @@ validate_head:
|
|||
*/
|
||||
STATIC int
|
||||
xlog_find_tail(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t *head_blk,
|
||||
xfs_daddr_t *tail_blk)
|
||||
{
|
||||
|
@ -1080,7 +1088,7 @@ done:
|
|||
*/
|
||||
STATIC int
|
||||
xlog_find_zeroed(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t *blk_no)
|
||||
{
|
||||
xfs_buf_t *bp;
|
||||
|
@ -1183,7 +1191,7 @@ bp_err:
|
|||
*/
|
||||
STATIC void
|
||||
xlog_add_record(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_caddr_t buf,
|
||||
int cycle,
|
||||
int block,
|
||||
|
@ -1205,7 +1213,7 @@ xlog_add_record(
|
|||
|
||||
STATIC int
|
||||
xlog_write_log_records(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
int cycle,
|
||||
int start_block,
|
||||
int blocks,
|
||||
|
@ -1305,7 +1313,7 @@ xlog_write_log_records(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_clear_stale_blocks(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_lsn_t tail_lsn)
|
||||
{
|
||||
int tail_cycle, head_cycle;
|
||||
|
@ -2050,11 +2058,11 @@ xfs_qm_dqcheck(
|
|||
*/
|
||||
STATIC void
|
||||
xlog_recover_do_dquot_buffer(
|
||||
xfs_mount_t *mp,
|
||||
xlog_t *log,
|
||||
xlog_recover_item_t *item,
|
||||
xfs_buf_t *bp,
|
||||
xfs_buf_log_format_t *buf_f)
|
||||
struct xfs_mount *mp,
|
||||
struct xlog *log,
|
||||
struct xlog_recover_item *item,
|
||||
struct xfs_buf *bp,
|
||||
struct xfs_buf_log_format *buf_f)
|
||||
{
|
||||
uint type;
|
||||
|
||||
|
@ -2108,9 +2116,9 @@ xlog_recover_do_dquot_buffer(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_recover_buffer_pass2(
|
||||
xlog_t *log,
|
||||
struct list_head *buffer_list,
|
||||
xlog_recover_item_t *item)
|
||||
struct xlog *log,
|
||||
struct list_head *buffer_list,
|
||||
struct xlog_recover_item *item)
|
||||
{
|
||||
xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr;
|
||||
xfs_mount_t *mp = log->l_mp;
|
||||
|
@ -2189,9 +2197,9 @@ xlog_recover_buffer_pass2(
|
|||
|
||||
STATIC int
|
||||
xlog_recover_inode_pass2(
|
||||
xlog_t *log,
|
||||
struct list_head *buffer_list,
|
||||
xlog_recover_item_t *item)
|
||||
struct xlog *log,
|
||||
struct list_head *buffer_list,
|
||||
struct xlog_recover_item *item)
|
||||
{
|
||||
xfs_inode_log_format_t *in_f;
|
||||
xfs_mount_t *mp = log->l_mp;
|
||||
|
@ -2452,14 +2460,14 @@ error:
|
|||
}
|
||||
|
||||
/*
|
||||
* Recover QUOTAOFF records. We simply make a note of it in the xlog_t
|
||||
* Recover QUOTAOFF records. We simply make a note of it in the xlog
|
||||
* structure, so that we know not to do any dquot item or dquot buffer recovery,
|
||||
* of that type.
|
||||
*/
|
||||
STATIC int
|
||||
xlog_recover_quotaoff_pass1(
|
||||
xlog_t *log,
|
||||
xlog_recover_item_t *item)
|
||||
struct xlog *log,
|
||||
struct xlog_recover_item *item)
|
||||
{
|
||||
xfs_qoff_logformat_t *qoff_f = item->ri_buf[0].i_addr;
|
||||
ASSERT(qoff_f);
|
||||
|
@ -2483,9 +2491,9 @@ xlog_recover_quotaoff_pass1(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_recover_dquot_pass2(
|
||||
xlog_t *log,
|
||||
struct list_head *buffer_list,
|
||||
xlog_recover_item_t *item)
|
||||
struct xlog *log,
|
||||
struct list_head *buffer_list,
|
||||
struct xlog_recover_item *item)
|
||||
{
|
||||
xfs_mount_t *mp = log->l_mp;
|
||||
xfs_buf_t *bp;
|
||||
|
@ -2578,9 +2586,9 @@ xlog_recover_dquot_pass2(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_recover_efi_pass2(
|
||||
xlog_t *log,
|
||||
xlog_recover_item_t *item,
|
||||
xfs_lsn_t lsn)
|
||||
struct xlog *log,
|
||||
struct xlog_recover_item *item,
|
||||
xfs_lsn_t lsn)
|
||||
{
|
||||
int error;
|
||||
xfs_mount_t *mp = log->l_mp;
|
||||
|
@ -2616,8 +2624,8 @@ xlog_recover_efi_pass2(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_recover_efd_pass2(
|
||||
xlog_t *log,
|
||||
xlog_recover_item_t *item)
|
||||
struct xlog *log,
|
||||
struct xlog_recover_item *item)
|
||||
{
|
||||
xfs_efd_log_format_t *efd_formatp;
|
||||
xfs_efi_log_item_t *efip = NULL;
|
||||
|
@ -2812,9 +2820,9 @@ xlog_recover_unmount_trans(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_recover_process_data(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
struct hlist_head rhash[],
|
||||
xlog_rec_header_t *rhead,
|
||||
struct xlog_rec_header *rhead,
|
||||
xfs_caddr_t dp,
|
||||
int pass)
|
||||
{
|
||||
|
@ -2986,7 +2994,7 @@ abort_error:
|
|||
*/
|
||||
STATIC int
|
||||
xlog_recover_process_efis(
|
||||
xlog_t *log)
|
||||
struct xlog *log)
|
||||
{
|
||||
xfs_log_item_t *lip;
|
||||
xfs_efi_log_item_t *efip;
|
||||
|
@ -3098,7 +3106,7 @@ xlog_recover_process_one_iunlink(
|
|||
/*
|
||||
* Get the on disk inode to find the next inode in the bucket.
|
||||
*/
|
||||
error = xfs_itobp(mp, NULL, ip, &dip, &ibp, 0);
|
||||
error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &ibp, 0, 0);
|
||||
if (error)
|
||||
goto fail_iput;
|
||||
|
||||
|
@ -3147,7 +3155,7 @@ xlog_recover_process_one_iunlink(
|
|||
*/
|
||||
STATIC void
|
||||
xlog_recover_process_iunlinks(
|
||||
xlog_t *log)
|
||||
struct xlog *log)
|
||||
{
|
||||
xfs_mount_t *mp;
|
||||
xfs_agnumber_t agno;
|
||||
|
@ -3209,9 +3217,9 @@ xlog_recover_process_iunlinks(
|
|||
#ifdef DEBUG
|
||||
STATIC void
|
||||
xlog_pack_data_checksum(
|
||||
xlog_t *log,
|
||||
xlog_in_core_t *iclog,
|
||||
int size)
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog,
|
||||
int size)
|
||||
{
|
||||
int i;
|
||||
__be32 *up;
|
||||
|
@ -3234,8 +3242,8 @@ xlog_pack_data_checksum(
|
|||
*/
|
||||
void
|
||||
xlog_pack_data(
|
||||
xlog_t *log,
|
||||
xlog_in_core_t *iclog,
|
||||
struct xlog *log,
|
||||
struct xlog_in_core *iclog,
|
||||
int roundoff)
|
||||
{
|
||||
int i, j, k;
|
||||
|
@ -3274,9 +3282,9 @@ xlog_pack_data(
|
|||
|
||||
STATIC void
|
||||
xlog_unpack_data(
|
||||
xlog_rec_header_t *rhead,
|
||||
struct xlog_rec_header *rhead,
|
||||
xfs_caddr_t dp,
|
||||
xlog_t *log)
|
||||
struct xlog *log)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
|
@ -3299,8 +3307,8 @@ xlog_unpack_data(
|
|||
|
||||
STATIC int
|
||||
xlog_valid_rec_header(
|
||||
xlog_t *log,
|
||||
xlog_rec_header_t *rhead,
|
||||
struct xlog *log,
|
||||
struct xlog_rec_header *rhead,
|
||||
xfs_daddr_t blkno)
|
||||
{
|
||||
int hlen;
|
||||
|
@ -3343,7 +3351,7 @@ xlog_valid_rec_header(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_do_recovery_pass(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t head_blk,
|
||||
xfs_daddr_t tail_blk,
|
||||
int pass)
|
||||
|
@ -3595,7 +3603,7 @@ xlog_do_recovery_pass(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_do_log_recovery(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t head_blk,
|
||||
xfs_daddr_t tail_blk)
|
||||
{
|
||||
|
@ -3646,7 +3654,7 @@ xlog_do_log_recovery(
|
|||
*/
|
||||
STATIC int
|
||||
xlog_do_recover(
|
||||
xlog_t *log,
|
||||
struct xlog *log,
|
||||
xfs_daddr_t head_blk,
|
||||
xfs_daddr_t tail_blk)
|
||||
{
|
||||
|
@ -3721,7 +3729,7 @@ xlog_do_recover(
|
|||
*/
|
||||
int
|
||||
xlog_recover(
|
||||
xlog_t *log)
|
||||
struct xlog *log)
|
||||
{
|
||||
xfs_daddr_t head_blk, tail_blk;
|
||||
int error;
|
||||
|
@ -3767,7 +3775,7 @@ xlog_recover(
|
|||
*/
|
||||
int
|
||||
xlog_recover_finish(
|
||||
xlog_t *log)
|
||||
struct xlog *log)
|
||||
{
|
||||
/*
|
||||
* Now we're ready to do the transactions needed for the
|
||||
|
@ -3814,7 +3822,7 @@ xlog_recover_finish(
|
|||
*/
|
||||
void
|
||||
xlog_recover_check_summary(
|
||||
xlog_t *log)
|
||||
struct xlog *log)
|
||||
{
|
||||
xfs_mount_t *mp;
|
||||
xfs_agf_t *agfp;
|
||||
|
|
|
@ -1200,8 +1200,6 @@ xfs_mountfs(
|
|||
|
||||
xfs_set_maxicount(mp);
|
||||
|
||||
mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
|
||||
|
||||
error = xfs_uuid_mount(mp);
|
||||
if (error)
|
||||
goto out;
|
||||
|
@ -1531,6 +1529,15 @@ xfs_unmountfs(
|
|||
xfs_ail_push_all_sync(mp->m_ail);
|
||||
xfs_wait_buftarg(mp->m_ddev_targp);
|
||||
|
||||
/*
|
||||
* The superblock buffer is uncached and xfsaild_push() will lock and
|
||||
* set the XBF_ASYNC flag on the buffer. We cannot do xfs_buf_iowait()
|
||||
* here but a lock on the superblock buffer will block until iodone()
|
||||
* has completed.
|
||||
*/
|
||||
xfs_buf_lock(mp->m_sb_bp);
|
||||
xfs_buf_unlock(mp->m_sb_bp);
|
||||
|
||||
xfs_log_unmount_write(mp);
|
||||
xfs_log_unmount(mp);
|
||||
xfs_uuid_unmount(mp);
|
||||
|
|
|
@ -176,7 +176,6 @@ typedef struct xfs_mount {
|
|||
uint m_qflags; /* quota status flags */
|
||||
xfs_trans_reservations_t m_reservations;/* precomputed res values */
|
||||
__uint64_t m_maxicount; /* maximum inode count */
|
||||
__uint64_t m_maxioffset; /* maximum inode offset */
|
||||
__uint64_t m_resblks; /* total reserved blocks */
|
||||
__uint64_t m_resblks_avail;/* available reserved blocks */
|
||||
__uint64_t m_resblks_save; /* reserved blks @ remount,ro */
|
||||
|
@ -297,8 +296,6 @@ xfs_preferred_iosize(xfs_mount_t *mp)
|
|||
PAGE_CACHE_SIZE));
|
||||
}
|
||||
|
||||
#define XFS_MAXIOFFSET(mp) ((mp)->m_maxioffset)
|
||||
|
||||
#define XFS_LAST_UNMOUNT_WAS_CLEAN(mp) \
|
||||
((mp)->m_flags & XFS_MOUNT_WAS_CLEAN)
|
||||
#define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
|
||||
|
|
|
@ -940,7 +940,7 @@ xfs_qm_dqiterate(
|
|||
map = kmem_alloc(XFS_DQITER_MAP_SIZE * sizeof(*map), KM_SLEEP);
|
||||
|
||||
lblkno = 0;
|
||||
maxlblkcnt = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
|
||||
maxlblkcnt = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
|
||||
do {
|
||||
nmaps = XFS_DQITER_MAP_SIZE;
|
||||
/*
|
||||
|
|
|
@ -868,67 +868,14 @@ xfs_fs_inode_init_once(
|
|||
"xfsino", ip->i_ino);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called by the VFS when dirtying inode metadata. This can happen
|
||||
* for a few reasons, but we only care about timestamp updates, given that
|
||||
* we handled the rest ourselves. In theory no other calls should happen,
|
||||
* but for example generic_write_end() keeps dirtying the inode after
|
||||
* updating i_size. Thus we check that the flags are exactly I_DIRTY_SYNC,
|
||||
* and skip this call otherwise.
|
||||
*
|
||||
* We'll hopefull get a different method just for updating timestamps soon,
|
||||
* at which point this hack can go away, and maybe we'll also get real
|
||||
* error handling here.
|
||||
*/
|
||||
STATIC void
|
||||
xfs_fs_dirty_inode(
|
||||
struct inode *inode,
|
||||
int flags)
|
||||
{
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
struct xfs_trans *tp;
|
||||
int error;
|
||||
|
||||
if (flags != I_DIRTY_SYNC)
|
||||
return;
|
||||
|
||||
trace_xfs_dirty_inode(ip);
|
||||
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);
|
||||
error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0);
|
||||
if (error) {
|
||||
xfs_trans_cancel(tp, 0);
|
||||
goto trouble;
|
||||
}
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
/*
|
||||
* Grab all the latest timestamps from the Linux inode.
|
||||
*/
|
||||
ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
|
||||
ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
|
||||
ip->i_d.di_ctime.t_sec = (__int32_t)inode->i_ctime.tv_sec;
|
||||
ip->i_d.di_ctime.t_nsec = (__int32_t)inode->i_ctime.tv_nsec;
|
||||
ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec;
|
||||
ip->i_d.di_mtime.t_nsec = (__int32_t)inode->i_mtime.tv_nsec;
|
||||
|
||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP);
|
||||
error = xfs_trans_commit(tp, 0);
|
||||
if (error)
|
||||
goto trouble;
|
||||
return;
|
||||
|
||||
trouble:
|
||||
xfs_warn(mp, "failed to update timestamps for inode 0x%llx", ip->i_ino);
|
||||
}
|
||||
|
||||
STATIC void
|
||||
xfs_fs_evict_inode(
|
||||
struct inode *inode)
|
||||
{
|
||||
xfs_inode_t *ip = XFS_I(inode);
|
||||
|
||||
ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
|
||||
|
||||
trace_xfs_evict_inode(ip);
|
||||
|
||||
truncate_inode_pages(&inode->i_data, 0);
|
||||
|
@ -937,22 +884,6 @@ xfs_fs_evict_inode(
|
|||
XFS_STATS_INC(vn_remove);
|
||||
XFS_STATS_DEC(vn_active);
|
||||
|
||||
/*
|
||||
* The iolock is used by the file system to coordinate reads,
|
||||
* writes, and block truncates. Up to this point the lock
|
||||
* protected concurrent accesses by users of the inode. But
|
||||
* from here forward we're doing some final processing of the
|
||||
* inode because we're done with it, and although we reuse the
|
||||
* iolock for protection it is really a distinct lock class
|
||||
* (in the lockdep sense) from before. To keep lockdep happy
|
||||
* (and basically indicate what we are doing), we explicitly
|
||||
* re-init the iolock here.
|
||||
*/
|
||||
ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
|
||||
mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
|
||||
lockdep_set_class_and_name(&ip->i_iolock.mr_lock,
|
||||
&xfs_iolock_reclaimable, "xfs_iolock_reclaimable");
|
||||
|
||||
xfs_inactive(ip);
|
||||
}
|
||||
|
||||
|
@ -1436,7 +1367,6 @@ xfs_fs_free_cached_objects(
|
|||
static const struct super_operations xfs_super_operations = {
|
||||
.alloc_inode = xfs_fs_alloc_inode,
|
||||
.destroy_inode = xfs_fs_destroy_inode,
|
||||
.dirty_inode = xfs_fs_dirty_inode,
|
||||
.evict_inode = xfs_fs_evict_inode,
|
||||
.drop_inode = xfs_fs_drop_inode,
|
||||
.put_super = xfs_fs_put_super,
|
||||
|
@ -1491,13 +1421,9 @@ xfs_init_zones(void)
|
|||
if (!xfs_da_state_zone)
|
||||
goto out_destroy_btree_cur_zone;
|
||||
|
||||
xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
|
||||
if (!xfs_dabuf_zone)
|
||||
goto out_destroy_da_state_zone;
|
||||
|
||||
xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
|
||||
if (!xfs_ifork_zone)
|
||||
goto out_destroy_dabuf_zone;
|
||||
goto out_destroy_da_state_zone;
|
||||
|
||||
xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
|
||||
if (!xfs_trans_zone)
|
||||
|
@ -1514,9 +1440,8 @@ xfs_init_zones(void)
|
|||
* size possible under XFS. This wastes a little bit of memory,
|
||||
* but it is much faster.
|
||||
*/
|
||||
xfs_buf_item_zone = kmem_zone_init((sizeof(xfs_buf_log_item_t) +
|
||||
(((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) /
|
||||
NBWORD) * sizeof(int))), "xfs_buf_item");
|
||||
xfs_buf_item_zone = kmem_zone_init(sizeof(struct xfs_buf_log_item),
|
||||
"xfs_buf_item");
|
||||
if (!xfs_buf_item_zone)
|
||||
goto out_destroy_log_item_desc_zone;
|
||||
|
||||
|
@ -1561,8 +1486,6 @@ xfs_init_zones(void)
|
|||
kmem_zone_destroy(xfs_trans_zone);
|
||||
out_destroy_ifork_zone:
|
||||
kmem_zone_destroy(xfs_ifork_zone);
|
||||
out_destroy_dabuf_zone:
|
||||
kmem_zone_destroy(xfs_dabuf_zone);
|
||||
out_destroy_da_state_zone:
|
||||
kmem_zone_destroy(xfs_da_state_zone);
|
||||
out_destroy_btree_cur_zone:
|
||||
|
@ -1590,7 +1513,6 @@ xfs_destroy_zones(void)
|
|||
kmem_zone_destroy(xfs_log_item_desc_zone);
|
||||
kmem_zone_destroy(xfs_trans_zone);
|
||||
kmem_zone_destroy(xfs_ifork_zone);
|
||||
kmem_zone_destroy(xfs_dabuf_zone);
|
||||
kmem_zone_destroy(xfs_da_state_zone);
|
||||
kmem_zone_destroy(xfs_btree_cur_zone);
|
||||
kmem_zone_destroy(xfs_bmap_free_item_zone);
|
||||
|
|
|
@ -359,6 +359,15 @@ xfs_quiesce_attr(
|
|||
* added an item to the AIL, thus flush it again.
|
||||
*/
|
||||
xfs_ail_push_all_sync(mp->m_ail);
|
||||
|
||||
/*
|
||||
* The superblock buffer is uncached and xfsaild_push() will lock and
|
||||
* set the XBF_ASYNC flag on the buffer. We cannot do xfs_buf_iowait()
|
||||
* here but a lock on the superblock buffer will block until iodone()
|
||||
* has completed.
|
||||
*/
|
||||
xfs_buf_lock(mp->m_sb_bp);
|
||||
xfs_buf_unlock(mp->m_sb_bp);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -712,8 +721,8 @@ restart:
|
|||
* Note that xfs_iflush will never block on the inode buffer lock, as
|
||||
* xfs_ifree_cluster() can lock the inode buffer before it locks the
|
||||
* ip->i_lock, and we are doing the exact opposite here. As a result,
|
||||
* doing a blocking xfs_itobp() to get the cluster buffer would result
|
||||
* in an ABBA deadlock with xfs_ifree_cluster().
|
||||
* doing a blocking xfs_imap_to_bp() to get the cluster buffer would
|
||||
* result in an ABBA deadlock with xfs_ifree_cluster().
|
||||
*
|
||||
* As xfs_ifree_cluser() must gather all inodes that are active in the
|
||||
* cache to mark them stale, if we hit this case we don't actually want
|
||||
|
|
|
@ -578,8 +578,8 @@ DEFINE_INODE_EVENT(xfs_ioctl_setattr);
|
|||
DEFINE_INODE_EVENT(xfs_dir_fsync);
|
||||
DEFINE_INODE_EVENT(xfs_file_fsync);
|
||||
DEFINE_INODE_EVENT(xfs_destroy_inode);
|
||||
DEFINE_INODE_EVENT(xfs_dirty_inode);
|
||||
DEFINE_INODE_EVENT(xfs_evict_inode);
|
||||
DEFINE_INODE_EVENT(xfs_update_time);
|
||||
|
||||
DEFINE_INODE_EVENT(xfs_dquot_dqalloc);
|
||||
DEFINE_INODE_EVENT(xfs_dquot_dqdetach);
|
||||
|
|
|
@ -448,11 +448,51 @@ xfs_trans_t *xfs_trans_dup(xfs_trans_t *);
|
|||
int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint,
|
||||
uint, uint);
|
||||
void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t);
|
||||
struct xfs_buf *xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t,
|
||||
int, uint);
|
||||
int xfs_trans_read_buf(struct xfs_mount *, xfs_trans_t *,
|
||||
struct xfs_buftarg *, xfs_daddr_t, int, uint,
|
||||
struct xfs_buf **);
|
||||
|
||||
struct xfs_buf *xfs_trans_get_buf_map(struct xfs_trans *tp,
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps,
|
||||
uint flags);
|
||||
|
||||
static inline struct xfs_buf *
|
||||
xfs_trans_get_buf(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
int numblks,
|
||||
uint flags)
|
||||
{
|
||||
struct xfs_buf_map map = {
|
||||
.bm_bn = blkno,
|
||||
.bm_len = numblks,
|
||||
};
|
||||
return xfs_trans_get_buf_map(tp, target, &map, 1, flags);
|
||||
}
|
||||
|
||||
int xfs_trans_read_buf_map(struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps,
|
||||
xfs_buf_flags_t flags,
|
||||
struct xfs_buf **bpp);
|
||||
|
||||
static inline int
|
||||
xfs_trans_read_buf(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
int numblks,
|
||||
xfs_buf_flags_t flags,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
struct xfs_buf_map map = {
|
||||
.bm_bn = blkno,
|
||||
.bm_len = numblks,
|
||||
};
|
||||
return xfs_trans_read_buf_map(mp, tp, target, &map, 1, flags, bpp);
|
||||
}
|
||||
|
||||
struct xfs_buf *xfs_trans_getsb(xfs_trans_t *, struct xfs_mount *, int);
|
||||
|
||||
void xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *);
|
||||
|
|
|
@ -383,6 +383,12 @@ xfsaild_push(
|
|||
}
|
||||
|
||||
spin_lock(&ailp->xa_lock);
|
||||
|
||||
/* barrier matches the xa_target update in xfs_ail_push() */
|
||||
smp_rmb();
|
||||
target = ailp->xa_target;
|
||||
ailp->xa_target_prev = target;
|
||||
|
||||
lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn);
|
||||
if (!lip) {
|
||||
/*
|
||||
|
@ -397,7 +403,6 @@ xfsaild_push(
|
|||
XFS_STATS_INC(xs_push_ail);
|
||||
|
||||
lsn = lip->li_lsn;
|
||||
target = ailp->xa_target;
|
||||
while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) {
|
||||
int lock_result;
|
||||
|
||||
|
@ -527,8 +532,32 @@ xfsaild(
|
|||
__set_current_state(TASK_KILLABLE);
|
||||
else
|
||||
__set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(tout ?
|
||||
msecs_to_jiffies(tout) : MAX_SCHEDULE_TIMEOUT);
|
||||
|
||||
spin_lock(&ailp->xa_lock);
|
||||
|
||||
/*
|
||||
* Idle if the AIL is empty and we are not racing with a target
|
||||
* update. We check the AIL after we set the task to a sleep
|
||||
* state to guarantee that we either catch an xa_target update
|
||||
* or that a wake_up resets the state to TASK_RUNNING.
|
||||
* Otherwise, we run the risk of sleeping indefinitely.
|
||||
*
|
||||
* The barrier matches the xa_target update in xfs_ail_push().
|
||||
*/
|
||||
smp_rmb();
|
||||
if (!xfs_ail_min(ailp) &&
|
||||
ailp->xa_target == ailp->xa_target_prev) {
|
||||
spin_unlock(&ailp->xa_lock);
|
||||
schedule();
|
||||
tout = 0;
|
||||
continue;
|
||||
}
|
||||
spin_unlock(&ailp->xa_lock);
|
||||
|
||||
if (tout)
|
||||
schedule_timeout(msecs_to_jiffies(tout));
|
||||
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
try_to_freeze();
|
||||
|
||||
|
|
|
@ -41,20 +41,26 @@ STATIC struct xfs_buf *
|
|||
xfs_trans_buf_item_match(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
int len)
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps)
|
||||
{
|
||||
struct xfs_log_item_desc *lidp;
|
||||
struct xfs_buf_log_item *blip;
|
||||
int len = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nmaps; i++)
|
||||
len += map[i].bm_len;
|
||||
|
||||
len = BBTOB(len);
|
||||
list_for_each_entry(lidp, &tp->t_items, lid_trans) {
|
||||
blip = (struct xfs_buf_log_item *)lidp->lid_item;
|
||||
if (blip->bli_item.li_type == XFS_LI_BUF &&
|
||||
blip->bli_buf->b_target == target &&
|
||||
XFS_BUF_ADDR(blip->bli_buf) == blkno &&
|
||||
BBTOB(blip->bli_buf->b_length) == len)
|
||||
XFS_BUF_ADDR(blip->bli_buf) == map[0].bm_bn &&
|
||||
blip->bli_buf->b_length == len) {
|
||||
ASSERT(blip->bli_buf->b_map_count == nmaps);
|
||||
return blip->bli_buf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -128,21 +134,19 @@ xfs_trans_bjoin(
|
|||
* If the transaction pointer is NULL, make this just a normal
|
||||
* get_buf() call.
|
||||
*/
|
||||
xfs_buf_t *
|
||||
xfs_trans_get_buf(xfs_trans_t *tp,
|
||||
xfs_buftarg_t *target_dev,
|
||||
xfs_daddr_t blkno,
|
||||
int len,
|
||||
uint flags)
|
||||
struct xfs_buf *
|
||||
xfs_trans_get_buf_map(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps,
|
||||
xfs_buf_flags_t flags)
|
||||
{
|
||||
xfs_buf_t *bp;
|
||||
xfs_buf_log_item_t *bip;
|
||||
|
||||
/*
|
||||
* Default to a normal get_buf() call if the tp is NULL.
|
||||
*/
|
||||
if (tp == NULL)
|
||||
return xfs_buf_get(target_dev, blkno, len, flags);
|
||||
if (!tp)
|
||||
return xfs_buf_get_map(target, map, nmaps, flags);
|
||||
|
||||
/*
|
||||
* If we find the buffer in the cache with this transaction
|
||||
|
@ -150,7 +154,7 @@ xfs_trans_get_buf(xfs_trans_t *tp,
|
|||
* have it locked. In this case we just increment the lock
|
||||
* recursion count and return the buffer to the caller.
|
||||
*/
|
||||
bp = xfs_trans_buf_item_match(tp, target_dev, blkno, len);
|
||||
bp = xfs_trans_buf_item_match(tp, target, map, nmaps);
|
||||
if (bp != NULL) {
|
||||
ASSERT(xfs_buf_islocked(bp));
|
||||
if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) {
|
||||
|
@ -167,7 +171,7 @@ xfs_trans_get_buf(xfs_trans_t *tp,
|
|||
return (bp);
|
||||
}
|
||||
|
||||
bp = xfs_buf_get(target_dev, blkno, len, flags);
|
||||
bp = xfs_buf_get_map(target, map, nmaps, flags);
|
||||
if (bp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -246,26 +250,22 @@ int xfs_error_mod = 33;
|
|||
* read_buf() call.
|
||||
*/
|
||||
int
|
||||
xfs_trans_read_buf(
|
||||
xfs_mount_t *mp,
|
||||
xfs_trans_t *tp,
|
||||
xfs_buftarg_t *target,
|
||||
xfs_daddr_t blkno,
|
||||
int len,
|
||||
uint flags,
|
||||
xfs_buf_t **bpp)
|
||||
xfs_trans_read_buf_map(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps,
|
||||
xfs_buf_flags_t flags,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
xfs_buf_t *bp;
|
||||
xfs_buf_log_item_t *bip;
|
||||
int error;
|
||||
|
||||
*bpp = NULL;
|
||||
|
||||
/*
|
||||
* Default to a normal get_buf() call if the tp is NULL.
|
||||
*/
|
||||
if (tp == NULL) {
|
||||
bp = xfs_buf_read(target, blkno, len, flags);
|
||||
if (!tp) {
|
||||
bp = xfs_buf_read_map(target, map, nmaps, flags);
|
||||
if (!bp)
|
||||
return (flags & XBF_TRYLOCK) ?
|
||||
EAGAIN : XFS_ERROR(ENOMEM);
|
||||
|
@ -303,7 +303,7 @@ xfs_trans_read_buf(
|
|||
* If the buffer is not yet read in, then we read it in, increment
|
||||
* the lock recursion count, and return it to the caller.
|
||||
*/
|
||||
bp = xfs_trans_buf_item_match(tp, target, blkno, len);
|
||||
bp = xfs_trans_buf_item_match(tp, target, map, nmaps);
|
||||
if (bp != NULL) {
|
||||
ASSERT(xfs_buf_islocked(bp));
|
||||
ASSERT(bp->b_transp == tp);
|
||||
|
@ -349,7 +349,7 @@ xfs_trans_read_buf(
|
|||
return 0;
|
||||
}
|
||||
|
||||
bp = xfs_buf_read(target, blkno, len, flags);
|
||||
bp = xfs_buf_read_map(target, map, nmaps, flags);
|
||||
if (bp == NULL) {
|
||||
*bpp = NULL;
|
||||
return (flags & XBF_TRYLOCK) ?
|
||||
|
|
|
@ -67,6 +67,7 @@ struct xfs_ail {
|
|||
struct task_struct *xa_task;
|
||||
struct list_head xa_ail;
|
||||
xfs_lsn_t xa_target;
|
||||
xfs_lsn_t xa_target_prev;
|
||||
struct list_head xa_cursors;
|
||||
spinlock_t xa_lock;
|
||||
xfs_lsn_t xa_last_pushed_lsn;
|
||||
|
|
|
@ -132,6 +132,20 @@ typedef __uint64_t xfs_filblks_t; /* number of blocks in a file */
|
|||
#define MAXEXTNUM ((xfs_extnum_t)0x7fffffff) /* signed int */
|
||||
#define MAXAEXTNUM ((xfs_aextnum_t)0x7fff) /* signed short */
|
||||
|
||||
/*
|
||||
* Minimum and maximum blocksize and sectorsize.
|
||||
* The blocksize upper limit is pretty much arbitrary.
|
||||
* The sectorsize upper limit is due to sizeof(sb_sectsize).
|
||||
*/
|
||||
#define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */
|
||||
#define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */
|
||||
#define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG)
|
||||
#define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG)
|
||||
#define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */
|
||||
#define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */
|
||||
#define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG)
|
||||
#define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG)
|
||||
|
||||
/*
|
||||
* Min numbers of data/attr fork btree root pointers.
|
||||
*/
|
||||
|
|
|
@ -65,7 +65,6 @@ xfs_dir_ialloc(
|
|||
xfs_trans_t *ntp;
|
||||
xfs_inode_t *ip;
|
||||
xfs_buf_t *ialloc_context = NULL;
|
||||
boolean_t call_again = B_FALSE;
|
||||
int code;
|
||||
uint log_res;
|
||||
uint log_count;
|
||||
|
@ -91,7 +90,7 @@ xfs_dir_ialloc(
|
|||
* the inode(s) that we've just allocated.
|
||||
*/
|
||||
code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid, okalloc,
|
||||
&ialloc_context, &call_again, &ip);
|
||||
&ialloc_context, &ip);
|
||||
|
||||
/*
|
||||
* Return an error if we were unable to allocate a new inode.
|
||||
|
@ -102,19 +101,18 @@ xfs_dir_ialloc(
|
|||
*ipp = NULL;
|
||||
return code;
|
||||
}
|
||||
if (!call_again && (ip == NULL)) {
|
||||
if (!ialloc_context && !ip) {
|
||||
*ipp = NULL;
|
||||
return XFS_ERROR(ENOSPC);
|
||||
}
|
||||
|
||||
/*
|
||||
* If call_again is set, then we were unable to get an
|
||||
* If the AGI buffer is non-NULL, then we were unable to get an
|
||||
* inode in one operation. We need to commit the current
|
||||
* transaction and call xfs_ialloc() again. It is guaranteed
|
||||
* to succeed the second time.
|
||||
*/
|
||||
if (call_again) {
|
||||
|
||||
if (ialloc_context) {
|
||||
/*
|
||||
* Normally, xfs_trans_commit releases all the locks.
|
||||
* We call bhold to hang on to the ialloc_context across
|
||||
|
@ -195,7 +193,7 @@ xfs_dir_ialloc(
|
|||
* this call should always succeed.
|
||||
*/
|
||||
code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid,
|
||||
okalloc, &ialloc_context, &call_again, &ip);
|
||||
okalloc, &ialloc_context, &ip);
|
||||
|
||||
/*
|
||||
* If we get an error at this point, return to the caller
|
||||
|
@ -206,12 +204,11 @@ xfs_dir_ialloc(
|
|||
*ipp = NULL;
|
||||
return code;
|
||||
}
|
||||
ASSERT ((!call_again) && (ip != NULL));
|
||||
ASSERT(!ialloc_context && ip);
|
||||
|
||||
} else {
|
||||
if (committed != NULL) {
|
||||
if (committed != NULL)
|
||||
*committed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*ipp = ip;
|
||||
|
|
|
@ -145,11 +145,6 @@ xfs_readlink(
|
|||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flags for xfs_free_eofblocks
|
||||
*/
|
||||
#define XFS_FREE_EOF_TRYLOCK (1<<0)
|
||||
|
||||
/*
|
||||
* This is called by xfs_inactive to free any blocks beyond eof
|
||||
* when the link count isn't zero and by xfs_dm_punch_hole() when
|
||||
|
@ -159,7 +154,7 @@ STATIC int
|
|||
xfs_free_eofblocks(
|
||||
xfs_mount_t *mp,
|
||||
xfs_inode_t *ip,
|
||||
int flags)
|
||||
bool need_iolock)
|
||||
{
|
||||
xfs_trans_t *tp;
|
||||
int error;
|
||||
|
@ -174,7 +169,7 @@ xfs_free_eofblocks(
|
|||
* of the file. If not, then there is nothing to do.
|
||||
*/
|
||||
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip));
|
||||
last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
|
||||
last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
|
||||
if (last_fsb <= end_fsb)
|
||||
return 0;
|
||||
map_len = last_fsb - end_fsb;
|
||||
|
@ -201,13 +196,11 @@ xfs_free_eofblocks(
|
|||
*/
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
|
||||
|
||||
if (flags & XFS_FREE_EOF_TRYLOCK) {
|
||||
if (need_iolock) {
|
||||
if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
|
||||
xfs_trans_cancel(tp, 0);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||
}
|
||||
|
||||
error = xfs_trans_reserve(tp, 0,
|
||||
|
@ -217,7 +210,8 @@ xfs_free_eofblocks(
|
|||
if (error) {
|
||||
ASSERT(XFS_FORCED_SHUTDOWN(mp));
|
||||
xfs_trans_cancel(tp, 0);
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
if (need_iolock)
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -244,7 +238,10 @@ xfs_free_eofblocks(
|
|||
error = xfs_trans_commit(tp,
|
||||
XFS_TRANS_RELEASE_LOG_RES);
|
||||
}
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL);
|
||||
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
if (need_iolock)
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -282,23 +279,15 @@ xfs_inactive_symlink_rmt(
|
|||
* free them all in one bunmapi call.
|
||||
*/
|
||||
ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
|
||||
if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
|
||||
XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) {
|
||||
ASSERT(XFS_FORCED_SHUTDOWN(mp));
|
||||
xfs_trans_cancel(tp, 0);
|
||||
*tpp = NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock the inode, fix the size, and join it to the transaction.
|
||||
* Hold it so in the normal path, we still have it locked for
|
||||
* the second transaction. In the error paths we need it
|
||||
* held so the cancel won't rele it, see below.
|
||||
*/
|
||||
xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
|
||||
size = (int)ip->i_d.di_size;
|
||||
ip->i_d.di_size = 0;
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||
/*
|
||||
* Find the block(s) so we can inval and unmap them.
|
||||
|
@ -385,114 +374,14 @@ xfs_inactive_symlink_rmt(
|
|||
ASSERT(XFS_FORCED_SHUTDOWN(mp));
|
||||
goto error0;
|
||||
}
|
||||
/*
|
||||
* Return with the inode locked but not joined to the transaction.
|
||||
*/
|
||||
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
*tpp = tp;
|
||||
return 0;
|
||||
|
||||
error1:
|
||||
xfs_bmap_cancel(&free_list);
|
||||
error0:
|
||||
/*
|
||||
* Have to come here with the inode locked and either
|
||||
* (held and in the transaction) or (not in the transaction).
|
||||
* If the inode isn't held then cancel would iput it, but
|
||||
* that's wrong since this is inactive and the vnode ref
|
||||
* count is 0 already.
|
||||
* Cancel won't do anything to the inode if held, but it still
|
||||
* needs to be locked until the cancel is done, if it was
|
||||
* joined to the transaction.
|
||||
*/
|
||||
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
|
||||
*tpp = NULL;
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_inactive_symlink_local(
|
||||
xfs_inode_t *ip,
|
||||
xfs_trans_t **tpp)
|
||||
{
|
||||
int error;
|
||||
|
||||
ASSERT(ip->i_d.di_size <= XFS_IFORK_DSIZE(ip));
|
||||
/*
|
||||
* We're freeing a symlink which fit into
|
||||
* the inode. Just free the memory used
|
||||
* to hold the old symlink.
|
||||
*/
|
||||
error = xfs_trans_reserve(*tpp, 0,
|
||||
XFS_ITRUNCATE_LOG_RES(ip->i_mount),
|
||||
0, XFS_TRANS_PERM_LOG_RES,
|
||||
XFS_ITRUNCATE_LOG_COUNT);
|
||||
|
||||
if (error) {
|
||||
xfs_trans_cancel(*tpp, 0);
|
||||
*tpp = NULL;
|
||||
return error;
|
||||
}
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
||||
|
||||
/*
|
||||
* Zero length symlinks _can_ exist.
|
||||
*/
|
||||
if (ip->i_df.if_bytes > 0) {
|
||||
xfs_idata_realloc(ip,
|
||||
-(ip->i_df.if_bytes),
|
||||
XFS_DATA_FORK);
|
||||
ASSERT(ip->i_df.if_bytes == 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_inactive_attrs(
|
||||
xfs_inode_t *ip,
|
||||
xfs_trans_t **tpp)
|
||||
{
|
||||
xfs_trans_t *tp;
|
||||
int error;
|
||||
xfs_mount_t *mp;
|
||||
|
||||
ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
|
||||
tp = *tpp;
|
||||
mp = ip->i_mount;
|
||||
ASSERT(ip->i_d.di_forkoff != 0);
|
||||
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
if (error)
|
||||
goto error_unlock;
|
||||
|
||||
error = xfs_attr_inactive(ip);
|
||||
if (error)
|
||||
goto error_unlock;
|
||||
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
|
||||
error = xfs_trans_reserve(tp, 0,
|
||||
XFS_IFREE_LOG_RES(mp),
|
||||
0, XFS_TRANS_PERM_LOG_RES,
|
||||
XFS_INACTIVE_LOG_COUNT);
|
||||
if (error)
|
||||
goto error_cancel;
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
xfs_idestroy_fork(ip, XFS_ATTR_FORK);
|
||||
|
||||
ASSERT(ip->i_d.di_anextents == 0);
|
||||
|
||||
*tpp = tp;
|
||||
return 0;
|
||||
|
||||
error_cancel:
|
||||
ASSERT(XFS_FORCED_SHUTDOWN(mp));
|
||||
xfs_trans_cancel(tp, 0);
|
||||
error_unlock:
|
||||
*tpp = NULL;
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -574,8 +463,7 @@ xfs_release(
|
|||
if (xfs_iflags_test(ip, XFS_IDIRTY_RELEASE))
|
||||
return 0;
|
||||
|
||||
error = xfs_free_eofblocks(mp, ip,
|
||||
XFS_FREE_EOF_TRYLOCK);
|
||||
error = xfs_free_eofblocks(mp, ip, true);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -604,7 +492,7 @@ xfs_inactive(
|
|||
xfs_trans_t *tp;
|
||||
xfs_mount_t *mp;
|
||||
int error;
|
||||
int truncate;
|
||||
int truncate = 0;
|
||||
|
||||
/*
|
||||
* If the inode is already free, then there can be nothing
|
||||
|
@ -616,17 +504,6 @@ xfs_inactive(
|
|||
return VN_INACTIVE_CACHE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only do a truncate if it's a regular file with
|
||||
* some actual space in it. It's OK to look at the
|
||||
* inode's fields without the lock because we're the
|
||||
* only one with a reference to the inode.
|
||||
*/
|
||||
truncate = ((ip->i_d.di_nlink == 0) &&
|
||||
((ip->i_d.di_size != 0) || XFS_ISIZE(ip) != 0 ||
|
||||
(ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) &&
|
||||
S_ISREG(ip->i_d.di_mode));
|
||||
|
||||
mp = ip->i_mount;
|
||||
|
||||
error = 0;
|
||||
|
@ -643,99 +520,100 @@ xfs_inactive(
|
|||
(!(ip->i_d.di_flags &
|
||||
(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
|
||||
ip->i_delayed_blks != 0))) {
|
||||
error = xfs_free_eofblocks(mp, ip, 0);
|
||||
error = xfs_free_eofblocks(mp, ip, false);
|
||||
if (error)
|
||||
return VN_INACTIVE_CACHE;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
ASSERT(ip->i_d.di_nlink == 0);
|
||||
if (S_ISREG(ip->i_d.di_mode) &&
|
||||
(ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 ||
|
||||
ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0))
|
||||
truncate = 1;
|
||||
|
||||
error = xfs_qm_dqattach(ip, 0);
|
||||
if (error)
|
||||
return VN_INACTIVE_CACHE;
|
||||
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
|
||||
if (truncate) {
|
||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||
error = xfs_trans_reserve(tp, 0,
|
||||
(truncate || S_ISLNK(ip->i_d.di_mode)) ?
|
||||
XFS_ITRUNCATE_LOG_RES(mp) :
|
||||
XFS_IFREE_LOG_RES(mp),
|
||||
0,
|
||||
XFS_TRANS_PERM_LOG_RES,
|
||||
XFS_ITRUNCATE_LOG_COUNT);
|
||||
if (error) {
|
||||
ASSERT(XFS_FORCED_SHUTDOWN(mp));
|
||||
xfs_trans_cancel(tp, 0);
|
||||
return VN_INACTIVE_CACHE;
|
||||
}
|
||||
|
||||
error = xfs_trans_reserve(tp, 0,
|
||||
XFS_ITRUNCATE_LOG_RES(mp),
|
||||
0, XFS_TRANS_PERM_LOG_RES,
|
||||
XFS_ITRUNCATE_LOG_COUNT);
|
||||
if (error) {
|
||||
/* Don't call itruncate_cleanup */
|
||||
ASSERT(XFS_FORCED_SHUTDOWN(mp));
|
||||
xfs_trans_cancel(tp, 0);
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
return VN_INACTIVE_CACHE;
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
|
||||
if (S_ISLNK(ip->i_d.di_mode)) {
|
||||
/*
|
||||
* Zero length symlinks _can_ exist.
|
||||
*/
|
||||
if (ip->i_d.di_size > XFS_IFORK_DSIZE(ip)) {
|
||||
error = xfs_inactive_symlink_rmt(ip, &tp);
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
} else if (ip->i_df.if_bytes > 0) {
|
||||
xfs_idata_realloc(ip, -(ip->i_df.if_bytes),
|
||||
XFS_DATA_FORK);
|
||||
ASSERT(ip->i_df.if_bytes == 0);
|
||||
}
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
|
||||
} else if (truncate) {
|
||||
ip->i_d.di_size = 0;
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||
|
||||
error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
|
||||
if (error) {
|
||||
xfs_trans_cancel(tp,
|
||||
XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
|
||||
return VN_INACTIVE_CACHE;
|
||||
}
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
|
||||
ASSERT(ip->i_d.di_nextents == 0);
|
||||
} else if (S_ISLNK(ip->i_d.di_mode)) {
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get an error while cleaning up a
|
||||
* symlink we bail out.
|
||||
*/
|
||||
error = (ip->i_d.di_size > XFS_IFORK_DSIZE(ip)) ?
|
||||
xfs_inactive_symlink_rmt(ip, &tp) :
|
||||
xfs_inactive_symlink_local(ip, &tp);
|
||||
/*
|
||||
* If there are attributes associated with the file then blow them away
|
||||
* now. The code calls a routine that recursively deconstructs the
|
||||
* attribute fork. We need to just commit the current transaction
|
||||
* because we can't use it for xfs_attr_inactive().
|
||||
*/
|
||||
if (ip->i_d.di_anextents > 0) {
|
||||
ASSERT(ip->i_d.di_forkoff != 0);
|
||||
|
||||
if (error) {
|
||||
ASSERT(tp == NULL);
|
||||
return VN_INACTIVE_CACHE;
|
||||
}
|
||||
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
} else {
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
|
||||
error = xfs_attr_inactive(ip);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
|
||||
error = xfs_trans_reserve(tp, 0,
|
||||
XFS_IFREE_LOG_RES(mp),
|
||||
0, XFS_TRANS_PERM_LOG_RES,
|
||||
XFS_INACTIVE_LOG_COUNT);
|
||||
if (error) {
|
||||
ASSERT(XFS_FORCED_SHUTDOWN(mp));
|
||||
xfs_trans_cancel(tp, 0);
|
||||
return VN_INACTIVE_CACHE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are attributes associated with the file
|
||||
* then blow them away now. The code calls a routine
|
||||
* that recursively deconstructs the attribute fork.
|
||||
* We need to just commit the current transaction
|
||||
* because we can't use it for xfs_attr_inactive().
|
||||
*/
|
||||
if (ip->i_d.di_anextents > 0) {
|
||||
error = xfs_inactive_attrs(ip, &tp);
|
||||
/*
|
||||
* If we got an error, the transaction is already
|
||||
* cancelled, and the inode is unlocked. Just get out.
|
||||
*/
|
||||
if (error)
|
||||
return VN_INACTIVE_CACHE;
|
||||
} else if (ip->i_afp) {
|
||||
if (ip->i_afp)
|
||||
xfs_idestroy_fork(ip, XFS_ATTR_FORK);
|
||||
}
|
||||
|
||||
ASSERT(ip->i_d.di_anextents == 0);
|
||||
|
||||
/*
|
||||
* Free the inode.
|
||||
|
@ -779,10 +657,13 @@ xfs_inactive(
|
|||
* Release the dquots held by inode, if any.
|
||||
*/
|
||||
xfs_qm_dqdetach(ip);
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
|
||||
|
||||
out:
|
||||
out_unlock:
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
out:
|
||||
return VN_INACTIVE_CACHE;
|
||||
out_cancel:
|
||||
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2262,10 +2143,10 @@ xfs_change_file_space(
|
|||
|
||||
llen = bf->l_len > 0 ? bf->l_len - 1 : bf->l_len;
|
||||
|
||||
if ( (bf->l_start < 0)
|
||||
|| (bf->l_start > XFS_MAXIOFFSET(mp))
|
||||
|| (bf->l_start + llen < 0)
|
||||
|| (bf->l_start + llen > XFS_MAXIOFFSET(mp)))
|
||||
if (bf->l_start < 0 ||
|
||||
bf->l_start > mp->m_super->s_maxbytes ||
|
||||
bf->l_start + llen < 0 ||
|
||||
bf->l_start + llen > mp->m_super->s_maxbytes)
|
||||
return XFS_ERROR(EINVAL);
|
||||
|
||||
bf->l_whence = 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче