aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2009-09-02 20:17:36 -0400
committerJoel Becker <joel.becker@oracle.com>2010-05-10 14:50:10 -0400
commite4b963f10e9026c83419b5c25b93a0350413cf16 (patch)
treed162595c9f79626d040cb28c84e53fd8b7fe50ff
parent0467ae954d1843de65e7cf8f706f88fe65cd8418 (diff)
ocfs2: Wrap signal blocking in void functions.
ocfs2 sometimes needs to block signals around dlm operations, but it currently does it with sigprocmask(). Even worse, it's checking the error code of sigprocmask(). The in-kernel sigprocmask() can only error if you get the SIG_* argument wrong. We don't. Wrap the sigprocmask() calls with ocfs2_[un]block_signals(). These functions are void, but they will BUG() if somehow sigprocmask() returns an error. Signed-off-by: Joel Becker <joel.becker@oracle.com>
-rw-r--r--fs/ocfs2/inode.c14
-rw-r--r--fs/ocfs2/mmap.c48
-rw-r--r--fs/ocfs2/super.c20
-rw-r--r--fs/ocfs2/super.h7
4 files changed, 39 insertions, 50 deletions
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 9ee13f70da57..b7650ccd76d0 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -957,7 +957,7 @@ static void ocfs2_cleanup_delete_inode(struct inode *inode,
957void ocfs2_delete_inode(struct inode *inode) 957void ocfs2_delete_inode(struct inode *inode)
958{ 958{
959 int wipe, status; 959 int wipe, status;
960 sigset_t blocked, oldset; 960 sigset_t oldset;
961 struct buffer_head *di_bh = NULL; 961 struct buffer_head *di_bh = NULL;
962 962
963 mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); 963 mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
@@ -984,13 +984,7 @@ void ocfs2_delete_inode(struct inode *inode)
984 * messaging paths may return us -ERESTARTSYS. Which would 984 * messaging paths may return us -ERESTARTSYS. Which would
985 * cause us to exit early, resulting in inodes being orphaned 985 * cause us to exit early, resulting in inodes being orphaned
986 * forever. */ 986 * forever. */
987 sigfillset(&blocked); 987 ocfs2_block_signals(&oldset);
988 status = sigprocmask(SIG_BLOCK, &blocked, &oldset);
989 if (status < 0) {
990 mlog_errno(status);
991 ocfs2_cleanup_delete_inode(inode, 1);
992 goto bail;
993 }
994 988
995 /* 989 /*
996 * Synchronize us against ocfs2_get_dentry. We take this in 990 * Synchronize us against ocfs2_get_dentry. We take this in
@@ -1064,9 +1058,7 @@ bail_unlock_nfs_sync:
1064 ocfs2_nfs_sync_unlock(OCFS2_SB(inode->i_sb), 0); 1058 ocfs2_nfs_sync_unlock(OCFS2_SB(inode->i_sb), 0);
1065 1059
1066bail_unblock: 1060bail_unblock:
1067 status = sigprocmask(SIG_SETMASK, &oldset, NULL); 1061 ocfs2_unblock_signals(&oldset);
1068 if (status < 0)
1069 mlog_errno(status);
1070bail: 1062bail:
1071 clear_inode(inode); 1063 clear_inode(inode);
1072 mlog_exit_void(); 1064 mlog_exit_void();
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index 39737613424a..a61809f8eab5 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -42,44 +42,20 @@
42#include "file.h" 42#include "file.h"
43#include "inode.h" 43#include "inode.h"
44#include "mmap.h" 44#include "mmap.h"
45#include "super.h"
45 46
46static inline int ocfs2_vm_op_block_sigs(sigset_t *blocked, sigset_t *oldset)
47{
48 /* The best way to deal with signals in the vm path is
49 * to block them upfront, rather than allowing the
50 * locking paths to return -ERESTARTSYS. */
51 sigfillset(blocked);
52
53 /* We should technically never get a bad return value
54 * from sigprocmask */
55 return sigprocmask(SIG_BLOCK, blocked, oldset);
56}
57
58static inline int ocfs2_vm_op_unblock_sigs(sigset_t *oldset)
59{
60 return sigprocmask(SIG_SETMASK, oldset, NULL);
61}
62 47
63static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) 48static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf)
64{ 49{
65 sigset_t blocked, oldset; 50 sigset_t oldset;
66 int error, ret; 51 int ret;
67 52
68 mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff); 53 mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff);
69 54
70 error = ocfs2_vm_op_block_sigs(&blocked, &oldset); 55 ocfs2_block_signals(&oldset);
71 if (error < 0) {
72 mlog_errno(error);
73 ret = VM_FAULT_SIGBUS;
74 goto out;
75 }
76
77 ret = filemap_fault(area, vmf); 56 ret = filemap_fault(area, vmf);
57 ocfs2_unblock_signals(&oldset);
78 58
79 error = ocfs2_vm_op_unblock_sigs(&oldset);
80 if (error < 0)
81 mlog_errno(error);
82out:
83 mlog_exit_ptr(vmf->page); 59 mlog_exit_ptr(vmf->page);
84 return ret; 60 return ret;
85} 61}
@@ -159,14 +135,10 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
159 struct page *page = vmf->page; 135 struct page *page = vmf->page;
160 struct inode *inode = vma->vm_file->f_path.dentry->d_inode; 136 struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
161 struct buffer_head *di_bh = NULL; 137 struct buffer_head *di_bh = NULL;
162 sigset_t blocked, oldset; 138 sigset_t oldset;
163 int ret, ret2; 139 int ret;
164 140
165 ret = ocfs2_vm_op_block_sigs(&blocked, &oldset); 141 ocfs2_block_signals(&oldset);
166 if (ret < 0) {
167 mlog_errno(ret);
168 return ret;
169 }
170 142
171 /* 143 /*
172 * The cluster locks taken will block a truncate from another 144 * The cluster locks taken will block a truncate from another
@@ -194,9 +166,7 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
194 ocfs2_inode_unlock(inode, 1); 166 ocfs2_inode_unlock(inode, 1);
195 167
196out: 168out:
197 ret2 = ocfs2_vm_op_unblock_sigs(&oldset); 169 ocfs2_unblock_signals(&oldset);
198 if (ret2 < 0)
199 mlog_errno(ret2);
200 if (ret) 170 if (ret)
201 ret = VM_FAULT_SIGBUS; 171 ret = VM_FAULT_SIGBUS;
202 return ret; 172 return ret;
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 12c2203a62fe..cf6d87b57450 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -2560,5 +2560,25 @@ void __ocfs2_abort(struct super_block* sb,
2560 ocfs2_handle_error(sb); 2560 ocfs2_handle_error(sb);
2561} 2561}
2562 2562
2563/*
2564 * Void signal blockers, because in-kernel sigprocmask() only fails
2565 * when SIG_* is wrong.
2566 */
2567void ocfs2_block_signals(sigset_t *oldset)
2568{
2569 int rc;
2570 sigset_t blocked;
2571
2572 sigfillset(&blocked);
2573 rc = sigprocmask(SIG_BLOCK, &blocked, oldset);
2574 BUG_ON(rc);
2575}
2576
2577void ocfs2_unblock_signals(sigset_t *oldset)
2578{
2579 int rc = sigprocmask(SIG_SETMASK, oldset, NULL);
2580 BUG_ON(rc);
2581}
2582
2563module_init(ocfs2_init); 2583module_init(ocfs2_init);
2564module_exit(ocfs2_exit); 2584module_exit(ocfs2_exit);
diff --git a/fs/ocfs2/super.h b/fs/ocfs2/super.h
index 783f5270f2a1..40c7de084c10 100644
--- a/fs/ocfs2/super.h
+++ b/fs/ocfs2/super.h
@@ -45,4 +45,11 @@ void __ocfs2_abort(struct super_block *sb,
45 45
46#define ocfs2_abort(sb, fmt, args...) __ocfs2_abort(sb, __PRETTY_FUNCTION__, fmt, ##args) 46#define ocfs2_abort(sb, fmt, args...) __ocfs2_abort(sb, __PRETTY_FUNCTION__, fmt, ##args)
47 47
48/*
49 * Void signal blockers, because in-kernel sigprocmask() only fails
50 * when SIG_* is wrong.
51 */
52void ocfs2_block_signals(sigset_t *oldset);
53void ocfs2_unblock_signals(sigset_t *oldset);
54
48#endif /* OCFS2_SUPER_H */ 55#endif /* OCFS2_SUPER_H */