From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: tytso@mit.edu, darrick.wong@oracle.com
Cc: linux-ext4@vger.kernel.org
Subject: [PATCH 34/54] libext2fs: support atexit cleanups
Date: Mon, 26 Jan 2015 23:39:15 -0800 [thread overview]
Message-ID: <20150127073915.13308.44734.stgit@birch.djwong.org> (raw)
In-Reply-To: <20150127073533.13308.44994.stgit@birch.djwong.org>
Use the atexit() function to provide a means for the library to clean
itself up on program exit. This will be used by the undo IO manager
to flush the undo file state to disk if the program should terminate
without closing the io channel, since most e2fsprogs clients will
simply exit() when they hit errors.
This won't help for signal termination; client programs must set
up signal handlers.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
lib/ext2fs/Makefile.in | 8 +++
lib/ext2fs/atexit.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/ext2fs/ext2fsP.h | 5 ++
lib/ext2fs/undo_io.c | 32 ++++++++++++--
4 files changed, 154 insertions(+), 3 deletions(-)
create mode 100644 lib/ext2fs/atexit.c
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index 2706bfa..4b64101 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -57,6 +57,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
alloc_sb.o \
alloc_stats.o \
alloc_tables.o \
+ atexit.o \
badblocks.o \
bb_inode.o \
bitmaps.o \
@@ -130,6 +131,7 @@ SRCS= ext2_err.c \
$(srcdir)/alloc_sb.c \
$(srcdir)/alloc_stats.c \
$(srcdir)/alloc_tables.c \
+ $(srcdir)/atexit.c \
$(srcdir)/badblocks.c \
$(srcdir)/bb_compat.c \
$(srcdir)/bb_inode.c \
@@ -615,6 +617,12 @@ alloc_tables.o: $(srcdir)/alloc_tables.c $(top_builddir)/lib/config.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/ext2fsP.h
+atexit.o: $(srcdir)/atexit.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/ext2fsP.h
badblocks.o: $(srcdir)/badblocks.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \
diff --git a/lib/ext2fs/atexit.c b/lib/ext2fs/atexit.c
new file mode 100644
index 0000000..5eba993
--- /dev/null
+++ b/lib/ext2fs/atexit.c
@@ -0,0 +1,112 @@
+/*
+ * atexit.c --- Clean things up when we exit normally.
+ *
+ * Copyright Oracle, 2014
+ * Author Darrick J. Wong <darrick.wong@oracle.com>
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Library
+ * General Public License, version 2.
+ * %End-Header%
+ */
+
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+
+#include "config.h"
+#include <stdlib.h>
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "ext2fsP.h"
+
+struct exit_data {
+ ext2_exit_fn func;
+ void *data;
+};
+
+static struct exit_data *items;
+static size_t nr_items;
+
+static void handle_exit(void)
+{
+ struct exit_data *ed;
+
+ for (ed = items + nr_items - 1; ed >= items; ed--) {
+ if (ed->func == NULL)
+ continue;
+ ed->func(ed->data);
+ }
+
+ ext2fs_free_mem(&items);
+ nr_items = 0;
+}
+
+/*
+ * Schedule a function to be called at (normal) program termination.
+ * If you want this to be called during a signal exit, you must capture
+ * the signal and call exit() yourself!
+ */
+errcode_t ext2fs_add_exit_fn(ext2_exit_fn func, void *data)
+{
+ struct exit_data *ed, *free_ed = NULL;
+ size_t x;
+ errcode_t ret;
+
+ if (func == NULL)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ for (x = 0, ed = items; x < nr_items; x++, ed++) {
+ if (ed->func == func && ed->data == data)
+ return EXT2_ET_FILE_EXISTS;
+ if (ed->func == NULL)
+ free_ed = ed;
+ }
+
+ if (free_ed) {
+ free_ed->func = func;
+ free_ed->data = data;
+ return 0;
+ }
+
+ if (nr_items == 0) {
+ ret = atexit(handle_exit);
+ if (ret)
+ return ret;
+ }
+
+ ret = ext2fs_resize_mem(0, (nr_items + 1) * sizeof(struct exit_data),
+ &items);
+ if (ret)
+ return ret;
+
+ items[nr_items].func = func;
+ items[nr_items].data = data;
+ nr_items++;
+
+ return 0;
+}
+
+/* Remove a function from the exit cleanup list. */
+errcode_t ext2fs_remove_exit_fn(ext2_exit_fn func, void *data)
+{
+ struct exit_data *ed;
+ size_t x;
+
+ if (func == NULL)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ for (x = 0, ed = items; x < nr_items; x++, ed++) {
+ if (ed->func == NULL)
+ return 0;
+ if (ed->func == func && ed->data == data) {
+ size_t sz = (nr_items - (x + 1)) *
+ sizeof(struct exit_data);
+ memmove(ed, ed + 1, sz);
+ memset(items + nr_items - 1, 0,
+ sizeof(struct exit_data));
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/ext2fs/ext2fsP.h b/lib/ext2fs/ext2fsP.h
index f8c61e6..8de9d33 100644
--- a/lib/ext2fs/ext2fsP.h
+++ b/lib/ext2fs/ext2fsP.h
@@ -169,3 +169,8 @@ extern int ext2fs_mem_is_zero(const char *mem, size_t len);
extern int ext2fs_file_block_offset_too_big(ext2_filsys fs,
struct ext2_inode *inode,
blk64_t offset);
+
+/* atexit support */
+typedef void (*ext2_exit_fn)(void *);
+errcode_t ext2fs_add_exit_fn(ext2_exit_fn fn, void *data);
+errcode_t ext2fs_remove_exit_fn(ext2_exit_fn fn, void *data);
diff --git a/lib/ext2fs/undo_io.c b/lib/ext2fs/undo_io.c
index f1c107a..df26e3e 100644
--- a/lib/ext2fs/undo_io.c
+++ b/lib/ext2fs/undo_io.c
@@ -41,6 +41,7 @@
#include "ext2_fs.h"
#include "ext2fs.h"
+#include "ext2fsP.h"
#ifdef __GNUC__
#define ATTR(x) __attribute__(x)
@@ -135,7 +136,7 @@ struct undo_private_data {
ext2fs_block_bitmap written_block_map;
struct struct_ext2_filsys fake_fs;
-
+ char *tdb_file;
struct undo_header hdr;
};
#define KEYS_PER_BLOCK(d) (((d)->tdb_data_size / sizeof(struct undo_key)) - 1)
@@ -662,6 +663,17 @@ out:
return retval;
}
+static void undo_atexit(void *p)
+{
+ struct undo_private_data *data = p;
+ errcode_t err;
+
+ err = write_undo_indexes(data);
+ io_channel_close(data->undo_file);
+
+ com_err(data->tdb_file, err, "while force-closing undo file");
+}
+
static errcode_t undo_open(const char *name, int flags, io_channel *channel)
{
io_channel io = NULL;
@@ -703,11 +715,16 @@ static errcode_t undo_open(const char *name, int flags, io_channel *channel)
if (retval)
goto cleanup;
- undo_fd = ext2fs_open_file(tdb_file, O_RDWR | O_CREAT, 0600);
+ data->tdb_file = strdup(tdb_file);
+ if (data->tdb_file == NULL)
+ goto cleanup;
+ undo_fd = ext2fs_open_file(data->tdb_file, O_RDWR | O_CREAT,
+ 0600);
if (undo_fd < 0)
goto cleanup;
- retval = undo_io_backing_manager->open(tdb_file, IO_FLAG_RW,
+ retval = undo_io_backing_manager->open(data->tdb_file,
+ IO_FLAG_RW,
&data->undo_file);
if (retval)
goto cleanup;
@@ -732,6 +749,9 @@ static errcode_t undo_open(const char *name, int flags, io_channel *channel)
if (retval)
goto cleanup;
}
+ retval = ext2fs_add_exit_fn(undo_atexit, data);
+ if (retval)
+ goto cleanup;
*channel = io;
if (undo_fd >= 0)
@@ -739,10 +759,13 @@ static errcode_t undo_open(const char *name, int flags, io_channel *channel)
return retval;
cleanup:
+ ext2fs_remove_exit_fn(undo_atexit, data);
if (undo_fd >= 0)
close(undo_fd);
if (data && data->undo_file)
io_channel_close(data->undo_file);
+ if (data && data->tdb_file)
+ free(data->tdb_file);
if (data && data->real)
io_channel_close(data->real);
if (data)
@@ -769,11 +792,14 @@ static errcode_t undo_close(io_channel channel)
err = write_undo_indexes(data);
if (data->real)
retval = io_channel_close(data->real);
+ if (data->tdb_file)
+ free(data->tdb_file);
if (data->undo_file)
io_channel_close(data->undo_file);
ext2fs_free_mem(&data->keyb);
if (data->written_block_map)
ext2fs_free_generic_bitmap(data->written_block_map);
+ ext2fs_remove_exit_fn(undo_atexit, data);
ext2fs_free_mem(&channel->private_data);
if (channel->name)
ext2fs_free_mem(&channel->name);
next prev parent reply other threads:[~2015-01-27 7:39 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-27 7:35 [PATCH 00/54] e2fsprogs January 2015 patchbomb Darrick J. Wong
2015-01-27 7:35 ` [PATCH 01/54] misc: fix minor testcase problems Darrick J. Wong
2015-01-27 15:55 ` Theodore Ts'o
2015-01-27 7:35 ` [PATCH 02/54] debugfs: document new commands Darrick J. Wong
2015-01-27 15:56 ` Theodore Ts'o
2015-01-27 7:35 ` [PATCH 03/54] debugfs: fix crash in ea_set argument handling Darrick J. Wong
2015-01-27 15:58 ` Theodore Ts'o
2015-01-27 7:35 ` [PATCH 04/54] libext2fs: initialize i_extra_isize when writing EAs Darrick J. Wong
2015-01-27 16:02 ` Theodore Ts'o
2015-01-27 7:36 ` [PATCH 05/54] libext2fs: avoid pointless EA block allocation Darrick J. Wong
2015-01-27 16:07 ` Theodore Ts'o
2015-01-27 19:26 ` Darrick J. Wong
2015-01-27 7:36 ` [PATCH 06/54] libext2fs: strengthen i_extra_isize checks when reading/writing xattrs Darrick J. Wong
2015-01-27 16:08 ` Theodore Ts'o
2015-01-27 7:36 ` [PATCH 07/54] libext2fs: fix tdb.c mmap leak Darrick J. Wong
2015-01-27 16:09 ` Theodore Ts'o
2015-01-27 7:36 ` [PATCH 08/54] resize2fs: fix regression test to not depend on ext4.ko being loaded Darrick J. Wong
2015-01-27 16:10 ` Theodore Ts'o
2015-01-27 7:36 ` [PATCH 09/54] tune2fs: disable csum verification before resizing inode Darrick J. Wong
2015-01-27 16:11 ` Theodore Ts'o
2015-01-27 7:36 ` [PATCH 10/54] tune2fs: abort when trying to enable/disable metadata_csum on mounted fs Darrick J. Wong
2015-01-27 16:26 ` Theodore Ts'o
2015-01-27 7:36 ` [PATCH 11/54] tune2fs: call out to resize2fs for 64bit conversion Darrick J. Wong
2015-01-27 16:31 ` Theodore Ts'o
2015-01-27 7:36 ` [PATCH 12/54] e2fsck: clear i_block[] when there are too many bad mappings on a special inode Darrick J. Wong
2015-01-27 16:32 ` Theodore Ts'o
2015-01-27 7:36 ` [PATCH 13/54] e2fsck: on read error, don't rewrite blocks past the end of the fs Darrick J. Wong
2015-01-27 17:35 ` Theodore Ts'o
2015-01-28 23:35 ` Darrick J. Wong
2015-01-27 7:37 ` [PATCH 14/54] e2fsck: fix the journal recreation message Darrick J. Wong
2015-01-27 18:02 ` Theodore Ts'o
2015-01-27 19:37 ` Darrick J. Wong
2015-01-27 7:37 ` [PATCH 15/54] e2fsck: handle multiple *ind block collisions with critical metadata Darrick J. Wong
2015-01-28 13:52 ` Theodore Ts'o
2015-01-27 7:37 ` [PATCH 16/54] e2fsck: decrement bad count _after_ remapping a duplicate block Darrick J. Wong
2015-01-28 13:58 ` Theodore Ts'o
2015-01-27 7:37 ` [PATCH 17/54] e2fsck: inspect inline dir data as two directory blocks Darrick J. Wong
2015-01-28 15:16 ` Theodore Ts'o
2015-01-27 7:37 ` [PATCH 18/54] e2fsck: improve the inline directory detector Darrick J. Wong
2015-01-28 16:38 ` Theodore Ts'o
2015-01-27 7:37 ` [PATCH 19/54] e2fsck: salvage under-sized dirents by removing them Darrick J. Wong
2015-02-16 15:40 ` Theodore Ts'o
2015-01-27 7:37 ` [PATCH 20/54] e2fsck: add a 'yes to all' response in interactive mode Darrick J. Wong
2015-03-29 2:54 ` Theodore Ts'o
2015-01-27 7:37 ` [PATCH 21/54] libext2fs: zero blocks via FALLOC_FL_ZERO_RANGE in ext2fs_zero_blocks Darrick J. Wong
2015-03-29 3:46 ` Theodore Ts'o
2015-01-27 7:37 ` [PATCH 22/54] libext2fs: ext2fs_new_block2() should call alloc_block hook Darrick J. Wong
2015-03-29 3:08 ` Theodore Ts'o
2015-01-27 7:38 ` [PATCH 23/54] libext2fs: Support readonly filesystem images Darrick J. Wong
2015-03-19 21:32 ` [PATCH v2 " Darrick J. Wong
2015-03-29 3:42 ` Theodore Ts'o
2015-01-27 7:38 ` [PATCH 24/54] libext2fs/e2fsck: provide routines to read-ahead metadata Darrick J. Wong
2015-01-27 7:38 ` [PATCH 25/54] e2fsck: read-ahead metadata during passes 1, 2, and 4 Darrick J. Wong
2015-01-27 7:38 ` [PATCH 26/54] e2fsck: track directories to be rehashed with a bitmap Darrick J. Wong
2015-01-27 7:38 ` [PATCH 27/54] e2fsck: rebuild sparse extent trees/convert non-extent ext3 files Darrick J. Wong
2015-03-19 21:42 ` [PATCH v4 " Darrick J. Wong
2015-01-27 7:38 ` [PATCH 28/54] tests: verify proper rebuilding of sparse extent trees and block map file conversion Darrick J. Wong
2015-01-27 7:38 ` [PATCH 29/54] undo-io: add new calls to and speed up the undo io manager Darrick J. Wong
2015-01-27 7:38 ` [PATCH 30/54] undo-io: be more flexible about setting block size Darrick J. Wong
2015-01-27 7:38 ` [PATCH 31/54] undo-io: use a bitmap to track what we've already written Darrick J. Wong
2015-01-27 7:39 ` [PATCH 32/54] e2undo: fix memory leaks and tweak the error messages somewhat Darrick J. Wong
2015-01-27 7:39 ` [PATCH 33/54] e2undo: ditch tdb file, write everything to a flat file Darrick J. Wong
2015-01-27 7:39 ` Darrick J. Wong [this message]
2015-01-27 7:39 ` [PATCH 35/54] e2fsck: optionally create an undo file Darrick J. Wong
2015-01-27 7:39 ` [PATCH 36/54] resize2fs: optionally create " Darrick J. Wong
2015-01-27 7:39 ` [PATCH 37/54] tune2fs: " Darrick J. Wong
2015-01-27 7:39 ` [PATCH 38/54] mke2fs: " Darrick J. Wong
2015-01-27 7:39 ` [PATCH 39/54] debugfs: " Darrick J. Wong
2015-01-27 7:39 ` [PATCH 40/54] tests: test undo file creation in e2fsck/resize2fs/tune2fs/mke2fs Darrick J. Wong
2015-01-27 7:40 ` [PATCH 41/54] tests: test various features of the new e2undo format Darrick J. Wong
2015-01-27 7:40 ` [PATCH 42/54] copy-in: create hardlinks with the correct directory filetype Darrick J. Wong
2015-01-27 7:40 ` [PATCH 43/54] copy-in: for files, only iterate file blocks that are mapped Darrick J. Wong
2015-01-27 7:40 ` [PATCH 44/54] copyin: fix error handling Darrick J. Wong
2015-01-27 7:40 ` [PATCH 45/54] mke2fs: add simple tests and re-alphabetize mke2fs manpage options Darrick J. Wong
2015-01-27 7:40 ` [PATCH 46/54] contrib: script to create minified ext4 image from a directory Darrick J. Wong
2015-01-27 7:40 ` [PATCH 47/54] libext2fs: support allocating uninit blocks in bmap2() Darrick J. Wong
2015-01-27 7:40 ` [PATCH 48/54] libext2fs: find/alloc a range of empty blocks Darrick J. Wong
2015-01-27 7:40 ` [PATCH 49/54] libext2fs: add new hooks to support large allocations Darrick J. Wong
2015-01-27 7:41 ` [PATCH 50/54] libext2fs: implement fallocate Darrick J. Wong
2015-01-27 7:41 ` [PATCH 51/54] libext2fs: use fallocate for creating journals and hugefiles Darrick J. Wong
2015-01-27 7:41 ` [PATCH 52/54] debugfs: implement fallocate Darrick J. Wong
2015-01-27 7:41 ` [PATCH 53/54] tests: test debugfs punch command Darrick J. Wong
2015-03-19 21:44 ` [PATCH 55/54] e2fsck: actually fix inline_data flags problems when user says to do so Darrick J. Wong
2015-03-29 4:05 ` Theodore Ts'o
2015-03-19 21:45 ` [PATCH 56/54] libext2fs: zero hash in ibody extended attributes Darrick J. Wong
2015-03-29 4:13 ` Theodore Ts'o
2015-03-19 21:47 ` [PATCH 57/54] e2fsck: convert block-mapped files to extents on bigalloc fs Darrick J. Wong
2015-03-19 23:54 ` [PATCH 58/54] e2fsck: turn inline data symlink into a fast symlink when possible Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150127073915.13308.44734.stgit@birch.djwong.org \
--to=darrick.wong@oracle.com \
--cc=linux-ext4@vger.kernel.org \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).