Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 339421
b: refs/heads/master
c: 9802182
h: refs/heads/master
i:
  339419: 31c6b34
v: v3
  • Loading branch information
Dave Chinner authored and Ben Myers committed Nov 16, 2012
1 parent da98061 commit 599aa4c
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 42 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: eab4e63368b4cfa597dbdac66d1a7a836a693b7d
refs/heads/master: 98021821a502db347bd9c7671beeee6e8ce07ea6
4 changes: 3 additions & 1 deletion trunk/fs/xfs/xfs_fsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,8 @@ xfs_growfs_data_private(
if (agno < oagcount) {
error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL);
XFS_FSS_TO_BB(mp, 1), 0, &bp,
xfs_sb_read_verify);
} else {
bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp,
XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
Expand All @@ -462,6 +463,7 @@ xfs_growfs_data_private(
break;
}
xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);

/*
* If we get an error writing out the alternate superblocks,
* just issue a warning and continue. The real work is
Expand Down
5 changes: 3 additions & 2 deletions trunk/fs/xfs/xfs_log_recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -3692,13 +3692,14 @@ xlog_do_recover(

/*
* Now that we've finished replaying all buffer and inode
* updates, re-read in the superblock.
* updates, re-read in the superblock and reverify it.
*/
bp = xfs_getsb(log->l_mp, 0);
XFS_BUF_UNDONE(bp);
ASSERT(!(XFS_BUF_ISWRITE(bp)));
XFS_BUF_READ(bp);
XFS_BUF_UNASYNC(bp);
bp->b_iodone = xfs_sb_read_verify;
xfsbdstrat(log->l_mp, bp);
error = xfs_buf_iowait(bp);
if (error) {
Expand All @@ -3710,7 +3711,7 @@ xlog_do_recover(

/* Convert superblock from on-disk format */
sbp = &log->l_mp->m_sb;
xfs_sb_from_disk(log->l_mp, XFS_BUF_TO_SBP(bp));
xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
ASSERT(xfs_sb_good_version(sbp));
xfs_buf_relse(bp);
Expand Down
98 changes: 61 additions & 37 deletions trunk/fs/xfs/xfs_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,8 @@ STATIC int
xfs_mount_validate_sb(
xfs_mount_t *mp,
xfs_sb_t *sbp,
int flags)
bool check_inprogress)
{
int loud = !(flags & XFS_MFSI_QUIET);

/*
* If the log device and data device have the
Expand All @@ -316,30 +315,26 @@ xfs_mount_validate_sb(
* a volume filesystem in a non-volume manner.
*/
if (sbp->sb_magicnum != XFS_SB_MAGIC) {
if (loud)
xfs_warn(mp, "bad magic number");
xfs_warn(mp, "bad magic number");
return XFS_ERROR(EWRONGFS);
}

if (!xfs_sb_good_version(sbp)) {
if (loud)
xfs_warn(mp, "bad version");
xfs_warn(mp, "bad version");
return XFS_ERROR(EWRONGFS);
}

if (unlikely(
sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
if (loud)
xfs_warn(mp,
xfs_warn(mp,
"filesystem is marked as having an external log; "
"specify logdev on the mount command line.");
return XFS_ERROR(EINVAL);
}

if (unlikely(
sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
if (loud)
xfs_warn(mp,
xfs_warn(mp,
"filesystem is marked as having an internal log; "
"do not specify logdev on the mount command line.");
return XFS_ERROR(EINVAL);
Expand Down Expand Up @@ -373,8 +368,7 @@ xfs_mount_validate_sb(
sbp->sb_dblocks == 0 ||
sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) ||
sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) {
if (loud)
XFS_CORRUPTION_ERROR("SB sanity check failed",
XFS_CORRUPTION_ERROR("SB sanity check failed",
XFS_ERRLEVEL_LOW, mp, sbp);
return XFS_ERROR(EFSCORRUPTED);
}
Expand All @@ -383,12 +377,10 @@ xfs_mount_validate_sb(
* Until this is fixed only page-sized or smaller data blocks work.
*/
if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
if (loud) {
xfs_warn(mp,
xfs_warn(mp,
"File system with blocksize %d bytes. "
"Only pagesize (%ld) or less will currently work.",
sbp->sb_blocksize, PAGE_SIZE);
}
return XFS_ERROR(ENOSYS);
}

Expand All @@ -402,33 +394,28 @@ xfs_mount_validate_sb(
case 2048:
break;
default:
if (loud)
xfs_warn(mp, "inode size of %d bytes not supported",
xfs_warn(mp, "inode size of %d bytes not supported",
sbp->sb_inodesize);
return XFS_ERROR(ENOSYS);
}

if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
if (loud)
xfs_warn(mp,
xfs_warn(mp,
"file system too large to be mounted on this system.");
return XFS_ERROR(EFBIG);
}

if (unlikely(sbp->sb_inprogress)) {
if (loud)
xfs_warn(mp, "file system busy");
if (check_inprogress && sbp->sb_inprogress) {
xfs_warn(mp, "Offline file system operation in progress!");
return XFS_ERROR(EFSCORRUPTED);
}

/*
* Version 1 directory format has never worked on Linux.
*/
if (unlikely(!xfs_sb_version_hasdirv2(sbp))) {
if (loud)
xfs_warn(mp,
"file system using version 1 directory format");
xfs_warn(mp, "file system using version 1 directory format");
return XFS_ERROR(ENOSYS);
}

Expand Down Expand Up @@ -521,11 +508,9 @@ xfs_initialize_perag(

void
xfs_sb_from_disk(
struct xfs_mount *mp,
struct xfs_sb *to,
xfs_dsb_t *from)
{
struct xfs_sb *to = &mp->m_sb;

to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
Expand Down Expand Up @@ -627,6 +612,50 @@ xfs_sb_to_disk(
}
}

void
xfs_sb_read_verify(
struct xfs_buf *bp)
{
struct xfs_mount *mp = bp->b_target->bt_mount;
struct xfs_sb sb;
int error;

xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp));

/*
* Only check the in progress field for the primary superblock as
* mkfs.xfs doesn't clear it from secondary superblocks.
*/
error = xfs_mount_validate_sb(mp, &sb, bp->b_bn == XFS_SB_DADDR);
if (error)
xfs_buf_ioerror(bp, error);
bp->b_iodone = NULL;
xfs_buf_ioend(bp, 0);
}

/*
* We may be probed for a filesystem match, so we may not want to emit
* messages when the superblock buffer is not actually an XFS superblock.
* If we find an XFS superblock, the run a normal, noisy mount because we are
* really going to mount it and want to know about errors.
*/
void
xfs_sb_quiet_read_verify(
struct xfs_buf *bp)
{
struct xfs_sb sb;

xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp));

if (sb.sb_magicnum == XFS_SB_MAGIC) {
/* XFS filesystem, verify noisily! */
xfs_sb_read_verify(bp);
return;
}
/* quietly fail */
xfs_buf_ioerror(bp, EFSCORRUPTED);
}

/*
* xfs_readsb
*
Expand All @@ -652,7 +681,9 @@ xfs_readsb(xfs_mount_t *mp, int flags)

reread:
bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), 0, NULL);
BTOBB(sector_size), 0,
loud ? xfs_sb_read_verify
: xfs_sb_quiet_read_verify);
if (!bp) {
if (loud)
xfs_warn(mp, "SB buffer read failed");
Expand All @@ -667,15 +698,8 @@ xfs_readsb(xfs_mount_t *mp, int flags)

/*
* Initialize the mount structure from the superblock.
* But first do some basic consistency checking.
*/
xfs_sb_from_disk(mp, XFS_BUF_TO_SBP(bp));
error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
if (error) {
if (loud)
xfs_warn(mp, "SB validate failed");
goto release_buf;
}
xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));

/*
* We must be able to do sector-sized and sector-aligned IO.
Expand Down
3 changes: 2 additions & 1 deletion trunk/fs/xfs/xfs_mount.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,11 @@ extern void xfs_set_low_space_thresholds(struct xfs_mount *);

#endif /* __KERNEL__ */

extern void xfs_sb_read_verify(struct xfs_buf *);
extern void xfs_mod_sb(struct xfs_trans *, __int64_t);
extern int xfs_initialize_perag(struct xfs_mount *, xfs_agnumber_t,
xfs_agnumber_t *);
extern void xfs_sb_from_disk(struct xfs_mount *, struct xfs_dsb *);
extern void xfs_sb_from_disk(struct xfs_sb *, struct xfs_dsb *);
extern void xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t);

#endif /* __XFS_MOUNT_H__ */

0 comments on commit 599aa4c

Please sign in to comment.