Commit 3ebe7d2d73179c4874aee4f32e043eb5acd9fa0f

Authored by Dave Chinner
Committed by Ben Myers
1 parent 5f6bed76c0

xfs: Inode create log items

Introduce the inode create log item type for logical inode create logging.
Instead of logging the changes in buffers, pass the range to be
initialised through the log by a new transaction type.  This reduces
the amount of log space required to record initialisation during
allocation from about 128 bytes per inode to a small fixed amount
per inode extent to be initialised.

This requires a new log item type to track it through the log
and the AIL. This is a relatively simple item - most callbacks are
noops as this item has the same life cycle as the transaction.

Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>

Showing 6 changed files with 261 additions and 2 deletions Side-by-side Diff

... ... @@ -71,6 +71,7 @@
71 71 xfs_dir2_sf.o \
72 72 xfs_ialloc.o \
73 73 xfs_ialloc_btree.o \
  74 + xfs_icreate_item.o \
74 75 xfs_inode.o \
75 76 xfs_log_recover.o \
76 77 xfs_mount.o \
fs/xfs/xfs_icreate_item.c
  1 +/*
  2 + * Copyright (c) 2008-2010, 2013 Dave Chinner
  3 + * All Rights Reserved.
  4 + *
  5 + * This program is free software; you can redistribute it and/or
  6 + * modify it under the terms of the GNU General Public License as
  7 + * published by the Free Software Foundation.
  8 + *
  9 + * This program is distributed in the hope that it would be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program; if not, write the Free Software Foundation,
  16 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17 + */
  18 +#include "xfs.h"
  19 +#include "xfs_fs.h"
  20 +#include "xfs_types.h"
  21 +#include "xfs_bit.h"
  22 +#include "xfs_log.h"
  23 +#include "xfs_inum.h"
  24 +#include "xfs_trans.h"
  25 +#include "xfs_buf_item.h"
  26 +#include "xfs_sb.h"
  27 +#include "xfs_ag.h"
  28 +#include "xfs_dir2.h"
  29 +#include "xfs_mount.h"
  30 +#include "xfs_trans_priv.h"
  31 +#include "xfs_bmap_btree.h"
  32 +#include "xfs_alloc_btree.h"
  33 +#include "xfs_ialloc_btree.h"
  34 +#include "xfs_attr_sf.h"
  35 +#include "xfs_dinode.h"
  36 +#include "xfs_inode.h"
  37 +#include "xfs_inode_item.h"
  38 +#include "xfs_btree.h"
  39 +#include "xfs_ialloc.h"
  40 +#include "xfs_error.h"
  41 +#include "xfs_icreate_item.h"
  42 +
  43 +kmem_zone_t *xfs_icreate_zone; /* inode create item zone */
  44 +
  45 +static inline struct xfs_icreate_item *ICR_ITEM(struct xfs_log_item *lip)
  46 +{
  47 + return container_of(lip, struct xfs_icreate_item, ic_item);
  48 +}
  49 +
  50 +/*
  51 + * This returns the number of iovecs needed to log the given inode item.
  52 + *
  53 + * We only need one iovec for the icreate log structure.
  54 + */
  55 +STATIC uint
  56 +xfs_icreate_item_size(
  57 + struct xfs_log_item *lip)
  58 +{
  59 + return 1;
  60 +}
  61 +
  62 +/*
  63 + * This is called to fill in the vector of log iovecs for the
  64 + * given inode create log item.
  65 + */
  66 +STATIC void
  67 +xfs_icreate_item_format(
  68 + struct xfs_log_item *lip,
  69 + struct xfs_log_iovec *log_vector)
  70 +{
  71 + struct xfs_icreate_item *icp = ICR_ITEM(lip);
  72 +
  73 + log_vector->i_addr = (xfs_caddr_t)&icp->ic_format;
  74 + log_vector->i_len = sizeof(struct xfs_icreate_log);
  75 + log_vector->i_type = XLOG_REG_TYPE_ICREATE;
  76 +}
  77 +
  78 +
  79 +/* Pinning has no meaning for the create item, so just return. */
  80 +STATIC void
  81 +xfs_icreate_item_pin(
  82 + struct xfs_log_item *lip)
  83 +{
  84 +}
  85 +
  86 +
  87 +/* pinning has no meaning for the create item, so just return. */
  88 +STATIC void
  89 +xfs_icreate_item_unpin(
  90 + struct xfs_log_item *lip,
  91 + int remove)
  92 +{
  93 +}
  94 +
  95 +STATIC void
  96 +xfs_icreate_item_unlock(
  97 + struct xfs_log_item *lip)
  98 +{
  99 + struct xfs_icreate_item *icp = ICR_ITEM(lip);
  100 +
  101 + if (icp->ic_item.li_flags & XFS_LI_ABORTED)
  102 + kmem_zone_free(xfs_icreate_zone, icp);
  103 + return;
  104 +}
  105 +
  106 +/*
  107 + * Because we have ordered buffers being tracked in the AIL for the inode
  108 + * creation, we don't need the create item after this. Hence we can free
  109 + * the log item and return -1 to tell the caller we're done with the item.
  110 + */
  111 +STATIC xfs_lsn_t
  112 +xfs_icreate_item_committed(
  113 + struct xfs_log_item *lip,
  114 + xfs_lsn_t lsn)
  115 +{
  116 + struct xfs_icreate_item *icp = ICR_ITEM(lip);
  117 +
  118 + kmem_zone_free(xfs_icreate_zone, icp);
  119 + return (xfs_lsn_t)-1;
  120 +}
  121 +
  122 +/* item can never get into the AIL */
  123 +STATIC uint
  124 +xfs_icreate_item_push(
  125 + struct xfs_log_item *lip,
  126 + struct list_head *buffer_list)
  127 +{
  128 + ASSERT(0);
  129 + return XFS_ITEM_SUCCESS;
  130 +}
  131 +
  132 +/* Ordered buffers do the dependency tracking here, so this does nothing. */
  133 +STATIC void
  134 +xfs_icreate_item_committing(
  135 + struct xfs_log_item *lip,
  136 + xfs_lsn_t lsn)
  137 +{
  138 +}
  139 +
  140 +/*
  141 + * This is the ops vector shared by all buf log items.
  142 + */
  143 +static struct xfs_item_ops xfs_icreate_item_ops = {
  144 + .iop_size = xfs_icreate_item_size,
  145 + .iop_format = xfs_icreate_item_format,
  146 + .iop_pin = xfs_icreate_item_pin,
  147 + .iop_unpin = xfs_icreate_item_unpin,
  148 + .iop_push = xfs_icreate_item_push,
  149 + .iop_unlock = xfs_icreate_item_unlock,
  150 + .iop_committed = xfs_icreate_item_committed,
  151 + .iop_committing = xfs_icreate_item_committing,
  152 +};
  153 +
  154 +
  155 +/*
  156 + * Initialize the inode log item for a newly allocated (in-core) inode.
  157 + *
  158 + * Inode extents can only reside within an AG. Hence specify the starting
  159 + * block for the inode chunk by offset within an AG as well as the
  160 + * length of the allocated extent.
  161 + *
  162 + * This joins the item to the transaction and marks it dirty so
  163 + * that we don't need a separate call to do this, nor does the
  164 + * caller need to know anything about the icreate item.
  165 + */
  166 +void
  167 +xfs_icreate_log(
  168 + struct xfs_trans *tp,
  169 + xfs_agnumber_t agno,
  170 + xfs_agblock_t agbno,
  171 + unsigned int count,
  172 + unsigned int inode_size,
  173 + xfs_agblock_t length,
  174 + unsigned int generation)
  175 +{
  176 + struct xfs_icreate_item *icp;
  177 +
  178 + icp = kmem_zone_zalloc(xfs_icreate_zone, KM_SLEEP);
  179 +
  180 + xfs_log_item_init(tp->t_mountp, &icp->ic_item, XFS_LI_ICREATE,
  181 + &xfs_icreate_item_ops);
  182 +
  183 + icp->ic_format.icl_type = XFS_LI_ICREATE;
  184 + icp->ic_format.icl_size = 1; /* single vector */
  185 + icp->ic_format.icl_ag = cpu_to_be32(agno);
  186 + icp->ic_format.icl_agbno = cpu_to_be32(agbno);
  187 + icp->ic_format.icl_count = cpu_to_be32(count);
  188 + icp->ic_format.icl_isize = cpu_to_be32(inode_size);
  189 + icp->ic_format.icl_length = cpu_to_be32(length);
  190 + icp->ic_format.icl_gen = cpu_to_be32(generation);
  191 +
  192 + xfs_trans_add_item(tp, &icp->ic_item);
  193 + tp->t_flags |= XFS_TRANS_DIRTY;
  194 + icp->ic_item.li_desc->lid_flags |= XFS_LID_DIRTY;
  195 +}
