xfs: add raw parent pointer apis to support repair

Add a couple of utility functions to set or remove parent pointers from
a file.  These functions will be used by repair code, hence they skip
the xattr logging that regular parent pointer updates use.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Darrick J. Wong 2024-04-22 09:48:09 -07:00
parent 086e934fe9
commit 5769aa41ee
4 changed files with 72 additions and 2 deletions

View File

@ -434,7 +434,7 @@ int
xfs_dir_removename(
struct xfs_trans *tp,
struct xfs_inode *dp,
struct xfs_name *name,
const struct xfs_name *name,
xfs_ino_t ino,
xfs_extlen_t total) /* bmap's total block count */
{

View File

@ -58,7 +58,7 @@ extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
const struct xfs_name *name, xfs_ino_t *inum,
struct xfs_name *ci_name);
extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t ino,
const struct xfs_name *name, xfs_ino_t ino,
xfs_extlen_t tot);
extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
const struct xfs_name *name, xfs_ino_t inum,

View File

@ -313,3 +313,67 @@ xfs_parent_lookup(
xfs_parent_da_args_init(scratch, tp, pptr, ip, ip->i_ino, parent_name);
return xfs_attr_get_ilocked(scratch);
}
/* Sanity-check a parent pointer before we try to perform repairs. */
static inline bool
xfs_parent_sanity_check(
struct xfs_mount *mp,
const struct xfs_name *parent_name,
const struct xfs_parent_rec *pptr)
{
if (!xfs_parent_namecheck(XFS_ATTR_PARENT, parent_name->name,
parent_name->len))
return false;
if (!xfs_parent_valuecheck(mp, pptr, sizeof(*pptr)))
return false;
return true;
}
/*
* Attach the parent pointer (@parent_name -> @pptr) to @ip immediately.
* Caller must not have a transaction or hold the ILOCK. This is for
* specialized repair functions only. The scratchpad need not be initialized.
*/
int
xfs_parent_set(
struct xfs_inode *ip,
xfs_ino_t owner,
const struct xfs_name *parent_name,
struct xfs_parent_rec *pptr,
struct xfs_da_args *scratch)
{
if (!xfs_parent_sanity_check(ip->i_mount, parent_name, pptr)) {
ASSERT(0);
return -EFSCORRUPTED;
}
memset(scratch, 0, sizeof(struct xfs_da_args));
xfs_parent_da_args_init(scratch, NULL, pptr, ip, owner, parent_name);
return xfs_attr_set(scratch, XFS_ATTRUPDATE_CREATE, false);
}
/*
* Remove the parent pointer (@parent_name -> @pptr) from @ip immediately.
* Caller must not have a transaction or hold the ILOCK. This is for
* specialized repair functions only. The scratchpad need not be initialized.
*/
int
xfs_parent_unset(
struct xfs_inode *ip,
xfs_ino_t owner,
const struct xfs_name *parent_name,
struct xfs_parent_rec *pptr,
struct xfs_da_args *scratch)
{
if (!xfs_parent_sanity_check(ip->i_mount, parent_name, pptr)) {
ASSERT(0);
return -EFSCORRUPTED;
}
memset(scratch, 0, sizeof(struct xfs_da_args));
xfs_parent_da_args_init(scratch, NULL, pptr, ip, owner, parent_name);
return xfs_attr_set(scratch, XFS_ATTRUPDATE_REMOVE, false);
}

View File

@ -100,5 +100,11 @@ int xfs_parent_from_attr(struct xfs_mount *mp, unsigned int attr_flags,
int xfs_parent_lookup(struct xfs_trans *tp, struct xfs_inode *ip,
const struct xfs_name *name, struct xfs_parent_rec *pptr,
struct xfs_da_args *scratch);
int xfs_parent_set(struct xfs_inode *ip, xfs_ino_t owner,
const struct xfs_name *name, struct xfs_parent_rec *pptr,
struct xfs_da_args *scratch);
int xfs_parent_unset(struct xfs_inode *ip, xfs_ino_t owner,
const struct xfs_name *name, struct xfs_parent_rec *pptr,
struct xfs_da_args *scratch);
#endif /* __XFS_PARENT_H__ */