Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[cascardo/linux.git] / fs / gfs2 / glock.c
index a4ff7b5..4b73bd1 100644 (file)
@@ -572,17 +572,24 @@ static void delete_work_func(struct work_struct *work)
        struct inode *inode;
        u64 no_addr = gl->gl_name.ln_number;
 
+       /* If someone's using this glock to create a new dinode, the block must
+          have been freed by another node, then re-used, in which case our
+          iopen callback is too late after the fact. Ignore it. */
+       if (test_bit(GLF_INODE_CREATING, &gl->gl_flags))
+               goto out;
+
        ip = gl->gl_object;
        /* Note: Unsafe to dereference ip as we don't hold right refs/locks */
 
        if (ip)
-               inode = gfs2_ilookup(sdp->sd_vfs, no_addr, 1);
+               inode = gfs2_ilookup(sdp->sd_vfs, no_addr);
        else
                inode = gfs2_lookup_by_inum(sdp, no_addr, NULL, GFS2_BLKST_UNLINKED);
        if (inode && !IS_ERR(inode)) {
                d_prune_aliases(inode);
                iput(inode);
        }
+out:
        gfs2_glock_put(gl);
 }
 
@@ -1015,6 +1022,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
                handle_callback(gl, LM_ST_UNLOCKED, 0, false);
 
        list_del_init(&gh->gh_list);
+       clear_bit(HIF_HOLDER, &gh->gh_iflags);
        if (find_first_holder(gl) == NULL) {
                if (glops->go_unlock) {
                        GLOCK_BUG_ON(gl, test_and_set_bit(GLF_LOCK, &gl->gl_flags));
@@ -1905,7 +1913,7 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file)
                if (seq->buf)
                        seq->size = GFS2_SEQ_GOODSIZE;
                gi->gl = NULL;
-               ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
+               ret = rhashtable_walk_init(&gl_hash_table, &gi->hti, GFP_KERNEL);
        }
        return ret;
 }
@@ -1933,7 +1941,7 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file)
                if (seq->buf)
                        seq->size = GFS2_SEQ_GOODSIZE;
                gi->gl = NULL;
-               ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
+               ret = rhashtable_walk_init(&gl_hash_table, &gi->hti, GFP_KERNEL);
        }
        return ret;
 }