]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
libxfs: sync xfs_ialloc.c to the kernel code
authorDave Chinner <dchinner@redhat.com>
Wed, 4 Sep 2013 22:05:15 +0000 (22:05 +0000)
committerRich Johnston <rjohnston@sgi.com>
Mon, 16 Sep 2013 20:14:41 +0000 (15:14 -0500)
include the missing xfs_difree() function. it's not used by
userspace, but it makes no sense to have just this one arbitrary
difference between the kernel and userspace files.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Review-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Rich Johnston <rjohnston@sgi.com>
libxfs/xfs.h
libxfs/xfs_ialloc.c

index 15e82d7491f489e71af10c067dd09609ab098ff2..3fd226c4b382685e204dabfcf3f7d022f4a1ac4f 100644 (file)
@@ -208,6 +208,7 @@ roundup_pow_of_two(uint v)
 #define XFS_MOUNT_SMALL_INUMS          0       /* ignored in userspace */
 #define XFS_MOUNT_WSYNC                        0       /* ignored in userspace */
 #define XFS_MOUNT_NOALIGN              0       /* ignored in userspace */
+#define XFS_MOUNT_IKEEP                        0       /* ignored in userspace */
 
 #define xfs_icsb_modify_counters(mp, field, delta, rsvd) \
        xfs_mod_incore_sb(mp, field, delta, rsvd)
index 48916dde43e466ca23229e09e3ab4abde3514e1c..98513fdf9f6aea5f854404c070b045caaa4bb6e7 100644 (file)
@@ -314,7 +314,7 @@ xfs_ialloc_ag_alloc(
         * First try to allocate inodes contiguous with the last-allocated
         * chunk of inodes.  If the filesystem is striped, this will fill
         * an entire stripe unit with inodes.
-        */
+        */
        agi = XFS_BUF_TO_AGI(agbp);
        newino = be32_to_cpu(agi->agi_newino);
        agno = be32_to_cpu(agi->agi_seqno);
@@ -324,8 +324,6 @@ xfs_ialloc_ag_alloc(
                  (args.agbno < be32_to_cpu(agi->agi_length)))) {
                args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
                args.type = XFS_ALLOCTYPE_THIS_BNO;
-               args.mod = args.total = args.wasdel = args.isfl =
-                       args.userdata = args.minalignslop = 0;
                args.prod = 1;
 
                /*
@@ -378,8 +376,6 @@ xfs_ialloc_ag_alloc(
                 * Allocate a fixed-size extent of inodes.
                 */
                args.type = XFS_ALLOCTYPE_NEAR_BNO;
-               args.mod = args.total = args.wasdel = args.isfl =
-                       args.userdata = args.minalignslop = 0;
                args.prod = 1;
                /*
                 * Allow space for the inode btree to split.
@@ -630,8 +626,7 @@ xfs_ialloc_get_rec(
        struct xfs_btree_cur    *cur,
        xfs_agino_t             agino,
        xfs_inobt_rec_incore_t  *rec,
-       int                     *done,
-       int                     left)
+       int                     *done)
 {
        int                     error;
        int                     i;
@@ -739,12 +734,12 @@ xfs_dialloc_ag(
                    pag->pagl_leftrec != NULLAGINO &&
                    pag->pagl_rightrec != NULLAGINO) {
                        error = xfs_ialloc_get_rec(tcur, pag->pagl_leftrec,
-                                                  &trec, &doneleft, 1);
+                                                  &trec, &doneleft);
                        if (error)
                                goto error1;
 
                        error = xfs_ialloc_get_rec(cur, pag->pagl_rightrec,
-                                                  &rec, &doneright, 0);
+                                                  &rec, &doneright);
                        if (error)
                                goto error1;
                } else {
@@ -1074,6 +1069,177 @@ 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             *delete,        /* 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 */
+       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;
+
+       /*
+        * 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));
+       /*
+        * Initialize the cursor.
+        */
+       cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
+
+       error = xfs_check_agi_freecount(cur, agi);
+       if (error)
+               goto error0;
+
+       /*
+        * Look for the entry describing this inode.
+        */
+       if ((error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i))) {
+               xfs_warn(mp, "%s: xfs_inobt_lookup() returned error %d.",
+                       __func__, error);
+               goto error0;
+       }
+       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+       error = xfs_inobt_get_rec(cur, &rec, &i);
+       if (error) {
+               xfs_warn(mp, "%s: xfs_inobt_get_rec() returned error %d.",
+                       __func__, error);
+               goto error0;
+       }
+       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+       /*
+        * Get the offset in the inode chunk.
+        */
+       off = agino - rec.ir_startino;
+       ASSERT(off >= 0 && off < XFS_INODES_PER_CHUNK);
+       ASSERT(!(rec.ir_free & XFS_INOBT_MASK(off)));
+       /*
+        * Mark the inode free & increment the count.
+        */
+       rec.ir_free |= XFS_INOBT_MASK(off);
+       rec.ir_freecount++;
+
+       /*
+        * When an inode cluster is free, it becomes eligible for removal
+        */
+       if (!(mp->m_flags & XFS_MOUNT_IKEEP) &&
+           (rec.ir_freecount == XFS_IALLOC_INODES(mp))) {
+
+               *delete = 1;
+               *first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino);
+
+               /*
+                * Remove the inode cluster from the AGI B+Tree, adjust the
+                * AGI and Superblock inode counts, and mark the disk space
+                * to be freed when the transaction is committed.
+                */
+               ilen = XFS_IALLOC_INODES(mp);
+               be32_add_cpu(&agi->agi_count, -ilen);
+               be32_add_cpu(&agi->agi_freecount, -(ilen - 1));
+               xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT);
+               pag = xfs_perag_get(mp, agno);
+               pag->pagi_freecount -= ilen - 1;
+               xfs_perag_put(pag);
+               xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, -ilen);
+               xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1));
+
+               if ((error = xfs_btree_delete(cur, &i))) {
+                       xfs_warn(mp, "%s: xfs_btree_delete returned error %d.",
+                               __func__, error);
+                       goto error0;
+               }
+
+               xfs_bmap_add_free(XFS_AGB_TO_FSB(mp,
+                               agno, XFS_INO_TO_AGBNO(mp,rec.ir_startino)),
+                               XFS_IALLOC_BLOCKS(mp), flist, mp);
+       } else {
+               *delete = 0;
+
+               error = xfs_inobt_update(cur, &rec);
+               if (error) {
+                       xfs_warn(mp, "%s: xfs_inobt_update returned error %d.",
+                               __func__, error);
+                       goto error0;
+               }
+
+               /* 
+                * Change the inode free counts and log the ag/sb changes.
+                */
+               be32_add_cpu(&agi->agi_freecount, 1);
+               xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
+               pag = xfs_perag_get(mp, agno);
+               pag->pagi_freecount++;
+               xfs_perag_put(pag);
+               xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1);
+       }
+
+       error = xfs_check_agi_freecount(cur, agi);
+       if (error)
+               goto error0;
+
+       xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+       return 0;
+
+error0:
+       xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
+       return error;
+}
+
 STATIC int
 xfs_imap_lookup(
        struct xfs_mount        *mp,
@@ -1153,7 +1319,7 @@ xfs_imap(
        xfs_agblock_t   cluster_agbno;  /* first block in inode cluster */
        int             error;  /* error code */
        int             offset; /* index of inode in its buffer */
-       xfs_agblock_t   offset_agbno;   /* blks from chunk start to inode */
+       int             offset_agbno;   /* blks from chunk start to inode */
 
        ASSERT(ino != NULLFSINO);