aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/fs.h7
-rw-r--r--kernel/acct.c7
2 files changed, 13 insertions, 1 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e8cd6b83967..b5a24ba83b6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2227,6 +2227,13 @@ static inline void file_start_write(struct file *file)
__sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
}
+static inline bool file_start_write_trylock(struct file *file)
+{
+ if (!S_ISREG(file_inode(file)->i_mode))
+ return true;
+ return __sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, false);
+}
+
static inline void file_end_write(struct file *file)
{
if (!S_ISREG(file_inode(file)->i_mode))
diff --git a/kernel/acct.c b/kernel/acct.c
index 85389fe2abd..8d6e145138b 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -540,10 +540,15 @@ static void do_acct_process(struct bsd_acct_struct *acct,
ac.ac_swaps = encode_comp_t(0);
/*
+ * Get freeze protection. If the fs is frozen, just skip the write
+ * as we could deadlock the system otherwise.
+ */
+ if (!file_start_write_trylock(file))
+ goto out;
+ /*
* Kernel segment override to datasegment and write it
* to the accounting file.
*/
- file_start_write(file);
fs = get_fs();
set_fs(KERNEL_DS);
/*