cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xfs_attr_item.c (24097B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2022 Oracle.  All Rights Reserved.
      4 * Author: Allison Henderson <allison.henderson@oracle.com>
      5 */
      6
      7#include "xfs.h"
      8#include "xfs_fs.h"
      9#include "xfs_format.h"
     10#include "xfs_trans_resv.h"
     11#include "xfs_shared.h"
     12#include "xfs_mount.h"
     13#include "xfs_defer.h"
     14#include "xfs_log_format.h"
     15#include "xfs_trans.h"
     16#include "xfs_bmap_btree.h"
     17#include "xfs_trans_priv.h"
     18#include "xfs_log.h"
     19#include "xfs_inode.h"
     20#include "xfs_da_format.h"
     21#include "xfs_da_btree.h"
     22#include "xfs_attr.h"
     23#include "xfs_attr_item.h"
     24#include "xfs_trace.h"
     25#include "xfs_trans_space.h"
     26#include "xfs_errortag.h"
     27#include "xfs_error.h"
     28#include "xfs_log_priv.h"
     29#include "xfs_log_recover.h"
     30
     31struct kmem_cache		*xfs_attri_cache;
     32struct kmem_cache		*xfs_attrd_cache;
     33
     34static const struct xfs_item_ops xfs_attri_item_ops;
     35static const struct xfs_item_ops xfs_attrd_item_ops;
     36static struct xfs_attrd_log_item *xfs_trans_get_attrd(struct xfs_trans *tp,
     37					struct xfs_attri_log_item *attrip);
     38
     39static inline struct xfs_attri_log_item *ATTRI_ITEM(struct xfs_log_item *lip)
     40{
     41	return container_of(lip, struct xfs_attri_log_item, attri_item);
     42}
     43
     44/*
     45 * Shared xattr name/value buffers for logged extended attribute operations
     46 *
     47 * When logging updates to extended attributes, we can create quite a few
     48 * attribute log intent items for a single xattr update.  To avoid cycling the
     49 * memory allocator and memcpy overhead, the name (and value, for setxattr)
     50 * are kept in a refcounted object that is shared across all related log items
     51 * and the upper-level deferred work state structure.  The shared buffer has
     52 * a control structure, followed by the name, and then the value.
     53 */
     54
     55static inline struct xfs_attri_log_nameval *
     56xfs_attri_log_nameval_get(
     57	struct xfs_attri_log_nameval	*nv)
     58{
     59	if (!refcount_inc_not_zero(&nv->refcount))
     60		return NULL;
     61	return nv;
     62}
     63
     64static inline void
     65xfs_attri_log_nameval_put(
     66	struct xfs_attri_log_nameval	*nv)
     67{
     68	if (!nv)
     69		return;
     70	if (refcount_dec_and_test(&nv->refcount))
     71		kvfree(nv);
     72}
     73
     74static inline struct xfs_attri_log_nameval *
     75xfs_attri_log_nameval_alloc(
     76	const void			*name,
     77	unsigned int			name_len,
     78	const void			*value,
     79	unsigned int			value_len)
     80{
     81	struct xfs_attri_log_nameval	*nv;
     82
     83	/*
     84	 * This could be over 64kB in length, so we have to use kvmalloc() for
     85	 * this. But kvmalloc() utterly sucks, so we use our own version.
     86	 */
     87	nv = xlog_kvmalloc(sizeof(struct xfs_attri_log_nameval) +
     88					name_len + value_len);
     89	if (!nv)
     90		return nv;
     91
     92	nv->name.i_addr = nv + 1;
     93	nv->name.i_len = name_len;
     94	nv->name.i_type = XLOG_REG_TYPE_ATTR_NAME;
     95	memcpy(nv->name.i_addr, name, name_len);
     96
     97	if (value_len) {
     98		nv->value.i_addr = nv->name.i_addr + name_len;
     99		nv->value.i_len = value_len;
    100		memcpy(nv->value.i_addr, value, value_len);
    101	} else {
    102		nv->value.i_addr = NULL;
    103		nv->value.i_len = 0;
    104	}
    105	nv->value.i_type = XLOG_REG_TYPE_ATTR_VALUE;
    106
    107	refcount_set(&nv->refcount, 1);
    108	return nv;
    109}
    110
    111STATIC void
    112xfs_attri_item_free(
    113	struct xfs_attri_log_item	*attrip)
    114{
    115	kmem_free(attrip->attri_item.li_lv_shadow);
    116	xfs_attri_log_nameval_put(attrip->attri_nameval);
    117	kmem_cache_free(xfs_attri_cache, attrip);
    118}
    119
    120/*
    121 * Freeing the attrip requires that we remove it from the AIL if it has already
    122 * been placed there. However, the ATTRI may not yet have been placed in the
    123 * AIL when called by xfs_attri_release() from ATTRD processing due to the
    124 * ordering of committed vs unpin operations in bulk insert operations. Hence
    125 * the reference count to ensure only the last caller frees the ATTRI.
    126 */
    127STATIC void
    128xfs_attri_release(
    129	struct xfs_attri_log_item	*attrip)
    130{
    131	ASSERT(atomic_read(&attrip->attri_refcount) > 0);
    132	if (!atomic_dec_and_test(&attrip->attri_refcount))
    133		return;
    134
    135	xfs_trans_ail_delete(&attrip->attri_item, 0);
    136	xfs_attri_item_free(attrip);
    137}
    138
    139STATIC void
    140xfs_attri_item_size(
    141	struct xfs_log_item		*lip,
    142	int				*nvecs,
    143	int				*nbytes)
    144{
    145	struct xfs_attri_log_item       *attrip = ATTRI_ITEM(lip);
    146	struct xfs_attri_log_nameval	*nv = attrip->attri_nameval;
    147
    148	*nvecs += 2;
    149	*nbytes += sizeof(struct xfs_attri_log_format) +
    150			xlog_calc_iovec_len(nv->name.i_len);
    151
    152	if (!nv->value.i_len)
    153		return;
    154
    155	*nvecs += 1;
    156	*nbytes += xlog_calc_iovec_len(nv->value.i_len);
    157}
    158
    159/*
    160 * This is called to fill in the log iovecs for the given attri log
    161 * item. We use  1 iovec for the attri_format_item, 1 for the name, and
    162 * another for the value if it is present
    163 */
    164STATIC void
    165xfs_attri_item_format(
    166	struct xfs_log_item		*lip,
    167	struct xfs_log_vec		*lv)
    168{
    169	struct xfs_attri_log_item	*attrip = ATTRI_ITEM(lip);
    170	struct xfs_log_iovec		*vecp = NULL;
    171	struct xfs_attri_log_nameval	*nv = attrip->attri_nameval;
    172
    173	attrip->attri_format.alfi_type = XFS_LI_ATTRI;
    174	attrip->attri_format.alfi_size = 1;
    175
    176	/*
    177	 * This size accounting must be done before copying the attrip into the
    178	 * iovec.  If we do it after, the wrong size will be recorded to the log
    179	 * and we trip across assertion checks for bad region sizes later during
    180	 * the log recovery.
    181	 */
    182
    183	ASSERT(nv->name.i_len > 0);
    184	attrip->attri_format.alfi_size++;
    185
    186	if (nv->value.i_len > 0)
    187		attrip->attri_format.alfi_size++;
    188
    189	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTRI_FORMAT,
    190			&attrip->attri_format,
    191			sizeof(struct xfs_attri_log_format));
    192	xlog_copy_from_iovec(lv, &vecp, &nv->name);
    193	if (nv->value.i_len > 0)
    194		xlog_copy_from_iovec(lv, &vecp, &nv->value);
    195}
    196
    197/*
    198 * The unpin operation is the last place an ATTRI is manipulated in the log. It
    199 * is either inserted in the AIL or aborted in the event of a log I/O error. In
    200 * either case, the ATTRI transaction has been successfully committed to make
    201 * it this far. Therefore, we expect whoever committed the ATTRI to either
    202 * construct and commit the ATTRD or drop the ATTRD's reference in the event of
    203 * error. Simply drop the log's ATTRI reference now that the log is done with
    204 * it.
    205 */
    206STATIC void
    207xfs_attri_item_unpin(
    208	struct xfs_log_item	*lip,
    209	int			remove)
    210{
    211	xfs_attri_release(ATTRI_ITEM(lip));
    212}
    213
    214
    215STATIC void
    216xfs_attri_item_release(
    217	struct xfs_log_item	*lip)
    218{
    219	xfs_attri_release(ATTRI_ITEM(lip));
    220}
    221
    222/*
    223 * Allocate and initialize an attri item.  Caller may allocate an additional
    224 * trailing buffer for name and value
    225 */
    226STATIC struct xfs_attri_log_item *
    227xfs_attri_init(
    228	struct xfs_mount		*mp,
    229	struct xfs_attri_log_nameval	*nv)
    230{
    231	struct xfs_attri_log_item	*attrip;
    232
    233	attrip = kmem_cache_zalloc(xfs_attri_cache, GFP_NOFS | __GFP_NOFAIL);
    234
    235	/*
    236	 * Grab an extra reference to the name/value buffer for this log item.
    237	 * The caller retains its own reference!
    238	 */
    239	attrip->attri_nameval = xfs_attri_log_nameval_get(nv);
    240	ASSERT(attrip->attri_nameval);
    241
    242	xfs_log_item_init(mp, &attrip->attri_item, XFS_LI_ATTRI,
    243			  &xfs_attri_item_ops);
    244	attrip->attri_format.alfi_id = (uintptr_t)(void *)attrip;
    245	atomic_set(&attrip->attri_refcount, 2);
    246
    247	return attrip;
    248}
    249
    250/*
    251 * Copy an attr format buffer from the given buf, and into the destination attr
    252 * format structure.
    253 */
    254STATIC int
    255xfs_attri_copy_format(
    256	struct xfs_log_iovec		*buf,
    257	struct xfs_attri_log_format	*dst_attr_fmt)
    258{
    259	struct xfs_attri_log_format	*src_attr_fmt = buf->i_addr;
    260	size_t				len;
    261
    262	len = sizeof(struct xfs_attri_log_format);
    263	if (buf->i_len != len) {
    264		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
    265		return -EFSCORRUPTED;
    266	}
    267
    268	memcpy((char *)dst_attr_fmt, (char *)src_attr_fmt, len);
    269	return 0;
    270}
    271
    272static inline struct xfs_attrd_log_item *ATTRD_ITEM(struct xfs_log_item *lip)
    273{
    274	return container_of(lip, struct xfs_attrd_log_item, attrd_item);
    275}
    276
    277STATIC void
    278xfs_attrd_item_free(struct xfs_attrd_log_item *attrdp)
    279{
    280	kmem_free(attrdp->attrd_item.li_lv_shadow);
    281	kmem_cache_free(xfs_attrd_cache, attrdp);
    282}
    283
    284STATIC void
    285xfs_attrd_item_size(
    286	struct xfs_log_item		*lip,
    287	int				*nvecs,
    288	int				*nbytes)
    289{
    290	*nvecs += 1;
    291	*nbytes += sizeof(struct xfs_attrd_log_format);
    292}
    293
    294/*
    295 * This is called to fill in the log iovecs for the given attrd log item. We use
    296 * only 1 iovec for the attrd_format, and we point that at the attr_log_format
    297 * structure embedded in the attrd item.
    298 */
    299STATIC void
    300xfs_attrd_item_format(
    301	struct xfs_log_item	*lip,
    302	struct xfs_log_vec	*lv)
    303{
    304	struct xfs_attrd_log_item	*attrdp = ATTRD_ITEM(lip);
    305	struct xfs_log_iovec		*vecp = NULL;
    306
    307	attrdp->attrd_format.alfd_type = XFS_LI_ATTRD;
    308	attrdp->attrd_format.alfd_size = 1;
    309
    310	xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTRD_FORMAT,
    311			&attrdp->attrd_format,
    312			sizeof(struct xfs_attrd_log_format));
    313}
    314
    315/*
    316 * The ATTRD is either committed or aborted if the transaction is canceled. If
    317 * the transaction is canceled, drop our reference to the ATTRI and free the
    318 * ATTRD.
    319 */
    320STATIC void
    321xfs_attrd_item_release(
    322	struct xfs_log_item		*lip)
    323{
    324	struct xfs_attrd_log_item	*attrdp = ATTRD_ITEM(lip);
    325
    326	xfs_attri_release(attrdp->attrd_attrip);
    327	xfs_attrd_item_free(attrdp);
    328}
    329
    330static struct xfs_log_item *
    331xfs_attrd_item_intent(
    332	struct xfs_log_item	*lip)
    333{
    334	return &ATTRD_ITEM(lip)->attrd_attrip->attri_item;
    335}
    336
    337/*
    338 * Performs one step of an attribute update intent and marks the attrd item
    339 * dirty..  An attr operation may be a set or a remove.  Note that the
    340 * transaction is marked dirty regardless of whether the operation succeeds or
    341 * fails to support the ATTRI/ATTRD lifecycle rules.
    342 */
    343STATIC int
    344xfs_xattri_finish_update(
    345	struct xfs_attr_intent		*attr,
    346	struct xfs_attrd_log_item	*attrdp)
    347{
    348	struct xfs_da_args		*args = attr->xattri_da_args;
    349	int				error;
    350
    351	if (XFS_TEST_ERROR(false, args->dp->i_mount, XFS_ERRTAG_LARP)) {
    352		error = -EIO;
    353		goto out;
    354	}
    355
    356	error = xfs_attr_set_iter(attr);
    357	if (!error && attr->xattri_dela_state != XFS_DAS_DONE)
    358		error = -EAGAIN;
    359out:
    360	/*
    361	 * Mark the transaction dirty, even on error. This ensures the
    362	 * transaction is aborted, which:
    363	 *
    364	 * 1.) releases the ATTRI and frees the ATTRD
    365	 * 2.) shuts down the filesystem
    366	 */
    367	args->trans->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
    368
    369	/*
    370	 * attr intent/done items are null when logged attributes are disabled
    371	 */
    372	if (attrdp)
    373		set_bit(XFS_LI_DIRTY, &attrdp->attrd_item.li_flags);
    374
    375	return error;
    376}
    377
    378/* Log an attr to the intent item. */
    379STATIC void
    380xfs_attr_log_item(
    381	struct xfs_trans		*tp,
    382	struct xfs_attri_log_item	*attrip,
    383	const struct xfs_attr_intent	*attr)
    384{
    385	struct xfs_attri_log_format	*attrp;
    386
    387	tp->t_flags |= XFS_TRANS_DIRTY;
    388	set_bit(XFS_LI_DIRTY, &attrip->attri_item.li_flags);
    389
    390	/*
    391	 * At this point the xfs_attr_intent has been constructed, and we've
    392	 * created the log intent. Fill in the attri log item and log format
    393	 * structure with fields from this xfs_attr_intent
    394	 */
    395	attrp = &attrip->attri_format;
    396	attrp->alfi_ino = attr->xattri_da_args->dp->i_ino;
    397	ASSERT(!(attr->xattri_op_flags & ~XFS_ATTRI_OP_FLAGS_TYPE_MASK));
    398	attrp->alfi_op_flags = attr->xattri_op_flags;
    399	attrp->alfi_value_len = attr->xattri_nameval->value.i_len;
    400	attrp->alfi_name_len = attr->xattri_nameval->name.i_len;
    401	ASSERT(!(attr->xattri_da_args->attr_filter & ~XFS_ATTRI_FILTER_MASK));
    402	attrp->alfi_attr_filter = attr->xattri_da_args->attr_filter;
    403}
    404
    405/* Get an ATTRI. */
    406static struct xfs_log_item *
    407xfs_attr_create_intent(
    408	struct xfs_trans		*tp,
    409	struct list_head		*items,
    410	unsigned int			count,
    411	bool				sort)
    412{
    413	struct xfs_mount		*mp = tp->t_mountp;
    414	struct xfs_attri_log_item	*attrip;
    415	struct xfs_attr_intent		*attr;
    416	struct xfs_da_args		*args;
    417
    418	ASSERT(count == 1);
    419
    420	/*
    421	 * Each attr item only performs one attribute operation at a time, so
    422	 * this is a list of one
    423	 */
    424	attr = list_first_entry_or_null(items, struct xfs_attr_intent,
    425			xattri_list);
    426	args = attr->xattri_da_args;
    427
    428	if (!(args->op_flags & XFS_DA_OP_LOGGED))
    429		return NULL;
    430
    431	/*
    432	 * Create a buffer to store the attribute name and value.  This buffer
    433	 * will be shared between the higher level deferred xattr work state
    434	 * and the lower level xattr log items.
    435	 */
    436	if (!attr->xattri_nameval) {
    437		/*
    438		 * Transfer our reference to the name/value buffer to the
    439		 * deferred work state structure.
    440		 */
    441		attr->xattri_nameval = xfs_attri_log_nameval_alloc(args->name,
    442				args->namelen, args->value, args->valuelen);
    443	}
    444	if (!attr->xattri_nameval)
    445		return ERR_PTR(-ENOMEM);
    446
    447	attrip = xfs_attri_init(mp, attr->xattri_nameval);
    448	xfs_trans_add_item(tp, &attrip->attri_item);
    449	xfs_attr_log_item(tp, attrip, attr);
    450
    451	return &attrip->attri_item;
    452}
    453
    454static inline void
    455xfs_attr_free_item(
    456	struct xfs_attr_intent		*attr)
    457{
    458	if (attr->xattri_da_state)
    459		xfs_da_state_free(attr->xattri_da_state);
    460	xfs_attri_log_nameval_put(attr->xattri_nameval);
    461	if (attr->xattri_da_args->op_flags & XFS_DA_OP_RECOVERY)
    462		kmem_free(attr);
    463	else
    464		kmem_cache_free(xfs_attr_intent_cache, attr);
    465}
    466
    467/* Process an attr. */
    468STATIC int
    469xfs_attr_finish_item(
    470	struct xfs_trans		*tp,
    471	struct xfs_log_item		*done,
    472	struct list_head		*item,
    473	struct xfs_btree_cur		**state)
    474{
    475	struct xfs_attr_intent		*attr;
    476	struct xfs_attrd_log_item	*done_item = NULL;
    477	int				error;
    478
    479	attr = container_of(item, struct xfs_attr_intent, xattri_list);
    480	if (done)
    481		done_item = ATTRD_ITEM(done);
    482
    483	/*
    484	 * Always reset trans after EAGAIN cycle
    485	 * since the transaction is new
    486	 */
    487	attr->xattri_da_args->trans = tp;
    488
    489	error = xfs_xattri_finish_update(attr, done_item);
    490	if (error != -EAGAIN)
    491		xfs_attr_free_item(attr);
    492
    493	return error;
    494}
    495
    496/* Abort all pending ATTRs. */
    497STATIC void
    498xfs_attr_abort_intent(
    499	struct xfs_log_item		*intent)
    500{
    501	xfs_attri_release(ATTRI_ITEM(intent));
    502}
    503
    504/* Cancel an attr */
    505STATIC void
    506xfs_attr_cancel_item(
    507	struct list_head		*item)
    508{
    509	struct xfs_attr_intent		*attr;
    510
    511	attr = container_of(item, struct xfs_attr_intent, xattri_list);
    512	xfs_attr_free_item(attr);
    513}
    514
    515STATIC bool
    516xfs_attri_item_match(
    517	struct xfs_log_item	*lip,
    518	uint64_t		intent_id)
    519{
    520	return ATTRI_ITEM(lip)->attri_format.alfi_id == intent_id;
    521}
    522
    523/* Is this recovered ATTRI format ok? */
    524static inline bool
    525xfs_attri_validate(
    526	struct xfs_mount		*mp,
    527	struct xfs_attri_log_format	*attrp)
    528{
    529	unsigned int			op = attrp->alfi_op_flags &
    530					     XFS_ATTRI_OP_FLAGS_TYPE_MASK;
    531
    532	if (attrp->__pad != 0)
    533		return false;
    534
    535	if (attrp->alfi_op_flags & ~XFS_ATTRI_OP_FLAGS_TYPE_MASK)
    536		return false;
    537
    538	if (attrp->alfi_attr_filter & ~XFS_ATTRI_FILTER_MASK)
    539		return false;
    540
    541	/* alfi_op_flags should be either a set or remove */
    542	switch (op) {
    543	case XFS_ATTRI_OP_FLAGS_SET:
    544	case XFS_ATTRI_OP_FLAGS_REPLACE:
    545	case XFS_ATTRI_OP_FLAGS_REMOVE:
    546		break;
    547	default:
    548		return false;
    549	}
    550
    551	if (attrp->alfi_value_len > XATTR_SIZE_MAX)
    552		return false;
    553
    554	if ((attrp->alfi_name_len > XATTR_NAME_MAX) ||
    555	    (attrp->alfi_name_len == 0))
    556		return false;
    557
    558	return xfs_verify_ino(mp, attrp->alfi_ino);
    559}
    560
    561/*
    562 * Process an attr intent item that was recovered from the log.  We need to
    563 * delete the attr that it describes.
    564 */
    565STATIC int
    566xfs_attri_item_recover(
    567	struct xfs_log_item		*lip,
    568	struct list_head		*capture_list)
    569{
    570	struct xfs_attri_log_item	*attrip = ATTRI_ITEM(lip);
    571	struct xfs_attr_intent		*attr;
    572	struct xfs_mount		*mp = lip->li_log->l_mp;
    573	struct xfs_inode		*ip;
    574	struct xfs_da_args		*args;
    575	struct xfs_trans		*tp;
    576	struct xfs_trans_res		tres;
    577	struct xfs_attri_log_format	*attrp;
    578	struct xfs_attri_log_nameval	*nv = attrip->attri_nameval;
    579	int				error;
    580	int				total;
    581	int				local;
    582	struct xfs_attrd_log_item	*done_item = NULL;
    583
    584	/*
    585	 * First check the validity of the attr described by the ATTRI.  If any
    586	 * are bad, then assume that all are bad and just toss the ATTRI.
    587	 */
    588	attrp = &attrip->attri_format;
    589	if (!xfs_attri_validate(mp, attrp) ||
    590	    !xfs_attr_namecheck(nv->name.i_addr, nv->name.i_len))
    591		return -EFSCORRUPTED;
    592
    593	error = xlog_recover_iget(mp,  attrp->alfi_ino, &ip);
    594	if (error)
    595		return error;
    596
    597	attr = kmem_zalloc(sizeof(struct xfs_attr_intent) +
    598			   sizeof(struct xfs_da_args), KM_NOFS);
    599	args = (struct xfs_da_args *)(attr + 1);
    600
    601	attr->xattri_da_args = args;
    602	attr->xattri_op_flags = attrp->alfi_op_flags &
    603						XFS_ATTRI_OP_FLAGS_TYPE_MASK;
    604
    605	/*
    606	 * We're reconstructing the deferred work state structure from the
    607	 * recovered log item.  Grab a reference to the name/value buffer and
    608	 * attach it to the new work state.
    609	 */
    610	attr->xattri_nameval = xfs_attri_log_nameval_get(nv);
    611	ASSERT(attr->xattri_nameval);
    612
    613	args->dp = ip;
    614	args->geo = mp->m_attr_geo;
    615	args->whichfork = XFS_ATTR_FORK;
    616	args->name = nv->name.i_addr;
    617	args->namelen = nv->name.i_len;
    618	args->hashval = xfs_da_hashname(args->name, args->namelen);
    619	args->attr_filter = attrp->alfi_attr_filter & XFS_ATTRI_FILTER_MASK;
    620	args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT |
    621			 XFS_DA_OP_LOGGED;
    622
    623	ASSERT(xfs_sb_version_haslogxattrs(&mp->m_sb));
    624
    625	switch (attr->xattri_op_flags) {
    626	case XFS_ATTRI_OP_FLAGS_SET:
    627	case XFS_ATTRI_OP_FLAGS_REPLACE:
    628		args->value = nv->value.i_addr;
    629		args->valuelen = nv->value.i_len;
    630		args->total = xfs_attr_calc_size(args, &local);
    631		if (xfs_inode_hasattr(args->dp))
    632			attr->xattri_dela_state = xfs_attr_init_replace_state(args);
    633		else
    634			attr->xattri_dela_state = xfs_attr_init_add_state(args);
    635		break;
    636	case XFS_ATTRI_OP_FLAGS_REMOVE:
    637		if (!xfs_inode_hasattr(args->dp))
    638			goto out;
    639		attr->xattri_dela_state = xfs_attr_init_remove_state(args);
    640		break;
    641	default:
    642		ASSERT(0);
    643		error = -EFSCORRUPTED;
    644		goto out;
    645	}
    646
    647	xfs_init_attr_trans(args, &tres, &total);
    648	error = xfs_trans_alloc(mp, &tres, total, 0, XFS_TRANS_RESERVE, &tp);
    649	if (error)
    650		goto out;
    651
    652	args->trans = tp;
    653	done_item = xfs_trans_get_attrd(tp, attrip);
    654
    655	xfs_ilock(ip, XFS_ILOCK_EXCL);
    656	xfs_trans_ijoin(tp, ip, 0);
    657
    658	error = xfs_xattri_finish_update(attr, done_item);
    659	if (error == -EAGAIN) {
    660		/*
    661		 * There's more work to do, so add the intent item to this
    662		 * transaction so that we can continue it later.
    663		 */
    664		xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_ATTR, &attr->xattri_list);
    665		error = xfs_defer_ops_capture_and_commit(tp, capture_list);
    666		if (error)
    667			goto out_unlock;
    668
    669		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    670		xfs_irele(ip);
    671		return 0;
    672	}
    673	if (error) {
    674		xfs_trans_cancel(tp);
    675		goto out_unlock;
    676	}
    677
    678	error = xfs_defer_ops_capture_and_commit(tp, capture_list);
    679out_unlock:
    680	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    681	xfs_irele(ip);
    682out:
    683	xfs_attr_free_item(attr);
    684	return error;
    685}
    686
    687/* Re-log an intent item to push the log tail forward. */
    688static struct xfs_log_item *
    689xfs_attri_item_relog(
    690	struct xfs_log_item		*intent,
    691	struct xfs_trans		*tp)
    692{
    693	struct xfs_attrd_log_item	*attrdp;
    694	struct xfs_attri_log_item	*old_attrip;
    695	struct xfs_attri_log_item	*new_attrip;
    696	struct xfs_attri_log_format	*new_attrp;
    697	struct xfs_attri_log_format	*old_attrp;
    698
    699	old_attrip = ATTRI_ITEM(intent);
    700	old_attrp = &old_attrip->attri_format;
    701
    702	tp->t_flags |= XFS_TRANS_DIRTY;
    703	attrdp = xfs_trans_get_attrd(tp, old_attrip);
    704	set_bit(XFS_LI_DIRTY, &attrdp->attrd_item.li_flags);
    705
    706	/*
    707	 * Create a new log item that shares the same name/value buffer as the
    708	 * old log item.
    709	 */
    710	new_attrip = xfs_attri_init(tp->t_mountp, old_attrip->attri_nameval);
    711	new_attrp = &new_attrip->attri_format;
    712
    713	new_attrp->alfi_ino = old_attrp->alfi_ino;
    714	new_attrp->alfi_op_flags = old_attrp->alfi_op_flags;
    715	new_attrp->alfi_value_len = old_attrp->alfi_value_len;
    716	new_attrp->alfi_name_len = old_attrp->alfi_name_len;
    717	new_attrp->alfi_attr_filter = old_attrp->alfi_attr_filter;
    718
    719	xfs_trans_add_item(tp, &new_attrip->attri_item);
    720	set_bit(XFS_LI_DIRTY, &new_attrip->attri_item.li_flags);
    721
    722	return &new_attrip->attri_item;
    723}
    724
    725STATIC int
    726xlog_recover_attri_commit_pass2(
    727	struct xlog                     *log,
    728	struct list_head		*buffer_list,
    729	struct xlog_recover_item        *item,
    730	xfs_lsn_t                       lsn)
    731{
    732	struct xfs_mount                *mp = log->l_mp;
    733	struct xfs_attri_log_item       *attrip;
    734	struct xfs_attri_log_format     *attri_formatp;
    735	struct xfs_attri_log_nameval	*nv;
    736	const void			*attr_value = NULL;
    737	const void			*attr_name;
    738	int                             error;
    739
    740	attri_formatp = item->ri_buf[0].i_addr;
    741	attr_name = item->ri_buf[1].i_addr;
    742
    743	/* Validate xfs_attri_log_format before the large memory allocation */
    744	if (!xfs_attri_validate(mp, attri_formatp)) {
    745		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
    746		return -EFSCORRUPTED;
    747	}
    748
    749	if (!xfs_attr_namecheck(attr_name, attri_formatp->alfi_name_len)) {
    750		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
    751		return -EFSCORRUPTED;
    752	}
    753
    754	if (attri_formatp->alfi_value_len)
    755		attr_value = item->ri_buf[2].i_addr;
    756
    757	/*
    758	 * Memory alloc failure will cause replay to abort.  We attach the
    759	 * name/value buffer to the recovered incore log item and drop our
    760	 * reference.
    761	 */
    762	nv = xfs_attri_log_nameval_alloc(attr_name,
    763			attri_formatp->alfi_name_len, attr_value,
    764			attri_formatp->alfi_value_len);
    765	if (!nv)
    766		return -ENOMEM;
    767
    768	attrip = xfs_attri_init(mp, nv);
    769	error = xfs_attri_copy_format(&item->ri_buf[0], &attrip->attri_format);
    770	if (error)
    771		goto out;
    772
    773	/*
    774	 * The ATTRI has two references. One for the ATTRD and one for ATTRI to
    775	 * ensure it makes it into the AIL. Insert the ATTRI into the AIL
    776	 * directly and drop the ATTRI reference. Note that
    777	 * xfs_trans_ail_update() drops the AIL lock.
    778	 */
    779	xfs_trans_ail_insert(log->l_ailp, &attrip->attri_item, lsn);
    780	xfs_attri_release(attrip);
    781	xfs_attri_log_nameval_put(nv);
    782	return 0;
    783out:
    784	xfs_attri_item_free(attrip);
    785	xfs_attri_log_nameval_put(nv);
    786	return error;
    787}
    788
    789/*
    790 * This routine is called to allocate an "attr free done" log item.
    791 */
    792static struct xfs_attrd_log_item *
    793xfs_trans_get_attrd(struct xfs_trans		*tp,
    794		  struct xfs_attri_log_item	*attrip)
    795{
    796	struct xfs_attrd_log_item		*attrdp;
    797
    798	ASSERT(tp != NULL);
    799
    800	attrdp = kmem_cache_zalloc(xfs_attrd_cache, GFP_NOFS | __GFP_NOFAIL);
    801
    802	xfs_log_item_init(tp->t_mountp, &attrdp->attrd_item, XFS_LI_ATTRD,
    803			  &xfs_attrd_item_ops);
    804	attrdp->attrd_attrip = attrip;
    805	attrdp->attrd_format.alfd_alf_id = attrip->attri_format.alfi_id;
    806
    807	xfs_trans_add_item(tp, &attrdp->attrd_item);
    808	return attrdp;
    809}
    810
    811/* Get an ATTRD so we can process all the attrs. */
    812static struct xfs_log_item *
    813xfs_attr_create_done(
    814	struct xfs_trans		*tp,
    815	struct xfs_log_item		*intent,
    816	unsigned int			count)
    817{
    818	if (!intent)
    819		return NULL;
    820
    821	return &xfs_trans_get_attrd(tp, ATTRI_ITEM(intent))->attrd_item;
    822}
    823
    824const struct xfs_defer_op_type xfs_attr_defer_type = {
    825	.max_items	= 1,
    826	.create_intent	= xfs_attr_create_intent,
    827	.abort_intent	= xfs_attr_abort_intent,
    828	.create_done	= xfs_attr_create_done,
    829	.finish_item	= xfs_attr_finish_item,
    830	.cancel_item	= xfs_attr_cancel_item,
    831};
    832
    833/*
    834 * This routine is called when an ATTRD format structure is found in a committed
    835 * transaction in the log. Its purpose is to cancel the corresponding ATTRI if
    836 * it was still in the log. To do this it searches the AIL for the ATTRI with
    837 * an id equal to that in the ATTRD format structure. If we find it we drop
    838 * the ATTRD reference, which removes the ATTRI from the AIL and frees it.
    839 */
    840STATIC int
    841xlog_recover_attrd_commit_pass2(
    842	struct xlog			*log,
    843	struct list_head		*buffer_list,
    844	struct xlog_recover_item	*item,
    845	xfs_lsn_t			lsn)
    846{
    847	struct xfs_attrd_log_format	*attrd_formatp;
    848
    849	attrd_formatp = item->ri_buf[0].i_addr;
    850	if (item->ri_buf[0].i_len != sizeof(struct xfs_attrd_log_format)) {
    851		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
    852		return -EFSCORRUPTED;
    853	}
    854
    855	xlog_recover_release_intent(log, XFS_LI_ATTRI,
    856				    attrd_formatp->alfd_alf_id);
    857	return 0;
    858}
    859
    860static const struct xfs_item_ops xfs_attri_item_ops = {
    861	.flags		= XFS_ITEM_INTENT,
    862	.iop_size	= xfs_attri_item_size,
    863	.iop_format	= xfs_attri_item_format,
    864	.iop_unpin	= xfs_attri_item_unpin,
    865	.iop_release    = xfs_attri_item_release,
    866	.iop_recover	= xfs_attri_item_recover,
    867	.iop_match	= xfs_attri_item_match,
    868	.iop_relog	= xfs_attri_item_relog,
    869};
    870
    871const struct xlog_recover_item_ops xlog_attri_item_ops = {
    872	.item_type	= XFS_LI_ATTRI,
    873	.commit_pass2	= xlog_recover_attri_commit_pass2,
    874};
    875
    876static const struct xfs_item_ops xfs_attrd_item_ops = {
    877	.flags		= XFS_ITEM_RELEASE_WHEN_COMMITTED |
    878			  XFS_ITEM_INTENT_DONE,
    879	.iop_size	= xfs_attrd_item_size,
    880	.iop_format	= xfs_attrd_item_format,
    881	.iop_release    = xfs_attrd_item_release,
    882	.iop_intent	= xfs_attrd_item_intent,
    883};
    884
    885const struct xlog_recover_item_ops xlog_attrd_item_ops = {
    886	.item_type	= XFS_LI_ATTRD,
    887	.commit_pass2	= xlog_recover_attrd_commit_pass2,
    888};