diff options
author | Karel Zak | 2011-03-30 09:30:05 +0200 |
---|---|---|
committer | Karel Zak | 2011-03-30 09:30:05 +0200 |
commit | 5976114f628c96285c9b3f2cc55994f216afe6f2 (patch) | |
tree | 7ec6963afb34654f2f44810c31a04af1c413cc52 /shlibs | |
parent | docs: update TODO (diff) | |
download | kernel-qcow2-util-linux-5976114f628c96285c9b3f2cc55994f216afe6f2.tar.gz kernel-qcow2-util-linux-5976114f628c96285c9b3f2cc55994f216afe6f2.tar.xz kernel-qcow2-util-linux-5976114f628c96285c9b3f2cc55994f216afe6f2.zip |
libmount: block signals when writing to mtab
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs')
-rw-r--r-- | shlibs/mount/src/context.c | 26 | ||||
-rw-r--r-- | shlibs/mount/src/libmount.h.in | 1 | ||||
-rw-r--r-- | shlibs/mount/src/libmount.sym | 1 | ||||
-rw-r--r-- | shlibs/mount/src/lock.c | 43 | ||||
-rw-r--r-- | shlibs/mount/src/tab_update.c | 28 |
5 files changed, 73 insertions, 26 deletions
diff --git a/shlibs/mount/src/context.c b/shlibs/mount/src/context.c index dba49430d..f24e90ebb 100644 --- a/shlibs/mount/src/context.c +++ b/shlibs/mount/src/context.c @@ -794,13 +794,21 @@ struct libmnt_cache *mnt_context_get_cache(struct libmnt_context *cxt) * mnt_context_get_lock: * @cxt: mount context * - * The application that uses libmount context does not have to care about - * mtab locking, but with a small exceptions: the application has to be able to - * remove the lock file when interrupted by signal. It means that properly written - * mount(8)-like application has to call mnt_unlock_file() from a signal handler. + * The libmount applications don't have to care about mtab locking, but with a + * small exception: the application has to be able to remove the lock file when + * interrupted by signal or signals have to be ignored when the lock is locked. * - * This function returns NULL if mtab file is not writable or nolock or nomtab - * flags is enabled. + * The default behavior is to ignore all signals (except SIGALRM and SIGTRAP) + * when the lock is locked. If this behavior is unacceptable then use: + * + * lc = mnt_context_get_lock(cxt); + * if (lc) + * mnt_lock_block_signals(lc, FALSE); + * + * and don't forget to call mnt_unlock_file(lc) before exit. + * + * This function returns NULL if the lock is unnecessary (mtab file is not writable + * or /etc/mtab is symlink to /proc/mounts). * * Returns: pointer to lock struct or NULL. */ @@ -809,9 +817,11 @@ struct libmnt_lock *mnt_context_get_lock(struct libmnt_context *cxt) if (!cxt || (cxt->flags & MNT_FL_NOMTAB) || !cxt->mtab_writable) return NULL; - if (!cxt->lock && cxt->mtab_path) + if (!cxt->lock && cxt->mtab_path) { cxt->lock = mnt_new_lock(cxt->mtab_path, 0); - + if (cxt->lock) + mnt_lock_block_signals(cxt->lock, TRUE); + } return cxt->lock; } diff --git a/shlibs/mount/src/libmount.h.in b/shlibs/mount/src/libmount.h.in index c9d0ba8f4..d7e7a5172 100644 --- a/shlibs/mount/src/libmount.h.in +++ b/shlibs/mount/src/libmount.h.in @@ -195,6 +195,7 @@ extern struct libmnt_lock *mnt_new_lock(const char *datafile, pid_t id); extern void mnt_free_lock(struct libmnt_lock *ml); extern void mnt_unlock_file(struct libmnt_lock *ml); extern int mnt_lock_file(struct libmnt_lock *ml); +extern int mnt_lock_block_signals(struct libmnt_lock *ml, int enable); /* fs.c */ extern struct libmnt_fs *mnt_new_fs(void); diff --git a/shlibs/mount/src/libmount.sym b/shlibs/mount/src/libmount.sym index f8a5345b0..af6f7bf48 100644 --- a/shlibs/mount/src/libmount.sym +++ b/shlibs/mount/src/libmount.sym @@ -126,6 +126,7 @@ global: mnt_has_regular_mtab; mnt_init_debug; mnt_iter_get_direction; + mnt_lock_block_signals; mnt_lock_file; mnt_mangle; mnt_match_fstype; diff --git a/shlibs/mount/src/lock.c b/shlibs/mount/src/lock.c index 554915876..55dcf73b2 100644 --- a/shlibs/mount/src/lock.c +++ b/shlibs/mount/src/lock.c @@ -40,7 +40,11 @@ struct libmnt_lock { char *lockfile; /* path to lock file (e.g. /etc/mtab~) */ char *linkfile; /* path to link file (e.g. /etc/mtab~.<id>) */ int lockfile_fd; /* lock file descriptor */ - int locked; /* do we own the lock? */ + + int locked :1; /* do we own the lock? */ + int sigblock: 1; /* block signals when locked */ + + sigset_t oldsigmask; }; @@ -102,6 +106,24 @@ void mnt_free_lock(struct libmnt_lock *ml) free(ml); } +/** + * mnt_lock_block_signals: + * @ml: struct libmnt_lock handler + * @enable: TRUE/FALSE + * + * Block/unblock signals when the lock is locked, the signals are not blocked + * by default. + * + * Returns: <0 on error, 0 on success. + */ +int mnt_lock_block_signals(struct libmnt_lock *ml, int enable) +{ + if (!ml) + return -EINVAL; + ml->sigblock = enable; + return 0; +} + /* * Returns path to lockfile. */ @@ -254,6 +276,11 @@ void mnt_unlock_file(struct libmnt_lock *ml) ml->locked = 0; ml->lockfile_fd = -1; + + if (ml->sigblock) + sigprocmask(SIG_SETMASK, &ml->oldsigmask, NULL); + + ml->sigblock = 0; } /** @@ -337,6 +364,20 @@ int mnt_lock_file(struct libmnt_lock *ml) if (!linkfile) return -EINVAL; + if (ml->sigblock) { + /* + * Block all signals when locked, mnt_unlock_file() will + * restore the old mask. + */ + sigset_t sigs; + + sigemptyset(&ml->oldsigmask); + sigfillset(&sigs); + sigdelset(&sigs, SIGTRAP); + sigdelset(&sigs, SIGALRM); + sigprocmask(SIG_BLOCK, &sigs, &ml->oldsigmask); + } + i = open(linkfile, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); if (i < 0) { /* linkfile does not exist (as a file) and we cannot create it. diff --git a/shlibs/mount/src/tab_update.c b/shlibs/mount/src/tab_update.c index 9a56b6738..7cf166ba5 100644 --- a/shlibs/mount/src/tab_update.c +++ b/shlibs/mount/src/tab_update.c @@ -778,10 +778,15 @@ static int update_modify_options(struct libmnt_update *upd, struct libmnt_lock * /** * mnt_update_table: * @upd: update - * @lc: lock + * @lc: lock or NULL * * High-level API to update /etc/mtab (or private /dev/.mount/utab file). * + * The @lc lock is optional and will be created if necessary. Note that + * the automatically created lock blocks all signals. + * + * See also mnt_lock_block_signals() and mnt_context_get_lock(). + * * Returns: 0 on success, negative number on error. */ int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc) @@ -801,8 +806,11 @@ int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc) DBG(UPDATE, mnt_fs_print_debug(upd->fs, stderr)); } - if (!lc && !upd->userspace_only) + if (!lc && !upd->userspace_only) { lc = mnt_new_lock(upd->filename, 0); + if (lc) + mnt_lock_block_signals(lc, TRUE); + } if (!upd->fs && upd->target) rc = update_remove_entry(upd, lc); /* umount */ @@ -825,14 +833,6 @@ int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc) #ifdef TEST_PROGRAM -struct libmnt_lock *lock; - -static void lock_fallback(void) -{ - if (lock) - mnt_unlock_file(lock); -} - static int update(const char *target, struct libmnt_fs *fs, unsigned long mountflags) { int rc; @@ -858,13 +858,7 @@ static int update(const char *target, struct libmnt_fs *fs, unsigned long mountf /* [... here should be mount(2) call ...] */ - filename = mnt_update_get_filename(upd); - if (filename) { - lock = mnt_new_lock(filename, 0); - if (lock) - atexit(lock_fallback); - } - rc = mnt_update_table(upd, lock); + rc = mnt_update_table(upd, NULL); done: return rc; } |