fs/xfs/xfs_icreate_item.h
  1 +/*
  2 + * Copyright (c) 2008-2010, Dave Chinner
  3 + * All Rights Reserved.
  4 + *
  5 + * This program is free software; you can redistribute it and/or
  6 + * modify it under the terms of the GNU General Public License as
  7 + * published by the Free Software Foundation.
  8 + *
  9 + * This program is distributed in the hope that it would be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program; if not, write the Free Software Foundation,
  16 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17 + */
  18 +#ifndef XFS_ICREATE_ITEM_H
  19 +#define XFS_ICREATE_ITEM_H 1
  20 +
  21 +/*
  22 + * on disk log item structure
  23 + *
  24 + * Log recovery assumes the first two entries are the type and size and they fit
  25 + * in 32 bits. Also in host order (ugh) so they have to be 32 bit aligned so
  26 + * decoding can be done correctly.
  27 + */
  28 +struct xfs_icreate_log {
  29 + __uint16_t icl_type; /* type of log format structure */
  30 + __uint16_t icl_size; /* size of log format structure */
  31 + __be32 icl_ag; /* ag being allocated in */
  32 + __be32 icl_agbno; /* start block of inode range */
  33 + __be32 icl_count; /* number of inodes to initialise */
  34 + __be32 icl_isize; /* size of inodes */
  35 + __be32 icl_length; /* length of extent to initialise */
  36 + __be32 icl_gen; /* inode generation number to use */
  37 +};
  38 +
  39 +/* in memory log item structure */
  40 +struct xfs_icreate_item {
  41 + struct xfs_log_item ic_item;
  42 + struct xfs_icreate_log ic_format;
  43 +};
  44 +
  45 +extern kmem_zone_t *xfs_icreate_zone; /* inode create item zone */
  46 +
  47 +void xfs_icreate_log(struct xfs_trans *tp, xfs_agnumber_t agno,
  48 + xfs_agblock_t agbno, unsigned int count,
  49 + unsigned int inode_size, xfs_agblock_t length,
  50 + unsigned int generation);
  51 +
  52 +#endif /* XFS_ICREATE_ITEM_H */
