}
 EXPORT_SYMBOL_GPL(get_inotify_watch);
 
+int pin_inotify_watch(struct inotify_watch *watch)
+{
+       struct super_block *sb = watch->inode->i_sb;
+       spin_lock(&sb_lock);
+       if (sb->s_count >= S_BIAS) {
+               atomic_inc(&sb->s_active);
+               spin_unlock(&sb_lock);
+               atomic_inc(&watch->count);
+               return 1;
+       }
+       spin_unlock(&sb_lock);
+       return 0;
+}
+
 /**
  * put_inotify_watch - decrements the ref count on a given watch.  cleans up
  * watch references if the count reaches zero.  inotify_watch is freed by
 }
 EXPORT_SYMBOL_GPL(put_inotify_watch);
 
+void unpin_inotify_watch(struct inotify_watch *watch)
+{
+       struct super_block *sb = watch->inode->i_sb;
+       put_inotify_watch(watch);
+       deactivate_super(sb);
+}
+
 /*
  * inotify_handle_get_wd - returns the next WD for use by the given handle
  *
 }
 EXPORT_SYMBOL_GPL(inotify_init_watch);
 
+/*
+ * Watch removals suck violently.  To kick the watch out we need (in this
+ * order) inode->inotify_mutex and ih->mutex.  That's fine if we have
+ * a hold on inode; however, for all other cases we need to make damn sure
+ * we don't race with umount.  We can *NOT* just grab a reference to a
+ * watch - inotify_unmount_inodes() will happily sail past it and we'll end
+ * with reference to inode potentially outliving its superblock.  Ideally
+ * we just want to grab an active reference to superblock if we can; that
+ * will make sure we won't go into inotify_umount_inodes() until we are
+ * done.  Cleanup is just deactivate_super().  However, that leaves a messy
+ * case - what if we *are* racing with umount() and active references to
+ * superblock can't be acquired anymore?  We can bump ->s_count, grab
+ * ->s_umount, which will almost certainly wait until the superblock is shut
+ * down and the watch in question is pining for fjords.  That's fine, but
+ * there is a problem - we might have hit the window between ->s_active
+ * getting to 0 / ->s_count - below S_BIAS (i.e. the moment when superblock
+ * is past the point of no return and is heading for shutdown) and the
+ * moment when deactivate_super() acquires ->s_umount.  We could just do
+ * drop_super() yield() and retry, but that's rather antisocial and this
+ * stuff is luser-triggerable.  OTOH, having grabbed ->s_umount and having
+ * found that we'd got there first (i.e. that ->s_root is non-NULL) we know
+ * that we won't race with inotify_umount_inodes().  So we could grab a
+ * reference to watch and do the rest as above, just with drop_super() instead
+ * of deactivate_super(), right?  Wrong.  We had to drop ih->mutex before we
+ * could grab ->s_umount.  So the watch could've been gone already.
+ *
+ * That still can be dealt with - we need to save watch->wd, do idr_find()
+ * and compare its result with our pointer.  If they match, we either have
+ * the damn thing still alive or we'd lost not one but two races at once,
+ * the watch had been killed and a new one got created with the same ->wd
+ * at the same address.  That couldn't have happened in inotify_destroy(),
+ * but inotify_rm_wd() could run into that.  Still, "new one got created"
+ * is not a problem - we have every right to kill it or leave it alone,
+ * whatever's more convenient.
+ *
+ * So we can use idr_find(...) == watch && watch->inode->i_sb == sb as
+ * "grab it and kill it" check.  If it's been our original watch, we are
+ * fine, if it's a newcomer - nevermind, just pretend that we'd won the
+ * race and kill the fscker anyway; we are safe since we know that its
+ * superblock won't be going away.
+ *
+ * And yes, this is far beyond mere "not very pretty"; so's the entire
+ * concept of inotify to start with.
+ */
+
+/**
+ * pin_to_kill - pin the watch down for removal
+ * @ih: inotify handle
+ * @watch: watch to kill
+ *
+ * Called with ih->mutex held, drops it.  Possible return values:
+ * 0 - nothing to do, it has died
+ * 1 - remove it, drop the reference and deactivate_super()
+ * 2 - remove it, drop the reference and drop_super(); we tried hard to avoid
+ * that variant, since it involved a lot of PITA, but that's the best that
+ * could've been done.
+ */
+static int pin_to_kill(struct inotify_handle *ih, struct inotify_watch *watch)
+{
+       struct super_block *sb = watch->inode->i_sb;
+       s32 wd = watch->wd;
+
+       spin_lock(&sb_lock);
+       if (sb->s_count >= S_BIAS) {
+               atomic_inc(&sb->s_active);
+               spin_unlock(&sb_lock);
+               get_inotify_watch(watch);
+               mutex_unlock(&ih->mutex);
+               return 1;       /* the best outcome */
+       }
+       sb->s_count++;
+       spin_unlock(&sb_lock);
+       mutex_unlock(&ih->mutex); /* can't grab ->s_umount under it */
+       down_read(&sb->s_umount);
+       if (likely(!sb->s_root)) {
+               /* fs is already shut down; the watch is dead */
+               drop_super(sb);
+               return 0;
+       }
+       /* raced with the final deactivate_super() */
+       mutex_lock(&ih->mutex);
+       if (idr_find(&ih->idr, wd) != watch || watch->inode->i_sb != sb) {
+               /* the watch is dead */
+               mutex_unlock(&ih->mutex);
+               drop_super(sb);
+               return 0;
+       }
+       /* still alive or freed and reused with the same sb and wd; kill */
+       get_inotify_watch(watch);
+       mutex_unlock(&ih->mutex);
+       return 2;
+}
+
+static void unpin_and_kill(struct inotify_watch *watch, int how)
+{
+       struct super_block *sb = watch->inode->i_sb;
+       put_inotify_watch(watch);
+       switch (how) {
+       case 1:
+               deactivate_super(sb);
+               break;
+       case 2:
+               drop_super(sb);
+       }
+}
+
 /**
  * inotify_destroy - clean up and destroy an inotify instance
  * @ih: inotify handle
         * pretty.  We cannot do a simple iteration over the list, because we
         * do not know the inode until we iterate to the watch.  But we need to
         * hold inode->inotify_mutex before ih->mutex.  The following works.
+        *
+        * AV: it had to become even uglier to start working ;-/
         */
        while (1) {
                struct inotify_watch *watch;
                struct list_head *watches;
+               struct super_block *sb;
                struct inode *inode;
+               int how;
 
                mutex_lock(&ih->mutex);
                watches = &ih->watches;
                        break;
                }
                watch = list_first_entry(watches, struct inotify_watch, h_list);
