mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-30 15:44:13 +08:00
bde7cff67c
Instead of setting up pointers to memory locations in iop_format which then get copied into the CIL linear buffer after return move the copy into the individual inode items. This avoids the need to always have a memory block in the exact same layout that gets written into the log around, and allow the log items to be much more flexible in their in-memory layouts. The only caveat is that we need to properly align the data for each iovec so that don't have structures misaligned in subsequent iovecs. Note that all log item format routines now need to be careful to modify the copy of the item that was placed into the CIL after calls to xlog_copy_iovec instead of the in-memory copy. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
190 lines
4.9 KiB
C
190 lines
4.9 KiB
C
/*
|
|
* Copyright (c) 2008-2010, 2013 Dave Chinner
|
|
* All Rights Reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it would be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#include "xfs.h"
|
|
#include "xfs_fs.h"
|
|
#include "xfs_shared.h"
|
|
#include "xfs_log_format.h"
|
|
#include "xfs_trans_resv.h"
|
|
#include "xfs_bit.h"
|
|
#include "xfs_sb.h"
|
|
#include "xfs_ag.h"
|
|
#include "xfs_mount.h"
|
|
#include "xfs_trans.h"
|
|
#include "xfs_trans_priv.h"
|
|
#include "xfs_error.h"
|
|
#include "xfs_icreate_item.h"
|
|
#include "xfs_log.h"
|
|
|
|
kmem_zone_t *xfs_icreate_zone; /* inode create item zone */
|
|
|
|
static inline struct xfs_icreate_item *ICR_ITEM(struct xfs_log_item *lip)
|
|
{
|
|
return container_of(lip, struct xfs_icreate_item, ic_item);
|
|
}
|
|
|
|
/*
|
|
* This returns the number of iovecs needed to log the given inode item.
|
|
*
|
|
* We only need one iovec for the icreate log structure.
|
|
*/
|
|
STATIC void
|
|
xfs_icreate_item_size(
|
|
struct xfs_log_item *lip,
|
|
int *nvecs,
|
|
int *nbytes)
|
|
{
|
|
*nvecs += 1;
|
|
*nbytes += sizeof(struct xfs_icreate_log);
|
|
}
|
|
|
|
/*
|
|
* This is called to fill in the vector of log iovecs for the
|
|
* given inode create log item.
|
|
*/
|
|
STATIC void
|
|
xfs_icreate_item_format(
|
|
struct xfs_log_item *lip,
|
|
struct xfs_log_vec *lv)
|
|
{
|
|
struct xfs_icreate_item *icp = ICR_ITEM(lip);
|
|
struct xfs_log_iovec *vecp = NULL;
|
|
|
|
xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICREATE,
|
|
&icp->ic_format,
|
|
sizeof(struct xfs_icreate_log));
|
|
}
|
|
|
|
|
|
/* Pinning has no meaning for the create item, so just return. */
|
|
STATIC void
|
|
xfs_icreate_item_pin(
|
|
struct xfs_log_item *lip)
|
|
{
|
|
}
|
|
|
|
|
|
/* pinning has no meaning for the create item, so just return. */
|
|
STATIC void
|
|
xfs_icreate_item_unpin(
|
|
struct xfs_log_item *lip,
|
|
int remove)
|
|
{
|
|
}
|
|
|
|
STATIC void
|
|
xfs_icreate_item_unlock(
|
|
struct xfs_log_item *lip)
|
|
{
|
|
struct xfs_icreate_item *icp = ICR_ITEM(lip);
|
|
|
|
if (icp->ic_item.li_flags & XFS_LI_ABORTED)
|
|
kmem_zone_free(xfs_icreate_zone, icp);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Because we have ordered buffers being tracked in the AIL for the inode
|
|
* creation, we don't need the create item after this. Hence we can free
|
|
* the log item and return -1 to tell the caller we're done with the item.
|
|
*/
|
|
STATIC xfs_lsn_t
|
|
xfs_icreate_item_committed(
|
|
struct xfs_log_item *lip,
|
|
xfs_lsn_t lsn)
|
|
{
|
|
struct xfs_icreate_item *icp = ICR_ITEM(lip);
|
|
|
|
kmem_zone_free(xfs_icreate_zone, icp);
|
|
return (xfs_lsn_t)-1;
|
|
}
|
|
|
|
/* item can never get into the AIL */
|
|
STATIC uint
|
|
xfs_icreate_item_push(
|
|
struct xfs_log_item *lip,
|
|
struct list_head *buffer_list)
|
|
{
|
|
ASSERT(0);
|
|
return XFS_ITEM_SUCCESS;
|
|
}
|
|
|
|
/* Ordered buffers do the dependency tracking here, so this does nothing. */
|
|
STATIC void
|
|
xfs_icreate_item_committing(
|
|
struct xfs_log_item *lip,
|
|
xfs_lsn_t lsn)
|
|
{
|
|
}
|
|
|
|
/*
|
|
* This is the ops vector shared by all buf log items.
|
|
*/
|
|
static struct xfs_item_ops xfs_icreate_item_ops = {
|
|
.iop_size = xfs_icreate_item_size,
|
|
.iop_format = xfs_icreate_item_format,
|
|
.iop_pin = xfs_icreate_item_pin,
|
|
.iop_unpin = xfs_icreate_item_unpin,
|
|
.iop_push = xfs_icreate_item_push,
|
|
.iop_unlock = xfs_icreate_item_unlock,
|
|
.iop_committed = xfs_icreate_item_committed,
|
|
.iop_committing = xfs_icreate_item_committing,
|
|
};
|
|
|
|
|
|
/*
|
|
* Initialize the inode log item for a newly allocated (in-core) inode.
|
|
*
|
|
* Inode extents can only reside within an AG. Hence specify the starting
|
|
* block for the inode chunk by offset within an AG as well as the
|
|
* length of the allocated extent.
|
|
*
|
|
* This joins the item to the transaction and marks it dirty so
|
|
* that we don't need a separate call to do this, nor does the
|
|
* caller need to know anything about the icreate item.
|
|
*/
|
|
void
|
|
xfs_icreate_log(
|
|
struct xfs_trans *tp,
|
|
xfs_agnumber_t agno,
|
|
xfs_agblock_t agbno,
|
|
unsigned int count,
|
|
unsigned int inode_size,
|
|
xfs_agblock_t length,
|
|
unsigned int generation)
|
|
{
|
|
struct xfs_icreate_item *icp;
|
|
|
|
icp = kmem_zone_zalloc(xfs_icreate_zone, KM_SLEEP);
|
|
|
|
xfs_log_item_init(tp->t_mountp, &icp->ic_item, XFS_LI_ICREATE,
|
|
&xfs_icreate_item_ops);
|
|
|
|
icp->ic_format.icl_type = XFS_LI_ICREATE;
|
|
icp->ic_format.icl_size = 1; /* single vector */
|
|
icp->ic_format.icl_ag = cpu_to_be32(agno);
|
|
icp->ic_format.icl_agbno = cpu_to_be32(agbno);
|
|
icp->ic_format.icl_count = cpu_to_be32(count);
|
|
icp->ic_format.icl_isize = cpu_to_be32(inode_size);
|
|
icp->ic_format.icl_length = cpu_to_be32(length);
|
|
icp->ic_format.icl_gen = cpu_to_be32(generation);
|
|
|
|
xfs_trans_add_item(tp, &icp->ic_item);
|
|
tp->t_flags |= XFS_TRANS_DIRTY;
|
|
icp->ic_item.li_desc->lid_flags |= XFS_LID_DIRTY;
|
|
}
|