... ... @@ -88,7 +88,8 @@
88 88 #define XLOG_REG_TYPE_UNMOUNT 17
89 89 #define XLOG_REG_TYPE_COMMIT 18
90 90 #define XLOG_REG_TYPE_TRANSHDR 19
91   -#define XLOG_REG_TYPE_MAX 19
  91 +#define XLOG_REG_TYPE_ICREATE 20
  92 +#define XLOG_REG_TYPE_MAX 20
92 93  
93 94 typedef struct xfs_log_iovec {
94 95 void *i_addr; /* beginning address of region */
... ... @@ -51,6 +51,7 @@
51 51 #include "xfs_inode_item.h"
52 52 #include "xfs_icache.h"
53 53 #include "xfs_trace.h"
  54 +#include "xfs_icreate_item.h"
54 55  
55 56 #include <linux/namei.h>
56 57 #include <linux/init.h>
57 58  
... ... @@ -1650,9 +1651,15 @@
1650 1651 KM_ZONE_SPREAD, NULL);
1651 1652 if (!xfs_ili_zone)
1652 1653 goto out_destroy_inode_zone;
  1654 + xfs_icreate_zone = kmem_zone_init(sizeof(struct xfs_icreate_item),
  1655 + "xfs_icr");
  1656 + if (!xfs_icreate_zone)
  1657 + goto out_destroy_ili_zone;
1653 1658  
1654 1659 return 0;
1655 1660  
  1661 + out_destroy_ili_zone:
  1662 + kmem_zone_destroy(xfs_ili_zone);
1656 1663 out_destroy_inode_zone:
1657 1664 kmem_zone_destroy(xfs_inode_zone);
1658 1665 out_destroy_efi_zone:
... ... @@ -1691,6 +1698,7 @@
1691 1698 * destroy caches.
1692 1699 */
1693 1700 rcu_barrier();
  1701 + kmem_zone_destroy(xfs_icreate_zone);
1694 1702 kmem_zone_destroy(xfs_ili_zone);
1695 1703 kmem_zone_destroy(xfs_inode_zone);
1696 1704 kmem_zone_destroy(xfs_efi_zone);
... ... @@ -48,6 +48,7 @@
48 48 #define XFS_LI_BUF 0x123c /* v2 bufs, variable sized inode bufs */
49 49 #define XFS_LI_DQUOT 0x123d
50 50 #define XFS_LI_QUOTAOFF 0x123e
  51 +#define XFS_LI_ICREATE 0x123f
51 52  
52 53 #define XFS_LI_TYPE_DESC \
53 54 { XFS_LI_EFI, "XFS_LI_EFI" }, \
... ... @@ -107,7 +108,8 @@
107 108 #define XFS_TRANS_SWAPEXT 40
108 109 #define XFS_TRANS_SB_COUNT 41
109 110 #define XFS_TRANS_CHECKPOINT 42
110   -#define XFS_TRANS_TYPE_MAX 42
  111 +#define XFS_TRANS_ICREATE 43
  112 +#define XFS_TRANS_TYPE_MAX 43
111 113 /* new transaction types need to be reflected in xfs_logprint(8) */
112 114  
113 115 #define XFS_TRANS_TYPES \