exofs: Remove inode->i_count manipulation in exofs_new_inode
Boaz Harrosh [Sat, 16 Oct 2010 08:14:01 +0000 (19:14 +1100)]
exofs_new_inode() was incrementing the inode->i_count and
decrementing it in create_done(), in a bad attempt to make sure
the inode will still be there when the asynchronous create_done()
finally arrives. This was very stupid because iput() was not called,
and if it was actually needed, it would leak the inode.

However all this is not needed, because at exofs_evict_inode()
we already wait for create_done() by waiting for the
object_created event. Therefore remove the superfluous ref counting
and just Thicken the comment at exofs_evict_inode() a bit.

While at it change places that open coded wait_obj_created()
to call the already available wrapper.

CC: Dave Chinner <dchinner@redhat.com>
CC: Christoph Hellwig <hch@lst.de>
CC: Nick Piggin <npiggin@kernel.dk>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>

fs/exofs/inode.c

index f5f8ce0..4268542 100644 (file)
@@ -1067,8 +1067,10 @@ bad_inode:
 int __exofs_wait_obj_created(struct exofs_i_info *oi)
 {
        if (!obj_created(oi)) {
+               EXOFS_DBGMSG("!obj_created\n");
                BUG_ON(!obj_2bcreated(oi));
                wait_event(oi->i_wq, obj_created(oi));
+               EXOFS_DBGMSG("wait_event done\n");
        }
        return unlikely(is_bad_inode(&oi->vfs_inode)) ? -EIO : 0;
 }
@@ -1102,7 +1104,6 @@ static void create_done(struct exofs_io_state *ios, void *p)
 
        set_obj_created(oi);
 
-       atomic_dec(&inode->i_count);
        wake_up(&oi->i_wq);
 }
 
@@ -1153,17 +1154,11 @@ struct inode *exofs_new_inode(struct inode *dir, int mode)
        ios->obj.id = exofs_oi_objno(oi);
        exofs_make_credential(oi->i_cred, &ios->obj);
 
-       /* increment the refcount so that the inode will still be around when we
-        * reach the callback
-        */
-       atomic_inc(&inode->i_count);
-
        ios->done = create_done;
        ios->private = inode;
        ios->cred = oi->i_cred;
        ret = exofs_sbi_create(ios);
        if (ret) {
-               atomic_dec(&inode->i_count);
                exofs_put_io_state(ios);
                return ERR_PTR(ret);
        }
@@ -1253,12 +1248,7 @@ static int exofs_update_inode(struct inode *inode, int do_sync)
        ios->out_attr_len = 1;
        ios->out_attr = &attr;
 
-       if (!obj_created(oi)) {
-               EXOFS_DBGMSG("!obj_created\n");
-               BUG_ON(!obj_2bcreated(oi));
-               wait_event(oi->i_wq, obj_created(oi));
-               EXOFS_DBGMSG("wait_event done\n");
-       }
+       wait_obj_created(oi);
 
        if (!do_sync) {
                args->sbi = sbi;
@@ -1321,12 +1311,12 @@ void exofs_evict_inode(struct inode *inode)
        inode->i_size = 0;
        end_writeback(inode);
 
-       /* if we are deleting an obj that hasn't been created yet, wait */
-       if (!obj_created(oi)) {
-               BUG_ON(!obj_2bcreated(oi));
-               wait_event(oi->i_wq, obj_created(oi));
-               /* ignore the error attempt a remove anyway */
-       }
+       /* if we are deleting an obj that hasn't been created yet, wait.
+        * This also makes sure that create_done cannot be called with an
+        * already evicted inode.
+        */
+       wait_obj_created(oi);
+       /* ignore the error, attempt a remove anyway */
 
        /* Now Remove the OSD objects */
        ret = exofs_get_io_state(&sbi->layout, &ios);