-               get_inotify_watch(watch);
-               mutex_unlock(&ih->mutex);
+               sb = watch->inode->i_sb;
+               how = pin_to_kill(ih, watch);
+               if (!how)
+                       continue;
 
                inode = watch->inode;
                mutex_lock(&inode->inotify_mutex);
 
                mutex_unlock(&ih->mutex);
                mutex_unlock(&inode->inotify_mutex);
-               put_inotify_watch(watch);
+               unpin_and_kill(watch, how);
        }
 
        /* free this handle: the put matching the get in inotify_init() */
 int inotify_rm_wd(struct inotify_handle *ih, u32 wd)
 {
        struct inotify_watch *watch;
+       struct super_block *sb;
        struct inode *inode;
+       int how;
 
        mutex_lock(&ih->mutex);
        watch = idr_find(&ih->idr, wd);
                mutex_unlock(&ih->mutex);
                return -EINVAL;
        }
-       get_inotify_watch(watch);
+       sb = watch->inode->i_sb;
+       how = pin_to_kill(ih, watch);
+       if (!how)
+               return 0;
+
        inode = watch->inode;
-       mutex_unlock(&ih->mutex);
 
        mutex_lock(&inode->inotify_mutex);
        mutex_lock(&ih->mutex);
 
        mutex_unlock(&ih->mutex);
        mutex_unlock(&inode->inotify_mutex);
-       put_inotify_watch(watch);
+       unpin_and_kill(watch, how);
 
        return 0;
 }
 
        struct list_head trees;         /* with root here */
        int dead;
        int count;
+       atomic_long_t refs;
        struct rcu_head head;
        struct node {
                struct list_head list;
  * tree is refcounted; one reference for "some rules on rules_list refer to
  * it", one for each chunk with pointer to it.
  *
- * chunk is refcounted by embedded inotify_watch.
+ * chunk is refcounted by embedded inotify_watch + .refs (non-zero refcount
+ * of watch contributes 1 to .refs).
  *
  * node.index allows to get from node.list to containing chunk.
  * MSB of that sucker is stolen to mark taggings that we might have to
        INIT_LIST_HEAD(&chunk->hash);
        INIT_LIST_HEAD(&chunk->trees);
        chunk->count = count;
+       atomic_long_set(&chunk->refs, 1);
        for (i = 0; i < count; i++) {
                INIT_LIST_HEAD(&chunk->owners[i].list);
                chunk->owners[i].index = i;
        return chunk;
 }
 
-static void __free_chunk(struct rcu_head *rcu)
+static void free_chunk(struct audit_chunk *chunk)
 {
-       struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head);
        int i;
 
        for (i = 0; i < chunk->count; i++) {
        kfree(chunk);
 }
 
-static inline void free_chunk(struct audit_chunk *chunk)
+void audit_put_chunk(struct audit_chunk *chunk)
 {
-       call_rcu(&chunk->head, __free_chunk);
+       if (atomic_long_dec_and_test(&chunk->refs))
+               free_chunk(chunk);
 }
 
-void audit_put_chunk(struct audit_chunk *chunk)
+static void __put_chunk(struct rcu_head *rcu)
 {
-       put_inotify_watch(&chunk->watch);
+       struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head);
+       audit_put_chunk(chunk);
 }
 
 enum {HASH_SIZE = 128};
 
        list_for_each_entry_rcu(p, list, hash) {
                if (p->watch.inode == inode) {
-                       get_inotify_watch(&p->watch);
+                       atomic_long_inc(&p->refs);
                        return p;
                }
        }
 
 /* tagging and untagging inodes with trees */
 
