Commit 645ceee8 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'xfs-fixes-for-3.14-rc4' of git://oss.sgi.com/xfs/xfs

Pull xfs fixes from Dave Chinner:
 "This is the first pull request I've had to do for you, so I'm still
  sorting things out.  The reason I'm sending this and not Ben should be
  obvious from the first commit below - SGI has stepped down from the
  XFS maintainership role.  As such, I'd like to take another
  opportunity to thank them for their many years of effort maintaining
  XFS and supporting the XFS community that they developed from the
  ground up.

  So I haven't had time to work things like signed tags into my
  workflows yet, so this is just a repo branch I'm asking you to pull
  from.  And yes, I named the branch -rc4 because I wanted the fixes in
  rc4, not because the branch was for merging into -rc3.  Probably not
  right, either.

  Anyway, I should have everything sorted out by the time the next merge
  window comes around.  If there's anything that you don't like in the
  pull req, feel free to flame me unmercifully.

  The changes are fixes for recent regressions and important thinkos in
  verification code:

        - a log vector buffer alignment issue on ia32
        - timestamps on truncate got mangled
        - primary superblock CRC validation fixes and error message
          sanitisation"

* 'xfs-fixes-for-3.14-rc4' of git://oss.sgi.com/xfs/xfs:
  xfs: limit superblock corruption errors to actual corruption
  xfs: skip verification on initial "guess" superblock read
  MAINTAINERS: SGI no longer maintaining XFS
  xfs: xfs_sb_read_verify() doesn't flag bad crcs on primary sb
  xfs: ensure correct log item buffer alignment
  xfs: ensure correct timestamp updates from truncate
