You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
xfs: scrub inodes
Scrub the fields within an inode. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Dave Chinner <dchinner@redhat.com>
This commit is contained in:
@@ -148,6 +148,7 @@ xfs-y += $(addprefix scrub/, \
|
||||
btree.o \
|
||||
common.o \
|
||||
ialloc.o \
|
||||
inode.o \
|
||||
refcount.o \
|
||||
rmap.o \
|
||||
scrub.o \
|
||||
|
||||
@@ -494,9 +494,10 @@ struct xfs_scrub_metadata {
|
||||
#define XFS_SCRUB_TYPE_FINOBT 8 /* free inode btree */
|
||||
#define XFS_SCRUB_TYPE_RMAPBT 9 /* reverse mapping btree */
|
||||
#define XFS_SCRUB_TYPE_REFCNTBT 10 /* reference count btree */
|
||||
#define XFS_SCRUB_TYPE_INODE 11 /* inode record */
|
||||
|
||||
/* Number of scrub subcommands. */
|
||||
#define XFS_SCRUB_TYPE_NR 11
|
||||
#define XFS_SCRUB_TYPE_NR 12
|
||||
|
||||
/* i: Repair this metadata. */
|
||||
#define XFS_SCRUB_IFLAG_REPAIR (1 << 0)
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_sb.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_icache.h"
|
||||
#include "xfs_itable.h"
|
||||
#include "xfs_alloc.h"
|
||||
#include "xfs_alloc_btree.h"
|
||||
#include "xfs_bmap.h"
|
||||
@@ -488,3 +490,55 @@ xfs_scrub_checkpoint_log(
|
||||
xfs_ail_push_all_sync(mp->m_ail);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an inode and the scrub control structure, grab either the
|
||||
* inode referenced in the control structure or the inode passed in.
|
||||
* The inode is not locked.
|
||||
*/
|
||||
int
|
||||
xfs_scrub_get_inode(
|
||||
struct xfs_scrub_context *sc,
|
||||
struct xfs_inode *ip_in)
|
||||
{
|
||||
struct xfs_mount *mp = sc->mp;
|
||||
struct xfs_inode *ip = NULL;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* If userspace passed us an AG number or a generation number
|
||||
* without an inode number, they haven't got a clue so bail out
|
||||
* immediately.
|
||||
*/
|
||||
if (sc->sm->sm_agno || (sc->sm->sm_gen && !sc->sm->sm_ino))
|
||||
return -EINVAL;
|
||||
|
||||
/* We want to scan the inode we already had opened. */
|
||||
if (sc->sm->sm_ino == 0 || sc->sm->sm_ino == ip_in->i_ino) {
|
||||
sc->ip = ip_in;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look up the inode, see if the generation number matches. */
|
||||
if (xfs_internal_inum(mp, sc->sm->sm_ino))
|
||||
return -ENOENT;
|
||||
error = xfs_iget(mp, NULL, sc->sm->sm_ino,
|
||||
XFS_IGET_UNTRUSTED | XFS_IGET_DONTCACHE, 0, &ip);
|
||||
if (error == -ENOENT || error == -EINVAL) {
|
||||
/* inode doesn't exist... */
|
||||
return -ENOENT;
|
||||
} else if (error) {
|
||||
trace_xfs_scrub_op_error(sc,
|
||||
XFS_INO_TO_AGNO(mp, sc->sm->sm_ino),
|
||||
XFS_INO_TO_AGBNO(mp, sc->sm->sm_ino),
|
||||
error, __return_address);
|
||||
return error;
|
||||
}
|
||||
if (VFS_I(ip)->i_generation != sc->sm->sm_gen) {
|
||||
iput(VFS_I(ip));
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
sc->ip = ip;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,8 @@ int xfs_scrub_setup_ag_rmapbt(struct xfs_scrub_context *sc,
|
||||
struct xfs_inode *ip);
|
||||
int xfs_scrub_setup_ag_refcountbt(struct xfs_scrub_context *sc,
|
||||
struct xfs_inode *ip);
|
||||
int xfs_scrub_setup_inode(struct xfs_scrub_context *sc,
|
||||
struct xfs_inode *ip);
|
||||
|
||||
|
||||
void xfs_scrub_ag_free(struct xfs_scrub_context *sc, struct xfs_scrub_ag *sa);
|
||||
@@ -105,5 +107,6 @@ int xfs_scrub_walk_agfl(struct xfs_scrub_context *sc,
|
||||
|
||||
int xfs_scrub_setup_ag_btree(struct xfs_scrub_context *sc,
|
||||
struct xfs_inode *ip, bool force_log);
|
||||
int xfs_scrub_get_inode(struct xfs_scrub_context *sc, struct xfs_inode *ip_in);
|
||||
|
||||
#endif /* __XFS_SCRUB_COMMON_H__ */
|
||||
|
||||
611
fs/xfs/scrub/inode.c
Normal file
611
fs/xfs/scrub/inode.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,8 @@
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_sb.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_icache.h"
|
||||
#include "xfs_itable.h"
|
||||
#include "xfs_alloc.h"
|
||||
#include "xfs_alloc_btree.h"
|
||||
#include "xfs_bmap.h"
|
||||
@@ -141,6 +143,7 @@ xfs_scrub_probe(
|
||||
STATIC int
|
||||
xfs_scrub_teardown(
|
||||
struct xfs_scrub_context *sc,
|
||||
struct xfs_inode *ip_in,
|
||||
int error)
|
||||
{
|
||||
xfs_scrub_ag_free(sc, &sc->sa);
|
||||
@@ -148,6 +151,13 @@ xfs_scrub_teardown(
|
||||
xfs_trans_cancel(sc->tp);
|
||||
sc->tp = NULL;
|
||||
}
|
||||
if (sc->ip) {
|
||||
xfs_iunlock(sc->ip, sc->ilock_flags);
|
||||
if (sc->ip != ip_in &&
|
||||
!xfs_internal_inum(sc->mp, sc->ip->i_ino))
|
||||
iput(VFS_I(sc->ip));
|
||||
sc->ip = NULL;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -201,6 +211,10 @@ static const struct xfs_scrub_meta_ops meta_scrub_ops[] = {
|
||||
.scrub = xfs_scrub_refcountbt,
|
||||
.has = xfs_sb_version_hasreflink,
|
||||
},
|
||||
{ /* inode record */
|
||||
.setup = xfs_scrub_setup_inode,
|
||||
.scrub = xfs_scrub_inode,
|
||||
},
|
||||
};
|
||||
|
||||
/* This isn't a stable feature, warn once per day. */
|
||||
@@ -300,7 +314,7 @@ retry_op:
|
||||
* Tear down everything we hold, then set up again with
|
||||
* preparation for worst-case scenarios.
|
||||
*/
|
||||
error = xfs_scrub_teardown(&sc, 0);
|
||||
error = xfs_scrub_teardown(&sc, ip, 0);
|
||||
if (error)
|
||||
goto out;
|
||||
try_harder = true;
|
||||
@@ -313,7 +327,7 @@ retry_op:
|
||||
xfs_alert_ratelimited(mp, "Corruption detected during scrub.");
|
||||
|
||||
out_teardown:
|
||||
error = xfs_scrub_teardown(&sc, error);
|
||||
error = xfs_scrub_teardown(&sc, ip, error);
|
||||
out:
|
||||
trace_xfs_scrub_done(ip, sm, error);
|
||||
if (error == -EFSCORRUPTED || error == -EFSBADCRC) {
|
||||
|
||||
@@ -59,6 +59,7 @@ struct xfs_scrub_context {
|
||||
const struct xfs_scrub_meta_ops *ops;
|
||||
struct xfs_trans *tp;
|
||||
struct xfs_inode *ip;
|
||||
uint ilock_flags;
|
||||
bool try_harder;
|
||||
|
||||
/* State tracking for single-AG operations. */
|
||||
@@ -77,5 +78,6 @@ int xfs_scrub_inobt(struct xfs_scrub_context *sc);
|
||||
int xfs_scrub_finobt(struct xfs_scrub_context *sc);
|
||||
int xfs_scrub_rmapbt(struct xfs_scrub_context *sc);
|
||||
int xfs_scrub_refcountbt(struct xfs_scrub_context *sc);
|
||||
int xfs_scrub_inode(struct xfs_scrub_context *sc);
|
||||
|
||||
#endif /* __XFS_SCRUB_SCRUB_H__ */
|
||||
|
||||
@@ -1202,6 +1202,8 @@ out_unlock:
|
||||
* 8. for non-realtime files, the extent size hint must be limited
|
||||
* to half the AG size to avoid alignment extending the extent beyond the
|
||||
* limits of the AG.
|
||||
*
|
||||
* Please keep this function in sync with xfs_scrub_inode_extsize.
|
||||
*/
|
||||
static int
|
||||
xfs_ioctl_setattr_check_extsize(
|
||||
@@ -1258,6 +1260,8 @@ xfs_ioctl_setattr_check_extsize(
|
||||
* 5. Extent size must be a multiple of the appropriate block size.
|
||||
* 6. The extent size hint must be limited to half the AG size to avoid
|
||||
* alignment extending the extent beyond the limits of the AG.
|
||||
*
|
||||
* Please keep this function in sync with xfs_scrub_inode_cowextsize.
|
||||
*/
|
||||
static int
|
||||
xfs_ioctl_setattr_check_cowextsize(
|
||||
|
||||
Reference in New Issue
Block a user