0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_trans.h"
0015 #include "xfs_trans_priv.h"
0016 #include "xfs_icreate_item.h"
0017 #include "xfs_log.h"
0018 #include "xfs_log_priv.h"
0019 #include "xfs_log_recover.h"
0020 #include "xfs_ialloc.h"
0021 #include "xfs_trace.h"
0022
0023 struct kmem_cache *xfs_icreate_cache;
0024
0025 static inline struct xfs_icreate_item *ICR_ITEM(struct xfs_log_item *lip)
0026 {
0027 return container_of(lip, struct xfs_icreate_item, ic_item);
0028 }
0029
0030
0031
0032
0033
0034
0035 STATIC void
0036 xfs_icreate_item_size(
0037 struct xfs_log_item *lip,
0038 int *nvecs,
0039 int *nbytes)
0040 {
0041 *nvecs += 1;
0042 *nbytes += sizeof(struct xfs_icreate_log);
0043 }
0044
0045
0046
0047
0048
0049 STATIC void
0050 xfs_icreate_item_format(
0051 struct xfs_log_item *lip,
0052 struct xfs_log_vec *lv)
0053 {
0054 struct xfs_icreate_item *icp = ICR_ITEM(lip);
0055 struct xfs_log_iovec *vecp = NULL;
0056
0057 xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICREATE,
0058 &icp->ic_format,
0059 sizeof(struct xfs_icreate_log));
0060 }
0061
0062 STATIC void
0063 xfs_icreate_item_release(
0064 struct xfs_log_item *lip)
0065 {
0066 kmem_free(ICR_ITEM(lip)->ic_item.li_lv_shadow);
0067 kmem_cache_free(xfs_icreate_cache, ICR_ITEM(lip));
0068 }
0069
0070 static const struct xfs_item_ops xfs_icreate_item_ops = {
0071 .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED,
0072 .iop_size = xfs_icreate_item_size,
0073 .iop_format = xfs_icreate_item_format,
0074 .iop_release = xfs_icreate_item_release,
0075 };
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 void
0090 xfs_icreate_log(
0091 struct xfs_trans *tp,
0092 xfs_agnumber_t agno,
0093 xfs_agblock_t agbno,
0094 unsigned int count,
0095 unsigned int inode_size,
0096 xfs_agblock_t length,
0097 unsigned int generation)
0098 {
0099 struct xfs_icreate_item *icp;
0100
0101 icp = kmem_cache_zalloc(xfs_icreate_cache, GFP_KERNEL | __GFP_NOFAIL);
0102
0103 xfs_log_item_init(tp->t_mountp, &icp->ic_item, XFS_LI_ICREATE,
0104 &xfs_icreate_item_ops);
0105
0106 icp->ic_format.icl_type = XFS_LI_ICREATE;
0107 icp->ic_format.icl_size = 1;
0108 icp->ic_format.icl_ag = cpu_to_be32(agno);
0109 icp->ic_format.icl_agbno = cpu_to_be32(agbno);
0110 icp->ic_format.icl_count = cpu_to_be32(count);
0111 icp->ic_format.icl_isize = cpu_to_be32(inode_size);
0112 icp->ic_format.icl_length = cpu_to_be32(length);
0113 icp->ic_format.icl_gen = cpu_to_be32(generation);
0114
0115 xfs_trans_add_item(tp, &icp->ic_item);
0116 tp->t_flags |= XFS_TRANS_DIRTY;
0117 set_bit(XFS_LI_DIRTY, &icp->ic_item.li_flags);
0118 }
0119
0120 static enum xlog_recover_reorder
0121 xlog_recover_icreate_reorder(
0122 struct xlog_recover_item *item)
0123 {
0124
0125
0126
0127
0128
0129
0130 return XLOG_REORDER_BUFFER_LIST;
0131 }
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 STATIC int
0142 xlog_recover_icreate_commit_pass2(
0143 struct xlog *log,
0144 struct list_head *buffer_list,
0145 struct xlog_recover_item *item,
0146 xfs_lsn_t lsn)
0147 {
0148 struct xfs_mount *mp = log->l_mp;
0149 struct xfs_icreate_log *icl;
0150 struct xfs_ino_geometry *igeo = M_IGEO(mp);
0151 xfs_agnumber_t agno;
0152 xfs_agblock_t agbno;
0153 unsigned int count;
0154 unsigned int isize;
0155 xfs_agblock_t length;
0156 int bb_per_cluster;
0157 int cancel_count;
0158 int nbufs;
0159 int i;
0160
0161 icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr;
0162 if (icl->icl_type != XFS_LI_ICREATE) {
0163 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad type");
0164 return -EINVAL;
0165 }
0166
0167 if (icl->icl_size != 1) {
0168 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad icl size");
0169 return -EINVAL;
0170 }
0171
0172 agno = be32_to_cpu(icl->icl_ag);
0173 if (agno >= mp->m_sb.sb_agcount) {
0174 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad agno");
0175 return -EINVAL;
0176 }
0177 agbno = be32_to_cpu(icl->icl_agbno);
0178 if (!agbno || agbno == NULLAGBLOCK || agbno >= mp->m_sb.sb_agblocks) {
0179 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad agbno");
0180 return -EINVAL;
0181 }
0182 isize = be32_to_cpu(icl->icl_isize);
0183 if (isize != mp->m_sb.sb_inodesize) {
0184 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad isize");
0185 return -EINVAL;
0186 }
0187 count = be32_to_cpu(icl->icl_count);
0188 if (!count) {
0189 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad count");
0190 return -EINVAL;
0191 }
0192 length = be32_to_cpu(icl->icl_length);
0193 if (!length || length >= mp->m_sb.sb_agblocks) {
0194 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad length");
0195 return -EINVAL;
0196 }
0197
0198
0199
0200
0201
0202 if (length != igeo->ialloc_blks &&
0203 length != igeo->ialloc_min_blks) {
0204 xfs_warn(log->l_mp,
0205 "%s: unsupported chunk length", __func__);
0206 return -EINVAL;
0207 }
0208
0209
0210 if ((count >> mp->m_sb.sb_inopblog) != length) {
0211 xfs_warn(log->l_mp,
0212 "%s: inconsistent inode count and chunk length",
0213 __func__);
0214 return -EINVAL;
0215 }
0216
0217
0218
0219
0220
0221
0222
0223 bb_per_cluster = XFS_FSB_TO_BB(mp, igeo->blocks_per_cluster);
0224 nbufs = length / igeo->blocks_per_cluster;
0225 for (i = 0, cancel_count = 0; i < nbufs; i++) {
0226 xfs_daddr_t daddr;
0227
0228 daddr = XFS_AGB_TO_DADDR(mp, agno,
0229 agbno + i * igeo->blocks_per_cluster);
0230 if (xlog_is_buffer_cancelled(log, daddr, bb_per_cluster))
0231 cancel_count++;
0232 }
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 ASSERT(!cancel_count || cancel_count == nbufs);
0245 if (cancel_count) {
0246 if (cancel_count != nbufs)
0247 xfs_warn(mp,
0248 "WARNING: partial inode chunk cancellation, skipped icreate.");
0249 trace_xfs_log_recover_icreate_cancel(log, icl);
0250 return 0;
0251 }
0252
0253 trace_xfs_log_recover_icreate_recover(log, icl);
0254 return xfs_ialloc_inode_init(mp, NULL, buffer_list, count, agno, agbno,
0255 length, be32_to_cpu(icl->icl_gen));
0256 }
0257
0258 const struct xlog_recover_item_ops xlog_icreate_item_ops = {
0259 .item_type = XFS_LI_ICREATE,
0260 .reorder = xlog_recover_icreate_reorder,
0261 .commit_pass2 = xlog_recover_icreate_commit_pass2,
0262 };