parents 10527106 5ef11eb0
...@@ -9728,7 +9728,6 @@ F: drivers/xen/*swiotlb* ...@@ -9728,7 +9728,6 @@ F: drivers/xen/*swiotlb*
XFS FILESYSTEM XFS FILESYSTEM
P: Silicon Graphics Inc P: Silicon Graphics Inc
M: Dave Chinner <david@fromorbit.com> M: Dave Chinner <david@fromorbit.com>
M: Ben Myers <bpm@sgi.com>
M: xfs@oss.sgi.com M: xfs@oss.sgi.com
L: xfs@oss.sgi.com L: xfs@oss.sgi.com
W: http://oss.sgi.com/projects/xfs W: http://oss.sgi.com/projects/xfs
......
...@@ -705,7 +705,6 @@ xfs_setattr_size( ...@@ -705,7 +705,6 @@ xfs_setattr_size(
{ {
struct xfs_mount *mp = ip->i_mount; struct xfs_mount *mp = ip->i_mount;
struct inode *inode = VFS_I(ip); struct inode *inode = VFS_I(ip);
int mask = iattr->ia_valid;
xfs_off_t oldsize, newsize; xfs_off_t oldsize, newsize;
struct xfs_trans *tp; struct xfs_trans *tp;
int error; int error;
...@@ -726,8 +725,8 @@ xfs_setattr_size( ...@@ -726,8 +725,8 @@ xfs_setattr_size(
ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
ASSERT(S_ISREG(ip->i_d.di_mode)); ASSERT(S_ISREG(ip->i_d.di_mode));
ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
oldsize = inode->i_size; oldsize = inode->i_size;
newsize = iattr->ia_size; newsize = iattr->ia_size;
...@@ -736,7 +735,7 @@ xfs_setattr_size( ...@@ -736,7 +735,7 @@ xfs_setattr_size(
* Short circuit the truncate case for zero length files. * Short circuit the truncate case for zero length files.
*/ */
if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) { if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
if (!(mask & (ATTR_CTIME|ATTR_MTIME))) if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME)))
return 0; return 0;
/* /*
...@@ -824,10 +823,11 @@ xfs_setattr_size( ...@@ -824,10 +823,11 @@ xfs_setattr_size(
* these flags set. For all other operations the VFS set these flags * these flags set. For all other operations the VFS set these flags
* explicitly if it wants a timestamp update. * explicitly if it wants a timestamp update.
*/ */
if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) { if (newsize != oldsize &&
!(iattr->ia_valid & (ATTR_CTIME | ATTR_MTIME))) {
iattr->ia_ctime = iattr->ia_mtime = iattr->ia_ctime = iattr->ia_mtime =
current_fs_time(inode->i_sb); current_fs_time(inode->i_sb);
mask |= ATTR_CTIME | ATTR_MTIME; iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
} }
/* /*
...@@ -863,9 +863,9 @@ xfs_setattr_size( ...@@ -863,9 +863,9 @@ xfs_setattr_size(
xfs_inode_clear_eofblocks_tag(ip); xfs_inode_clear_eofblocks_tag(ip);
} }
if (mask & ATTR_MODE) if (iattr->ia_valid & ATTR_MODE)
xfs_setattr_mode(ip, iattr); xfs_setattr_mode(ip, iattr);
if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME)) if (iattr->ia_valid & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
xfs_setattr_time(ip, iattr); xfs_setattr_time(ip, iattr);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
......
...@@ -205,16 +205,25 @@ xlog_cil_insert_format_items( ...@@ -205,16 +205,25 @@ xlog_cil_insert_format_items(
/* /*
* We 64-bit align the length of each iovec so that the start * We 64-bit align the length of each iovec so that the start
* of the next one is naturally aligned. We'll need to * of the next one is naturally aligned. We'll need to
* account for that slack space here. * account for that slack space here. Then round nbytes up
* to 64-bit alignment so that the initial buffer alignment is
* easy to calculate and verify.
*/ */
nbytes += niovecs * sizeof(uint64_t); nbytes += niovecs * sizeof(uint64_t);
nbytes = round_up(nbytes, sizeof(uint64_t));
/* grab the old item if it exists for reservation accounting */ /* grab the old item if it exists for reservation accounting */
old_lv = lip->li_lv; old_lv = lip->li_lv;
/* calc buffer size */ /*
buf_size = sizeof(struct xfs_log_vec) + nbytes + * The data buffer needs to start 64-bit aligned, so round up
niovecs * sizeof(struct xfs_log_iovec); * that space to ensure we can align it appropriately and not
* overrun the buffer.
*/
buf_size = nbytes +
round_up((sizeof(struct xfs_log_vec) +
niovecs * sizeof(struct xfs_log_iovec)),
sizeof(uint64_t));
/* compare to existing item size */ /* compare to existing item size */
if (lip->li_lv && buf_size <= lip->li_lv->lv_size) { if (lip->li_lv && buf_size <= lip->li_lv->lv_size) {
...@@ -251,6 +260,8 @@ xlog_cil_insert_format_items( ...@@ -251,6 +260,8 @@ xlog_cil_insert_format_items(
/* The allocated data region lies beyond the iovec region */ /* The allocated data region lies beyond the iovec region */
lv->lv_buf_len = 0; lv->lv_buf_len = 0;
lv->lv_buf = (char *)lv + buf_size - nbytes; lv->lv_buf = (char *)lv + buf_size - nbytes;
ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t)));
lip->li_ops->iop_format(lip, lv); lip->li_ops->iop_format(lip, lv);
insert: insert:
ASSERT(lv->lv_buf_len <= nbytes); ASSERT(lv->lv_buf_len <= nbytes);
......
...@@ -282,22 +282,29 @@ xfs_readsb( ...@@ -282,22 +282,29 @@ xfs_readsb(
struct xfs_sb *sbp = &mp->m_sb; struct xfs_sb *sbp = &mp->m_sb;
int error; int error;
int loud = !(flags & XFS_MFSI_QUIET); int loud = !(flags & XFS_MFSI_QUIET);
const struct xfs_buf_ops *buf_ops;
ASSERT(mp->m_sb_bp == NULL); ASSERT(mp->m_sb_bp == NULL);
ASSERT(mp->m_ddev_targp != NULL); ASSERT(mp->m_ddev_targp != NULL);
/*
* For the initial read, we must guess at the sector
* size based on the block device. It's enough to
* get the sb_sectsize out of the superblock and
* then reread with the proper length.
* We don't verify it yet, because it may not be complete.
*/
sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
buf_ops = NULL;
/* /*
* Allocate a (locked) buffer to hold the superblock. * Allocate a (locked) buffer to hold the superblock.
* This will be kept around at all times to optimize * This will be kept around at all times to optimize
* access to the superblock. * access to the superblock.
*/ */
sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
reread: reread:
bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR, bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), 0, BTOBB(sector_size), 0, buf_ops);
loud ? &xfs_sb_buf_ops
: &xfs_sb_quiet_buf_ops);
if (!bp) { if (!bp) {
if (loud) if (loud)
xfs_warn(mp, "SB buffer read failed"); xfs_warn(mp, "SB buffer read failed");
...@@ -328,12 +335,13 @@ xfs_readsb( ...@@ -328,12 +335,13 @@ xfs_readsb(
} }
/* /*
* If device sector size is smaller than the superblock size, * Re-read the superblock so the buffer is correctly sized,
* re-read the superblock so the buffer is correctly sized. * and properly verified.
*/ */
if (sector_size < sbp->sb_sectsize) { if (buf_ops == NULL) {
xfs_buf_relse(bp); xfs_buf_relse(bp);
sector_size = sbp->sb_sectsize; sector_size = sbp->sb_sectsize;
buf_ops = loud ? &xfs_sb_buf_ops : &xfs_sb_quiet_buf_ops;
goto reread; goto reread;
} }
......
...@@ -295,8 +295,7 @@ xfs_mount_validate_sb( ...@@ -295,8 +295,7 @@ xfs_mount_validate_sb(
sbp->sb_dblocks == 0 || sbp->sb_dblocks == 0 ||
sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) || sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) ||
sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) { sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) {
XFS_CORRUPTION_ERROR("SB sanity check failed", xfs_notice(mp, "SB sanity check failed");
XFS_ERRLEVEL_LOW, mp, sbp);
return XFS_ERROR(EFSCORRUPTED); return XFS_ERROR(EFSCORRUPTED);
} }
...@@ -611,10 +610,10 @@ xfs_sb_read_verify( ...@@ -611,10 +610,10 @@ xfs_sb_read_verify(
XFS_SB_VERSION_5) || XFS_SB_VERSION_5) ||
dsb->sb_crc != 0)) { dsb->sb_crc != 0)) {
if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize), if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
offsetof(struct xfs_sb, sb_crc))) { offsetof(struct xfs_sb, sb_crc))) {
/* Only fail bad secondaries on a known V5 filesystem */ /* Only fail bad secondaries on a known V5 filesystem */
if (bp->b_bn != XFS_SB_DADDR && if (bp->b_bn == XFS_SB_DADDR ||
xfs_sb_version_hascrc(&mp->m_sb)) { xfs_sb_version_hascrc(&mp->m_sb)) {
error = EFSCORRUPTED; error = EFSCORRUPTED;
goto out_error; goto out_error;
...@@ -625,7 +624,7 @@ xfs_sb_read_verify( ...@@ -625,7 +624,7 @@ xfs_sb_read_verify(
out_error: out_error:
if (error) { if (error) {
if (error != EWRONGFS) if (error == EFSCORRUPTED)
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
mp, bp->b_addr); mp, bp->b_addr);
xfs_buf_ioerror(bp, error); xfs_buf_ioerror(bp, error);
...@@ -644,7 +643,6 @@ xfs_sb_quiet_read_verify( ...@@ -644,7 +643,6 @@ xfs_sb_quiet_read_verify(
{ {
struct xfs_dsb *dsb = XFS_BUF_TO_SBP(bp); struct xfs_dsb *dsb = XFS_BUF_TO_SBP(bp);
if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC)) { if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC)) {
/* XFS filesystem, verify noisily! */ /* XFS filesystem, verify noisily! */
xfs_sb_read_verify(bp); xfs_sb_read_verify(bp);
......
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