Skip to content

Commit

Permalink
xfs: scrub directory metadata
Browse files Browse the repository at this point in the history
Scrub the hash tree and all the entries in a directory.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
  • Loading branch information
Darrick J. Wong committed Oct 26, 2017
1 parent 7c4a07a commit a5c46e5
Show file tree
Hide file tree
Showing 11 changed files with 393 additions and 4 deletions.
1 change: 1 addition & 0 deletions fs/xfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ xfs-y += $(addprefix scrub/, \
btree.o \
common.o \
dabtree.o \
dir.o \
ialloc.o \
inode.o \
refcount.o \
Expand Down
4 changes: 3 additions & 1 deletion fs/xfs/libxfs/xfs_dir2.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
/*
* Convert inode mode to directory entry filetype
*/
unsigned char xfs_mode_to_ftype(int mode)
unsigned char
xfs_mode_to_ftype(
int mode)
{
switch (mode & S_IFMT) {
case S_IFREG:
Expand Down
17 changes: 17 additions & 0 deletions fs/xfs/libxfs/xfs_dir2.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,4 +324,21 @@ xfs_dir2_leaf_tail_p(struct xfs_da_geometry *geo, struct xfs_dir2_leaf *lp)
sizeof(struct xfs_dir2_leaf_tail));
}

/*
* The Linux API doesn't pass down the total size of the buffer
* we read into down to the filesystem. With the filldir concept
* it's not needed for correct information, but the XFS dir2 leaf
* code wants an estimate of the buffer size to calculate it's
* readahead window and size the buffers used for mapping to
* physical blocks.
*
* Try to give it an estimate that's good enough, maybe at some
* point we can change the ->readdir prototype to include the
* buffer size. For now we use the current glibc buffer size.
* musl libc hardcodes 2k and dietlibc uses PAGE_SIZE.
*/
#define XFS_READDIR_BUFSIZE (32768)

unsigned char xfs_dir3_get_dtype(struct xfs_mount *mp, uint8_t filetype);

#endif /* __XFS_DIR2_H__ */
3 changes: 2 additions & 1 deletion fs/xfs/libxfs/xfs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,10 @@ struct xfs_scrub_metadata {
#define XFS_SCRUB_TYPE_BMBTD 12 /* data fork block mapping */
#define XFS_SCRUB_TYPE_BMBTA 13 /* attr fork block mapping */
#define XFS_SCRUB_TYPE_BMBTC 14 /* CoW fork block mapping */
#define XFS_SCRUB_TYPE_DIR 15 /* directory */

/* Number of scrub subcommands. */
#define XFS_SCRUB_TYPE_NR 15
#define XFS_SCRUB_TYPE_NR 16

/* i: Repair this metadata. */
#define XFS_SCRUB_IFLAG_REPAIR (1 << 0)
Expand Down
28 changes: 28 additions & 0 deletions fs/xfs/scrub/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,3 +542,31 @@ xfs_scrub_get_inode(
sc->ip = ip;
return 0;
}

/* Set us up to scrub a file's contents. */
int
xfs_scrub_setup_inode_contents(
struct xfs_scrub_context *sc,
struct xfs_inode *ip,
unsigned int resblks)
{
struct xfs_mount *mp = sc->mp;
int error;

error = xfs_scrub_get_inode(sc, ip);
if (error)
return error;

/* Got the inode, lock it and we're ready to go. */
sc->ilock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
xfs_ilock(sc->ip, sc->ilock_flags);
error = xfs_scrub_trans_alloc(sc->sm, mp, &sc->tp);
if (error)
goto out;
sc->ilock_flags |= XFS_ILOCK_EXCL;
xfs_ilock(sc->ip, XFS_ILOCK_EXCL);

out:
/* scrub teardown will unlock and release the inode for us */
return error;
}
4 changes: 4 additions & 0 deletions fs/xfs/scrub/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ int xfs_scrub_setup_inode_bmap(struct xfs_scrub_context *sc,
struct xfs_inode *ip);
int xfs_scrub_setup_inode_bmap_data(struct xfs_scrub_context *sc,
struct xfs_inode *ip);
int xfs_scrub_setup_directory(struct xfs_scrub_context *sc,
struct xfs_inode *ip);

void xfs_scrub_ag_free(struct xfs_scrub_context *sc, struct xfs_scrub_ag *sa);
int xfs_scrub_ag_init(struct xfs_scrub_context *sc, xfs_agnumber_t agno,
Expand All @@ -111,5 +113,7 @@ 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);
int xfs_scrub_setup_inode_contents(struct xfs_scrub_context *sc,
struct xfs_inode *ip, unsigned int resblks);

#endif /* __XFS_SCRUB_COMMON_H__ */
Loading

0 comments on commit a5c46e5

Please sign in to comment.