Commit ae673f53 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: record inode generation in xattr update log intent items



For parent pointer updates, record the i_generation of the file that is
being updated so that we don't accidentally jump generations.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 5773f7f8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1049,7 +1049,7 @@ struct xfs_icreate_log {
struct xfs_attri_log_format {
	uint16_t	alfi_type;	/* attri log item type */
	uint16_t	alfi_size;	/* size of this item */
	uint32_t	__pad;		/* pad to 64 bit aligned */
	uint32_t	alfi_igen;	/* generation of alfi_ino for pptr ops */
	uint64_t	alfi_id;	/* attri identifier */
	uint64_t	alfi_ino;	/* the inode for this attr operation */
	uint32_t	alfi_op_flags;	/* marks the op as a set or remove */
+27 −6
Original line number Diff line number Diff line
@@ -388,9 +388,14 @@ xfs_attr_log_item(
	case XFS_ATTRI_OP_FLAGS_PPTR_REPLACE:
		ASSERT(nv->value.i_len == nv->new_value.i_len);

		attrp->alfi_igen = VFS_I(args->dp)->i_generation;
		attrp->alfi_old_name_len = nv->name.i_len;
		attrp->alfi_new_name_len = nv->new_name.i_len;
		break;
	case XFS_ATTRI_OP_FLAGS_PPTR_REMOVE:
	case XFS_ATTRI_OP_FLAGS_PPTR_SET:
		attrp->alfi_igen = VFS_I(args->dp)->i_generation;
		fallthrough;
	default:
		attrp->alfi_name_len = nv->name.i_len;
		break;
@@ -545,9 +550,6 @@ xfs_attri_validate(
{
	unsigned int			op = xfs_attr_log_item_op(attrp);

	if (attrp->__pad != 0)
		return false;

	if (attrp->alfi_op_flags & ~XFS_ATTRI_OP_FLAGS_TYPE_MASK)
		return false;

@@ -639,9 +641,27 @@ xfs_attri_recover_work(
	int				local;
	int				error;

	/*
	 * Parent pointer attr items record the generation but regular logged
	 * xattrs do not; select the right iget function.
	 */
	switch (xfs_attr_log_item_op(attrp)) {
	case XFS_ATTRI_OP_FLAGS_PPTR_SET:
	case XFS_ATTRI_OP_FLAGS_PPTR_REPLACE:
	case XFS_ATTRI_OP_FLAGS_PPTR_REMOVE:
		error = xlog_recover_iget_handle(mp, attrp->alfi_ino,
				attrp->alfi_igen, &ip);
		break;
	default:
		error = xlog_recover_iget(mp, attrp->alfi_ino, &ip);
	if (error)
		return ERR_PTR(error);
		break;
	}
	if (error) {
		xfs_irele(ip);
		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, attrp,
				sizeof(*attrp));
		return ERR_PTR(-EFSCORRUPTED);
	}

	if (xfs_inode_has_attr_fork(ip)) {
		error = xfs_attri_iread_extents(ip);
@@ -793,6 +813,7 @@ xfs_attr_relog_intent(
	new_attrp = &new_attrip->attri_format;

	new_attrp->alfi_ino = old_attrp->alfi_ino;
	new_attrp->alfi_igen = old_attrp->alfi_igen;
	new_attrp->alfi_op_flags = old_attrp->alfi_op_flags;
	new_attrp->alfi_value_len = old_attrp->alfi_value_len;