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_ag.h"
0017 #include "xfs_iunlink_item.h"
0018 #include "xfs_trace.h"
0019 #include "xfs_error.h"
0020
0021 struct kmem_cache *xfs_iunlink_cache;
0022
0023 static inline struct xfs_iunlink_item *IUL_ITEM(struct xfs_log_item *lip)
0024 {
0025 return container_of(lip, struct xfs_iunlink_item, item);
0026 }
0027
0028 static void
0029 xfs_iunlink_item_release(
0030 struct xfs_log_item *lip)
0031 {
0032 struct xfs_iunlink_item *iup = IUL_ITEM(lip);
0033
0034 xfs_perag_put(iup->pag);
0035 kmem_cache_free(xfs_iunlink_cache, IUL_ITEM(lip));
0036 }
0037
0038
0039 static uint64_t
0040 xfs_iunlink_item_sort(
0041 struct xfs_log_item *lip)
0042 {
0043 return IUL_ITEM(lip)->ip->i_ino;
0044 }
0045
0046
0047
0048
0049
0050 static int
0051 xfs_iunlink_log_dinode(
0052 struct xfs_trans *tp,
0053 struct xfs_iunlink_item *iup)
0054 {
0055 struct xfs_mount *mp = tp->t_mountp;
0056 struct xfs_inode *ip = iup->ip;
0057 struct xfs_dinode *dip;
0058 struct xfs_buf *ibp;
0059 int offset;
0060 int error;
0061
0062 error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &ibp);
0063 if (error)
0064 return error;
0065
0066
0067
0068
0069
0070 if (ibp->b_flags & XBF_STALE)
0071 goto out;
0072
0073 dip = xfs_buf_offset(ibp, ip->i_imap.im_boffset);
0074
0075
0076 if (be32_to_cpu(dip->di_next_unlinked) != iup->old_agino) {
0077 xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
0078 sizeof(*dip), __this_address);
0079 error = -EFSCORRUPTED;
0080 goto out;
0081 }
0082
0083 trace_xfs_iunlink_update_dinode(mp, iup->pag->pag_agno,
0084 XFS_INO_TO_AGINO(mp, ip->i_ino),
0085 be32_to_cpu(dip->di_next_unlinked), iup->next_agino);
0086
0087 dip->di_next_unlinked = cpu_to_be32(iup->next_agino);
0088 offset = ip->i_imap.im_boffset +
0089 offsetof(struct xfs_dinode, di_next_unlinked);
0090
0091 xfs_dinode_calc_crc(mp, dip);
0092 xfs_trans_inode_buf(tp, ibp);
0093 xfs_trans_log_buf(tp, ibp, offset, offset + sizeof(xfs_agino_t) - 1);
0094 return 0;
0095 out:
0096 xfs_trans_brelse(tp, ibp);
0097 return error;
0098 }
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108 static int
0109 xfs_iunlink_item_precommit(
0110 struct xfs_trans *tp,
0111 struct xfs_log_item *lip)
0112 {
0113 struct xfs_iunlink_item *iup = IUL_ITEM(lip);
0114 int error;
0115
0116 error = xfs_iunlink_log_dinode(tp, iup);
0117 list_del(&lip->li_trans);
0118 xfs_iunlink_item_release(lip);
0119 return error;
0120 }
0121
0122 static const struct xfs_item_ops xfs_iunlink_item_ops = {
0123 .iop_release = xfs_iunlink_item_release,
0124 .iop_sort = xfs_iunlink_item_sort,
0125 .iop_precommit = xfs_iunlink_item_precommit,
0126 };
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 int
0141 xfs_iunlink_log_inode(
0142 struct xfs_trans *tp,
0143 struct xfs_inode *ip,
0144 struct xfs_perag *pag,
0145 xfs_agino_t next_agino)
0146 {
0147 struct xfs_mount *mp = tp->t_mountp;
0148 struct xfs_iunlink_item *iup;
0149
0150 ASSERT(xfs_verify_agino_or_null(pag, next_agino));
0151 ASSERT(xfs_verify_agino_or_null(pag, ip->i_next_unlinked));
0152
0153
0154
0155
0156
0157
0158 if (ip->i_next_unlinked == next_agino) {
0159 if (next_agino != NULLAGINO)
0160 return -EFSCORRUPTED;
0161 return 0;
0162 }
0163
0164 iup = kmem_cache_zalloc(xfs_iunlink_cache, GFP_KERNEL | __GFP_NOFAIL);
0165 xfs_log_item_init(mp, &iup->item, XFS_LI_IUNLINK,
0166 &xfs_iunlink_item_ops);
0167
0168 iup->ip = ip;
0169 iup->next_agino = next_agino;
0170 iup->old_agino = ip->i_next_unlinked;
0171
0172 atomic_inc(&pag->pag_ref);
0173 iup->pag = pag;
0174
0175 xfs_trans_add_item(tp, &iup->item);
0176 tp->t_flags |= XFS_TRANS_DIRTY;
0177 set_bit(XFS_LI_DIRTY, &iup->item.li_flags);
0178 return 0;
0179 }
0180