On Tue, Jul 10, 2018 at 6:02 AM Jan Kara <jack(a)suse.cz> wrote:
Audit tree code currently associates new fsnotify mark with each new
chunk. As chunk attached to an inode is replaced when new tag is added /
removed, we also need to remove old fsnotify mark and add a new one on
such occasion. This is cumbersome and makes locking rules somewhat
difficult to follow.
Fix these problems by allocating fsnotify mark independently of chunk
and keeping it all the time while there is some chunk attached to an
inode. Also add documentation about the locking rules so that things are
easier to follow.
Signed-off-by: Jan Kara <jack(a)suse.cz>
---
kernel/audit_tree.c | 163 +++++++++++++++++++++++++++-------------------------
1 file changed, 85 insertions(+), 78 deletions(-)
This is a really nice improvement, thanks!
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index aec9b27a20ff..40f61de77dd0 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -272,6 +273,20 @@ static struct audit_chunk *find_chunk(struct node *p)
return container_of(p, struct audit_chunk, owners[0]);
}
+static void replace_mark_chunk(struct fsnotify_mark *entry,
+ struct audit_chunk *chunk)
+{
+ struct audit_chunk *old;
+
+ assert_spin_locked(&hash_lock);
+ old = AUDIT_M(entry)->chunk;
+ AUDIT_M(entry)->chunk = chunk;
+ if (chunk)
+ chunk->mark = entry;
+ if (old)
+ old->mark = NULL;
Is it necessary that we check to see if chunk and old are non-NULL?
It seems like we would always want to set chunk->mark to entry and set
old->mark to NULL, yes?
@@ -321,29 +341,31 @@ static void untag_chunk(struct node *p)
mutex_lock(&entry->group->mark_mutex);
/*
- * mark_mutex protects mark from getting detached and thus also from
- * mark->connector->obj getting NULL.
+ * mark_mutex protects mark stabilizes chunk attached to the mark so we
+ * can check whether it didn't change while we've dropped hash_lock.
I think your new text could use some revision, the "protects mark
stabilizes chunk" is odd.
*/
- if (chunk->dead || !(entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) {
+ if (!(entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED) ||
+ AUDIT_M(entry)->chunk != chunk) {
mutex_unlock(&entry->group->mark_mutex);
if (new)
- fsnotify_put_mark(new->mark);
+ kfree(new);
Since we are just calling kfree() now we can do away with the "if (new)" check.
--
paul moore
www.paul-moore.com