]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - libxfs/init.c
xfs: fix transaction leak on remote attr set/remove failure
[thirdparty/xfsprogs-dev.git] / libxfs / init.c
index 302f088dde2ce5597e153ef343fbcb7cfef7d241..2f38997201152f81f578a65f712a03c81892e8df 100644 (file)
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <sys/stat.h>
@@ -43,9 +31,7 @@ int libxfs_bhash_size;                /* #buckets in bcache */
 
 int    use_xfs_buf_lock;       /* global flag: use xfs_buf_t locks for MT */
 
-static void manage_zones(int); /* setup global zones */
-
-kmem_zone_t    *xfs_inode_zone;
+static int manage_zones(int);  /* setup/teardown global zones */
 
 /*
  * dev_map - map open devices to fd.
@@ -374,29 +360,34 @@ done:
 /*
  * Initialize/destroy all of the zone allocators we use.
  */
-static void
+static int
 manage_zones(int release)
 {
        extern kmem_zone_t      *xfs_buf_zone;
        extern kmem_zone_t      *xfs_ili_zone;
+       extern kmem_zone_t      *xfs_inode_zone;
        extern kmem_zone_t      *xfs_ifork_zone;
        extern kmem_zone_t      *xfs_buf_item_zone;
        extern kmem_zone_t      *xfs_da_state_zone;
        extern kmem_zone_t      *xfs_btree_cur_zone;
        extern kmem_zone_t      *xfs_bmap_free_item_zone;
-       extern kmem_zone_t      *xfs_log_item_desc_zone;
+       extern kmem_zone_t      *xfs_trans_zone;
        extern void             xfs_dir_startup();
 
        if (release) {  /* free zone allocation */
-               kmem_free(xfs_buf_zone);
-               kmem_free(xfs_inode_zone);
-               kmem_free(xfs_ifork_zone);
-               kmem_free(xfs_buf_item_zone);
-               kmem_free(xfs_da_state_zone);
-               kmem_free(xfs_btree_cur_zone);
-               kmem_free(xfs_bmap_free_item_zone);
-               kmem_free(xfs_log_item_desc_zone);
-               return;
+               int     leaked = 0;
+
+               leaked += kmem_zone_destroy(xfs_buf_zone);
+               leaked += kmem_zone_destroy(xfs_ili_zone);
+               leaked += kmem_zone_destroy(xfs_inode_zone);
+               leaked += kmem_zone_destroy(xfs_ifork_zone);
+               leaked += kmem_zone_destroy(xfs_buf_item_zone);
+               leaked += kmem_zone_destroy(xfs_da_state_zone);
+               leaked += kmem_zone_destroy(xfs_btree_cur_zone);
+               leaked += kmem_zone_destroy(xfs_bmap_free_item_zone);
+               leaked += kmem_zone_destroy(xfs_trans_zone);
+
+               return leaked;
        }
        /* otherwise initialise zone allocation */
        xfs_buf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buffer");
@@ -413,9 +404,11 @@ manage_zones(int release)
        xfs_bmap_free_item_zone = kmem_zone_init(
                        sizeof(struct xfs_extent_free_item),
                        "xfs_bmap_free_item");
-       xfs_log_item_desc_zone = kmem_zone_init(
-                       sizeof(struct xfs_log_item_desc), "xfs_log_item_desc");
+       xfs_trans_zone = kmem_zone_init(
+                       sizeof(struct xfs_trans), "xfs_trans");
        xfs_dir_startup();
+
+       return 0;
 }
 
 /*
@@ -884,8 +877,15 @@ libxfs_umount(xfs_mount_t *mp)
 void
 libxfs_destroy(void)
 {
-       manage_zones(1);
+       int     leaked;
+
+       /* Free everything from the buffer cache before freeing buffer zone */
+       libxfs_bcache_purge();
+       libxfs_bcache_free();
        cache_destroy(libxfs_bcache);
+       leaked = manage_zones(1);
+       if (getenv("LIBXFS_LEAK_CHECK") && leaked)
+               exit(1);
 }
 
 int