]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
libxfs: fix root inode handling inconsistencies
authorDave Chinner <dchinner@redhat.com>
Wed, 13 Nov 2013 06:40:39 +0000 (06:40 +0000)
committerRich Johnston <rjohnston@sgi.com>
Wed, 13 Nov 2013 17:08:19 +0000 (11:08 -0600)
When "mounting" a filesystem via libxfs_mount(), callers can tell
libxfs to read the root and realtime inodes into cache. However,
when unmounting the filesystem, libxfs_unmount() used to
unconditionally free root inodes if they were present.

This leads to interesting issues like in mkfs, when it handles
creation, reading and freeing of the root and rt inodes itself.
It, however, passes in the flag to tell libxfs_mount() to read the
root inodes and so can result in unbalanced freeing of inodes when
cleaning up during the unmount proceedure.

As it turns out, nothing ever uses mp->m_rootip and so we don't need
to read it in or free it, or even have a pointer to it in the struct
xfs_mount. Similarly, the only user of the realtime inodes is mkfs,
and it initialises them itself. Hence we can kill the m_rootip and
the realtime inode mounting code.

This leaves one user of LIBXFS_MOUNT_ROOTINOS - xfs_db - and that is
only used to initialise the in-core superblock counter values from
the ag header for xfs_check. Move this code to the xfs_db init
functions so we can get rid of the mount parameter previously used
to trigger all these behavours (LIBXFS_MOUNT_ROOTINOS) completely.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Rich Johnston <rjohnston@sgi.com>
copy/xfs_copy.c
db/init.c
include/libxfs.h
libxfs/init.c
mkfs/proto.c
mkfs/xfs_mkfs.c
repair/phase6.c

index bb37279a61a81df43df0f84f5f34b7c3c79f7341..9986fbf60a04915a5a00281038d17f435a5dc710 100644 (file)
@@ -684,7 +684,7 @@ main(int argc, char **argv)
        sb = &mbuf.m_sb;
        libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbp));
 
-       mp = libxfs_mount(&mbuf, sb, xargs.ddev, xargs.logdev, xargs.rtdev, 1);
+       mp = libxfs_mount(&mbuf, sb, xargs.ddev, xargs.logdev, xargs.rtdev, 0);
        if (mp == NULL) {
                do_log(_("%s: %s filesystem failed to initialize\n"
                        "%s: Aborting.\n"), progname, source_name, progname);
index 2932e51b54f293db8d62215168f7d5f60ed73c23..d73d5490d57870058fd4034a5d5a075a1e180d8b 100644 (file)
--- a/db/init.c
+++ b/db/init.c
@@ -149,18 +149,28 @@ init(
        }
 
        mp = libxfs_mount(&xmount, sbp, x.ddev, x.logdev, x.rtdev,
-                               LIBXFS_MOUNT_ROOTINOS | LIBXFS_MOUNT_DEBUGGER);
+                         LIBXFS_MOUNT_DEBUGGER);
        if (!mp) {
-               mp = libxfs_mount(&xmount, sbp, x.ddev, x.logdev, x.rtdev,
-                               LIBXFS_MOUNT_DEBUGGER);
-               if (!mp) {
-                       fprintf(stderr, _("%s: device %s unusable (not an XFS "
-                               "filesystem?)\n"), progname, fsdevice);
-                       exit(1);
-               }
+               fprintf(stderr,
+                       _("%s: device %s unusable (not an XFS filesystem?)\n"),
+                       progname, fsdevice);
+               exit(1);
        }
        blkbb = 1 << mp->m_blkbb_log;
 
+       /*
+        * xfs_check needs corrected incore superblock values
+        */
+       if (sbp->sb_rootino != NULLFSINO &&
+           xfs_sb_version_haslazysbcount(&mp->m_sb)) {
+               int error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
+               if (error) {
+                       fprintf(stderr,
+       _("%s: cannot init perag data (%d). Continuing anyway.\n"),
+                               progname, error);
+               }
+       }
+
        if (xfs_sb_version_hascrc(&mp->m_sb))
                type_set_tab_crc();
 
index f10ab5954c514bd8657bdc0edf240a2ceacfeb0f..3df8c07ec3ca0c02580a06ee92f06384cd2f0366 100644 (file)
@@ -167,7 +167,6 @@ typedef struct xfs_mount {
        uint                    m_rsumsize;     /* size of rt summary, bytes */
        struct xfs_inode        *m_rbmip;       /* pointer to bitmap inode */
        struct xfs_inode        *m_rsumip;      /* pointer to summary inode */
-       struct xfs_inode        *m_rootip;      /* pointer to root directory */
        struct xfs_buftarg      *m_ddev_targp;
        struct xfs_buftarg      *m_logdev_targp;
        struct xfs_buftarg      *m_rtdev_targp;
@@ -259,12 +258,11 @@ typedef struct xfs_perag {
        int             pagb_count;     /* pagb slots in use */
 } xfs_perag_t;
 
-#define LIBXFS_MOUNT_ROOTINOS          0x0001
-#define LIBXFS_MOUNT_DEBUGGER          0x0002
-#define LIBXFS_MOUNT_32BITINODES       0x0004
-#define LIBXFS_MOUNT_32BITINOOPT       0x0008
-#define LIBXFS_MOUNT_COMPAT_ATTR       0x0010
-#define LIBXFS_MOUNT_ATTR2             0x0020
+#define LIBXFS_MOUNT_DEBUGGER          0x0001
+#define LIBXFS_MOUNT_32BITINODES       0x0002
+#define LIBXFS_MOUNT_32BITINOOPT       0x0004
+#define LIBXFS_MOUNT_COMPAT_ATTR       0x0008
+#define LIBXFS_MOUNT_ATTR2             0x0010
 
 #define LIBXFS_IHASHSIZE(sbp)          (1<<10)
 #define LIBXFS_BHASHSIZE(sbp)          (1<<10)
index db7eeea9e97fced54608e74f464064833e487e07..33c01f5313a2620d140fe68b19d9107cee917153 100644 (file)
@@ -409,40 +409,6 @@ manage_zones(int release)
        xfs_dir_startup();
 }
 
-/*
- * Get the bitmap and summary inodes into the mount structure
- * at mount time.
- */
-static int
-rtmount_inodes(xfs_mount_t *mp)
-{
-       int             error;
-       xfs_sb_t        *sbp;
-
-       sbp = &mp->m_sb;
-       if (sbp->sb_rbmino == NULLFSINO)
-               return 0;
-       error = libxfs_iget(mp, NULL, sbp->sb_rbmino, 0, &mp->m_rbmip, 0);
-       if (error) {
-               fprintf(stderr,
-                       _("%s: cannot read realtime bitmap inode (%d)\n"),
-                       progname, error);
-               return error;
-       }
-       ASSERT(mp->m_rbmip != NULL);
-       ASSERT(sbp->sb_rsumino != NULLFSINO);
-       error = libxfs_iget(mp, NULL, sbp->sb_rsumino, 0, &mp->m_rsumip, 0);
-       if (error) {
-               libxfs_iput(mp->m_rbmip, 0);
-               fprintf(stderr,
-                       _("%s: cannot read realtime summary inode (%d)\n"),
-                       progname, error);
-               return error;
-       }
-       ASSERT(mp->m_rsumip != NULL);
-       return 0;
-}
-
 /*
  * Initialize realtime fields in the mount structure.
  */
@@ -810,39 +776,6 @@ libxfs_mount(
                exit(1);
        }
 
-       /*
-        * mkfs calls mount before the root inode is allocated.
-        */
-       if ((flags & LIBXFS_MOUNT_ROOTINOS) && sbp->sb_rootino != NULLFSINO) {
-               error = libxfs_iget(mp, NULL, sbp->sb_rootino, 0,
-                               &mp->m_rootip, 0);
-               if (error) {
-                       fprintf(stderr, _("%s: cannot read root inode (%d)\n"),
-                               progname, error);
-                       if (!(flags & LIBXFS_MOUNT_DEBUGGER))
-                               return NULL;
-               }
-               ASSERT(mp->m_rootip != NULL);
-       }
-       if ((flags & LIBXFS_MOUNT_ROOTINOS) && rtmount_inodes(mp)) {
-               if (mp->m_rootip)
-                       libxfs_iput(mp->m_rootip, 0);
-               return NULL;
-       }
-
-       /*
-        * mkfs calls mount before the AGF/AGI structures are written.
-        */
-       if ((flags & LIBXFS_MOUNT_ROOTINOS) && sbp->sb_rootino != NULLFSINO &&
-           xfs_sb_version_haslazysbcount(&mp->m_sb)) {
-               error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
-               if (error) {
-                       fprintf(stderr, _("%s: cannot init perag data (%d)\n"),
-                               progname, error);
-                       return NULL;
-               }
-       }
-
        return mp;
 }
 
index 0cdef4107572cd3a2ada05ee63ff91ff90c1ed16..4cc0df6ccc4f4946791e97a26c145efd9f1b4862 100644 (file)
@@ -543,7 +543,6 @@ parseproto(
                        pip = ip;
                        mp->m_sb.sb_rootino = ip->i_ino;
                        libxfs_mod_sb(tp, XFS_SB_ROOTINO);
-                       mp->m_rootip = ip;
                        isroot = 1;
                } else {
                        libxfs_trans_ijoin(tp, pip, 0);
index 355708c99dd3408a2d1d955a722530a8c82c3dee..d37e9485989363c18a7f56f1fe4eeb15c8ab9005 100644 (file)
@@ -2582,6 +2582,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
        memset(XFS_BUF_PTR(buf), 0, sectorsize);
        libxfs_sb_to_disk((void *)XFS_BUF_PTR(buf), sbp, XFS_SB_ALL_BITS);
        libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
+       libxfs_purgebuf(buf);
 
        /*
         * If the data area is a file, then grow it out to its final size
@@ -2616,7 +2617,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
                (xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
                &sbp->sb_uuid, logversion, lsunit, XLOG_FMT);
 
-       mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 1);
+       mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 0);
        if (mp == NULL) {
                fprintf(stderr, _("%s: filesystem failed to initialize\n"),
                        progname);
@@ -2887,7 +2888,6 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
        /*
         * Allocate the root inode and anything else in the proto file.
         */
-       mp->m_rootip = NULL;
        parse_proto(mp, &fsx, &protostring);
 
        /*
index 2a3743827495e1cc8cb082afd8bc57e665e52033..5307acf61a479fdb67f4068b679830864fccd483 100644 (file)
@@ -856,8 +856,6 @@ mk_root_dir(xfs_mount_t *mp)
        ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
        ip->i_df.if_u1.if_extents = NULL;
 
-       mp->m_rootip = ip;
-
        /*
         * initialize the directory
         */