-static void untag_chunk(struct audit_chunk *chunk, struct node *p)
+static struct audit_chunk *find_chunk(struct node *p)
+{
+       int index = p->index & ~(1U<<31);
+       p -= index;
+       return container_of(p, struct audit_chunk, owners[0]);
+}
+
+static void untag_chunk(struct node *p)
 {
+       struct audit_chunk *chunk = find_chunk(p);
        struct audit_chunk *new;
        struct audit_tree *owner;
        int size = chunk->count - 1;
        int i, j;
 
+       if (!pin_inotify_watch(&chunk->watch)) {
+               /*
+                * Filesystem is shutting down; all watches are getting
+                * evicted, just take it off the node list for this
+                * tree and let the eviction logics take care of the
+                * rest.
+                */
+               owner = p->owner;
+               if (owner->root == chunk) {
+                       list_del_init(&owner->same_root);
+                       owner->root = NULL;
+               }
+               list_del_init(&p->list);
+               p->owner = NULL;
+               put_tree(owner);
+               return;
+       }
+
+       spin_unlock(&hash_lock);
+
+       /*
+        * pin_inotify_watch() succeeded, so the watch won't go away
+        * from under us.
+        */
        mutex_lock(&chunk->watch.inode->inotify_mutex);
        if (chunk->dead) {
                mutex_unlock(&chunk->watch.inode->inotify_mutex);
-               return;
+               goto out;
        }
 
        owner = p->owner;
                inotify_evict_watch(&chunk->watch);
                mutex_unlock(&chunk->watch.inode->inotify_mutex);
                put_inotify_watch(&chunk->watch);
-               return;
+               goto out;
        }
 
        new = alloc_chunk(size);
        inotify_evict_watch(&chunk->watch);
        mutex_unlock(&chunk->watch.inode->inotify_mutex);
        put_inotify_watch(&chunk->watch);
-       return;
+       goto out;
 
 Fallback:
        // do the best we can
        put_tree(owner);
        spin_unlock(&hash_lock);
        mutex_unlock(&chunk->watch.inode->inotify_mutex);
+out:
+       unpin_inotify_watch(&chunk->watch);
+       spin_lock(&hash_lock);
 }
 
 static int create_chunk(struct inode *inode, struct audit_tree *tree)
        return 0;
 }
 
-static struct audit_chunk *find_chunk(struct node *p)
-{
-       int index = p->index & ~(1U<<31);
-       p -= index;
-       return container_of(p, struct audit_chunk, owners[0]);
-}
-
 static void kill_rules(struct audit_tree *tree)
 {
        struct audit_krule *rule, *next;
        spin_lock(&hash_lock);
        while (!list_empty(&victim->chunks)) {
                struct node *p;
-               struct audit_chunk *chunk;
 
                p = list_entry(victim->chunks.next, struct node, list);
-               chunk = find_chunk(p);
-               get_inotify_watch(&chunk->watch);
-               spin_unlock(&hash_lock);
-
-               untag_chunk(chunk, p);
 
-               put_inotify_watch(&chunk->watch);
-               spin_lock(&hash_lock);
+               untag_chunk(p);
        }
        spin_unlock(&hash_lock);
        put_tree(victim);
 
        while (!list_empty(&tree->chunks)) {
                struct node *node;
-               struct audit_chunk *chunk;
 
                node = list_entry(tree->chunks.next, struct node, list);
 
                if (!(node->index & (1U<<31)))
                        break;
 
-               chunk = find_chunk(node);
-               get_inotify_watch(&chunk->watch);
-               spin_unlock(&hash_lock);
-
-               untag_chunk(chunk, node);
-
-               put_inotify_watch(&chunk->watch);
-               spin_lock(&hash_lock);
+               untag_chunk(node);
        }
        if (!tree->root && !tree->goner) {
                tree->goner = 1;
 static void destroy_watch(struct inotify_watch *watch)
 {
        struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch);
-       free_chunk(chunk);
+       call_rcu(&chunk->head, __put_chunk);
 }
 
 static const struct inotify_operations rtree_inotify_ops = {