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

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
...@@ -1049,7 +1049,7 @@ struct xfs_icreate_log { ...@@ -1049,7 +1049,7 @@ struct xfs_icreate_log {
struct xfs_attri_log_format { struct xfs_attri_log_format {
uint16_t alfi_type; /* attri log item type */ uint16_t alfi_type; /* attri log item type */
uint16_t alfi_size; /* size of this item */ 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_id; /* attri identifier */
uint64_t alfi_ino; /* the inode for this attr operation */ uint64_t alfi_ino; /* the inode for this attr operation */
uint32_t alfi_op_flags; /* marks the op as a set or remove */ uint32_t alfi_op_flags; /* marks the op as a set or remove */
......
...@@ -388,9 +388,14 @@ xfs_attr_log_item( ...@@ -388,9 +388,14 @@ xfs_attr_log_item(
case XFS_ATTRI_OP_FLAGS_PPTR_REPLACE: case XFS_ATTRI_OP_FLAGS_PPTR_REPLACE:
ASSERT(nv->value.i_len == nv->new_value.i_len); 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_old_name_len = nv->name.i_len;
attrp->alfi_new_name_len = nv->new_name.i_len; attrp->alfi_new_name_len = nv->new_name.i_len;
break; 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: default:
attrp->alfi_name_len = nv->name.i_len; attrp->alfi_name_len = nv->name.i_len;
break; break;
...@@ -545,9 +550,6 @@ xfs_attri_validate( ...@@ -545,9 +550,6 @@ xfs_attri_validate(
{ {
unsigned int op = xfs_attr_log_item_op(attrp); 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) if (attrp->alfi_op_flags & ~XFS_ATTRI_OP_FLAGS_TYPE_MASK)
return false; return false;
...@@ -639,9 +641,27 @@ xfs_attri_recover_work( ...@@ -639,9 +641,27 @@ xfs_attri_recover_work(
int local; int local;
int error; int error;
error = xlog_recover_iget(mp, attrp->alfi_ino, &ip); /*
if (error) * Parent pointer attr items record the generation but regular logged
return ERR_PTR(error); * 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);
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)) { if (xfs_inode_has_attr_fork(ip)) {
error = xfs_attri_iread_extents(ip); error = xfs_attri_iread_extents(ip);
...@@ -793,6 +813,7 @@ xfs_attr_relog_intent( ...@@ -793,6 +813,7 @@ xfs_attr_relog_intent(
new_attrp = &new_attrip->attri_format; new_attrp = &new_attrip->attri_format;
new_attrp->alfi_ino = old_attrp->alfi_ino; 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_op_flags = old_attrp->alfi_op_flags;
new_attrp->alfi_value_len = old_attrp->alfi_value_len; new_attrp->alfi_value_len = old_attrp->alfi_value_len;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment