xfs_icreate_item.c 4.8 KB
Newer Older
D
Dave Chinner 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * 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"
20
#include "xfs_shared.h"
21
#include "xfs_format.h"
22 23
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
D
Dave Chinner 已提交
24 25
#include "xfs_bit.h"
#include "xfs_mount.h"
26
#include "xfs_trans.h"
D
Dave Chinner 已提交
27 28 29
#include "xfs_trans_priv.h"
#include "xfs_error.h"
#include "xfs_icreate_item.h"
C
Christoph Hellwig 已提交
30
#include "xfs_log.h"
D
Dave Chinner 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43

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.
 */
44
STATIC void
D
Dave Chinner 已提交
45
xfs_icreate_item_size(
46 47 48
	struct xfs_log_item	*lip,
	int			*nvecs,
	int			*nbytes)
D
Dave Chinner 已提交
49
{
50 51
	*nvecs += 1;
	*nbytes += sizeof(struct xfs_icreate_log);
D
Dave Chinner 已提交
52 53 54 55 56 57 58 59 60
}

/*
 * 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,
61
	struct xfs_log_vec	*lv)
D
Dave Chinner 已提交
62 63
{
	struct xfs_icreate_item	*icp = ICR_ITEM(lip);
64
	struct xfs_log_iovec	*vecp = NULL;
D
Dave Chinner 已提交
65

66
	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICREATE,
C
Christoph Hellwig 已提交
67 68
			&icp->ic_format,
			sizeof(struct xfs_icreate_log));
D
Dave Chinner 已提交
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
}


/* 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;
}