Merge branch 'xfs-misc-fixes-2-for-3.16' into for-next
authorDave Chinner <david@fromorbit.com>
Mon, 19 May 2014 22:56:00 +0000 (08:56 +1000)
committerDave Chinner <david@fromorbit.com>
Mon, 19 May 2014 22:56:00 +0000 (08:56 +1000)
Conflicts:
fs/xfs/xfs_ialloc.c

1  2 
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_log_cil.c

Simple merge
@@@ -1430,30 -1098,74 +1430,30 @@@ out_error
        return XFS_ERROR(error);
  }
  
 -/*
 - * Free disk inode.  Carefully avoids touching the incore inode, all
 - * manipulations incore are the caller's responsibility.
 - * The on-disk inode is not changed by this operation, only the
 - * btree (free inode mask) is changed.
 - */
 -int
 -xfs_difree(
 -      xfs_trans_t     *tp,            /* transaction pointer */
 -      xfs_ino_t       inode,          /* inode to be freed */
 -      xfs_bmap_free_t *flist,         /* extents to free */
 -      int             *deleted,       /* set if inode cluster was deleted */
 -      xfs_ino_t       *first_ino)     /* first inode in deleted cluster */
 +STATIC int
 +xfs_difree_inobt(
 +      struct xfs_mount                *mp,
 +      struct xfs_trans                *tp,
 +      struct xfs_buf                  *agbp,
 +      xfs_agino_t                     agino,
 +      struct xfs_bmap_free            *flist,
-       int                             *delete,
++      int                             *deleted,
 +      xfs_ino_t                       *first_ino,
 +      struct xfs_inobt_rec_incore     *orec)
  {
 -      /* REFERENCED */
 -      xfs_agblock_t   agbno;  /* block number containing inode */
 -      xfs_buf_t       *agbp;  /* buffer containing allocation group header */
 -      xfs_agino_t     agino;  /* inode number relative to allocation group */
 -      xfs_agnumber_t  agno;   /* allocation group number */
 -      xfs_agi_t       *agi;   /* allocation group header */
 -      xfs_btree_cur_t *cur;   /* inode btree cursor */
 -      int             error;  /* error return value */
 -      int             i;      /* result code */
 -      int             ilen;   /* inodes in an inode cluster */
 -      xfs_mount_t     *mp;    /* mount structure for filesystem */
 -      int             off;    /* offset of inode in inode chunk */
 -      xfs_inobt_rec_incore_t rec;     /* btree record */
 -      struct xfs_perag *pag;
 -
 -      mp = tp->t_mountp;
 +      struct xfs_agi                  *agi = XFS_BUF_TO_AGI(agbp);
 +      xfs_agnumber_t                  agno = be32_to_cpu(agi->agi_seqno);
 +      struct xfs_perag                *pag;
 +      struct xfs_btree_cur            *cur;
 +      struct xfs_inobt_rec_incore     rec;
 +      int                             ilen;
 +      int                             error;
 +      int                             i;
 +      int                             off;
  
 -      /*
 -       * Break up inode number into its components.
 -       */
 -      agno = XFS_INO_TO_AGNO(mp, inode);
 -      if (agno >= mp->m_sb.sb_agcount)  {
 -              xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).",
 -                      __func__, agno, mp->m_sb.sb_agcount);
 -              ASSERT(0);
 -              return XFS_ERROR(EINVAL);
 -      }
 -      agino = XFS_INO_TO_AGINO(mp, inode);
 -      if (inode != XFS_AGINO_TO_INO(mp, agno, agino))  {
 -              xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).",
 -                      __func__, (unsigned long long)inode,
 -                      (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino));
 -              ASSERT(0);
 -              return XFS_ERROR(EINVAL);
 -      }
 -      agbno = XFS_AGINO_TO_AGBNO(mp, agino);
 -      if (agbno >= mp->m_sb.sb_agblocks)  {
 -              xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).",
 -                      __func__, agbno, mp->m_sb.sb_agblocks);
 -              ASSERT(0);
 -              return XFS_ERROR(EINVAL);
 -      }
 -      /*
 -       * Get the allocation group header.
 -       */
 -      error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
 -      if (error) {
 -              xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.",
 -                      __func__, error);
 -              return error;
 -      }
 -      agi = XFS_BUF_TO_AGI(agbp);
        ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
 -      ASSERT(agbno < be32_to_cpu(agi->agi_length));
 +      ASSERT(XFS_AGINO_TO_AGBNO(mp, agino) < be32_to_cpu(agi->agi_length));
 +
        /*
         * Initialize the cursor.
         */
@@@ -1558,182 -1269,6 +1558,182 @@@ error0
        return error;
  }
  
-       int                     *delete,/* set if inode cluster was deleted */
 +/*
 + * Free an inode in the free inode btree.
 + */
 +STATIC int
 +xfs_difree_finobt(
 +      struct xfs_mount                *mp,
 +      struct xfs_trans                *tp,
 +      struct xfs_buf                  *agbp,
 +      xfs_agino_t                     agino,
 +      struct xfs_inobt_rec_incore     *ibtrec) /* inobt record */
 +{
 +      struct xfs_agi                  *agi = XFS_BUF_TO_AGI(agbp);
 +      xfs_agnumber_t                  agno = be32_to_cpu(agi->agi_seqno);
 +      struct xfs_btree_cur            *cur;
 +      struct xfs_inobt_rec_incore     rec;
 +      int                             offset = agino - ibtrec->ir_startino;
 +      int                             error;
 +      int                             i;
 +
 +      cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_FINO);
 +
 +      error = xfs_inobt_lookup(cur, ibtrec->ir_startino, XFS_LOOKUP_EQ, &i);
 +      if (error)
 +              goto error;
 +      if (i == 0) {
 +              /*
 +               * If the record does not exist in the finobt, we must have just
 +               * freed an inode in a previously fully allocated chunk. If not,
 +               * something is out of sync.
 +               */
 +              XFS_WANT_CORRUPTED_GOTO(ibtrec->ir_freecount == 1, error);
 +
 +              error = xfs_inobt_insert_rec(cur, ibtrec->ir_freecount,
 +                                           ibtrec->ir_free, &i);
 +              if (error)
 +                      goto error;
 +              ASSERT(i == 1);
 +
 +              goto out;
 +      }
 +
 +      /*
 +       * Read and update the existing record. We could just copy the ibtrec
 +       * across here, but that would defeat the purpose of having redundant
 +       * metadata. By making the modifications independently, we can catch
 +       * corruptions that we wouldn't see if we just copied from one record
 +       * to another.
 +       */
 +      error = xfs_inobt_get_rec(cur, &rec, &i);
 +      if (error)
 +              goto error;
 +      XFS_WANT_CORRUPTED_GOTO(i == 1, error);
 +
 +      rec.ir_free |= XFS_INOBT_MASK(offset);
 +      rec.ir_freecount++;
 +
 +      XFS_WANT_CORRUPTED_GOTO((rec.ir_free == ibtrec->ir_free) &&
 +                              (rec.ir_freecount == ibtrec->ir_freecount),
 +                              error);
 +
 +      /*
 +       * The content of inobt records should always match between the inobt
 +       * and finobt. The lifecycle of records in the finobt is different from
 +       * the inobt in that the finobt only tracks records with at least one
 +       * free inode. Hence, if all of the inodes are free and we aren't
 +       * keeping inode chunks permanently on disk, remove the record.
 +       * Otherwise, update the record with the new information.
 +       */
 +      if (rec.ir_freecount == mp->m_ialloc_inos &&
 +          !(mp->m_flags & XFS_MOUNT_IKEEP)) {
 +              error = xfs_btree_delete(cur, &i);
 +              if (error)
 +                      goto error;
 +              ASSERT(i == 1);
 +      } else {
 +              error = xfs_inobt_update(cur, &rec);
 +              if (error)
 +                      goto error;
 +      }
 +
 +out:
 +      error = xfs_check_agi_freecount(cur, agi);
 +      if (error)
 +              goto error;
 +
 +      xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
 +      return 0;
 +
 +error:
 +      xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
 +      return error;
 +}
 +
 +/*
 + * Free disk inode.  Carefully avoids touching the incore inode, all
 + * manipulations incore are the caller's responsibility.
 + * The on-disk inode is not changed by this operation, only the
 + * btree (free inode mask) is changed.
 + */
 +int
 +xfs_difree(
 +      struct xfs_trans        *tp,            /* transaction pointer */
 +      xfs_ino_t               inode,          /* inode to be freed */
 +      struct xfs_bmap_free    *flist,         /* extents to free */
-       error = xfs_difree_inobt(mp, tp, agbp, agino, flist, delete, first_ino,
++      int                     *deleted,/* set if inode cluster was deleted */
 +      xfs_ino_t               *first_ino)/* first inode in deleted cluster */
 +{
 +      /* REFERENCED */
 +      xfs_agblock_t           agbno;  /* block number containing inode */
 +      struct xfs_buf          *agbp;  /* buffer for allocation group header */
 +      xfs_agino_t             agino;  /* allocation group inode number */
 +      xfs_agnumber_t          agno;   /* allocation group number */
 +      int                     error;  /* error return value */
 +      struct xfs_mount        *mp;    /* mount structure for filesystem */
 +      struct xfs_inobt_rec_incore rec;/* btree record */
 +
 +      mp = tp->t_mountp;
 +
 +      /*
 +       * Break up inode number into its components.
 +       */
 +      agno = XFS_INO_TO_AGNO(mp, inode);
 +      if (agno >= mp->m_sb.sb_agcount)  {
 +              xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).",
 +                      __func__, agno, mp->m_sb.sb_agcount);
 +              ASSERT(0);
 +              return XFS_ERROR(EINVAL);
 +      }
 +      agino = XFS_INO_TO_AGINO(mp, inode);
 +      if (inode != XFS_AGINO_TO_INO(mp, agno, agino))  {
 +              xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).",
 +                      __func__, (unsigned long long)inode,
 +                      (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino));
 +              ASSERT(0);
 +              return XFS_ERROR(EINVAL);
 +      }
 +      agbno = XFS_AGINO_TO_AGBNO(mp, agino);
 +      if (agbno >= mp->m_sb.sb_agblocks)  {
 +              xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).",
 +                      __func__, agbno, mp->m_sb.sb_agblocks);
 +              ASSERT(0);
 +              return XFS_ERROR(EINVAL);
 +      }
 +      /*
 +       * Get the allocation group header.
 +       */
 +      error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
 +      if (error) {
 +              xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.",
 +                      __func__, error);
 +              return error;
 +      }
 +
 +      /*
 +       * Fix up the inode allocation btree.
 +       */
++      error = xfs_difree_inobt(mp, tp, agbp, agino, flist, deleted, first_ino,
 +                               &rec);
 +      if (error)
 +              goto error0;
 +
 +      /*
 +       * Fix up the free inode btree.
 +       */
 +      if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
 +              error = xfs_difree_finobt(mp, tp, agbp, agino, &rec);
 +              if (error)
 +                      goto error0;
 +      }
 +
 +      return 0;
 +
 +error0:
 +      return error;
 +}
 +
  STATIC int
  xfs_imap_lookup(
        struct xfs_mount        *mp,
Simple merge