Clones an existing reference to inode; caller must already hold one.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
                kfree(st);
        } else {
                /* Caching disabled. No need to get upto date stat info.
-                * This dentry will be released immediately. So, just i_count++
+                * This dentry will be released immediately. So, just hold the
+                * inode
                 */
-               atomic_inc(&old_dentry->d_inode->i_count);
+               ihold(old_dentry->d_inode);
        }
 
        dentry->d_op = old_dentry->d_op;
 
                affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
                mark_buffer_dirty_inode(inode_bh, inode);
                inode->i_nlink = 2;
-               atomic_inc(&inode->i_count);
+               ihold(inode);
        }
        affs_fix_checksum(sb, bh);
        mark_buffer_dirty_inode(bh, inode);
 
        if (ret < 0)
                goto link_error;
 
-       atomic_inc(&vnode->vfs_inode.i_count);
+       ihold(&vnode->vfs_inode);
        d_instantiate(dentry, &vnode->vfs_inode);
        key_put(key);
        _leave(" = 0");
 
         *
         * When we're called, we always have a reference
         * on the file, so we must always have a reference
-        * on the inode, so igrab must always just
-        * bump the count and move on.
+        * on the inode, so ihold() is safe here.
         */
-       atomic_inc(&mapping->host->i_count);
+       ihold(mapping->host);
        abe->mapping = mapping;
        hlist_add_head(&abe->list, &batch_hash[bucket]);
        return;
 
        path.mnt = mntget(anon_inode_mnt);
        /*
         * We know the anon_inode inode count is always greater than zero,
-        * so we can avoid doing an igrab() and we can use an open-coded
-        * atomic_inc().
+        * so ihold() is safe.
         */
-       atomic_inc(&anon_inode_inode->i_count);
+       ihold(anon_inode_inode);
 
        path.dentry->d_op = &anon_inodefs_dentry_operations;
        d_instantiate(path.dentry, anon_inode_inode);
 
        inc_nlink(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        d_instantiate(new, inode);
        mutex_unlock(&info->bfs_lock);
        return 0;
 
  */
 struct block_device *bdgrab(struct block_device *bdev)
 {
-       atomic_inc(&bdev->bd_inode->i_count);
+       ihold(bdev->bd_inode);
        return bdev;
 }
 
        spin_lock(&bdev_lock);
        bdev = inode->i_bdev;
        if (bdev) {
-               atomic_inc(&bdev->bd_inode->i_count);
+               ihold(bdev->bd_inode);
                spin_unlock(&bdev_lock);
                return bdev;
        }
                spin_lock(&bdev_lock);
                if (!inode->i_bdev) {
                        /*
-                        * We take an additional bd_inode->i_count for inode,
+                        * We take an additional reference to bd_inode,
                         * and it's released in clear_inode() of inode.
                         * So, we can access it via ->i_mapping always
                         * without igrab().
                         */
-                       atomic_inc(&bdev->bd_inode->i_count);
+                       ihold(bdev->bd_inode);
                        inode->i_bdev = bdev;
                        inode->i_mapping = bdev->bd_inode->i_mapping;
                        list_add(&inode->i_devices, &bdev->bd_inodes);
 
        }
 
        btrfs_set_trans_block_group(trans, dir);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
 
        err = btrfs_add_nondir(trans, dentry, inode, 1, index);
 
 
        }
 
        coda_dir_update_mtime(dir_inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        d_instantiate(de, inode);
        inc_nlink(inode);
        return 0;
 
 
        inode->i_ctime = CURRENT_TIME;
        inode_inc_link_count(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
 
        return exofs_add_nondir(dentry, inode);
 }
 
 
        inode->i_ctime = CURRENT_TIME_SEC;
        inode_inc_link_count(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
 
        err = ext2_add_link(dentry, inode);
        if (!err) {
 
 
        inode->i_ctime = CURRENT_TIME_SEC;
        inc_nlink(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
 
        err = ext3_add_entry(handle, dentry, inode);
        if (!err) {
 
 
        inode->i_ctime = ext4_current_time(inode);
        ext4_inc_count(handle, inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
 
        err = ext4_add_entry(handle, dentry, inode);
        if (!err) {
 
        gfs2_holder_uninit(ghs);
        gfs2_holder_uninit(ghs + 1);
        if (!error) {
-               atomic_inc(&inode->i_count);
+               ihold(inode);
                d_instantiate(dentry, inode);
                mark_inode_dirty(inode);
        }
 
 
        inc_nlink(inode);
        hfsplus_instantiate(dst_dentry, inode, cnid);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        inode->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(inode);
        sbi->file_count++;
 
        atomic_inc(&inode->i_count);
 }
 
+/*
+ * get additional reference to inode; caller must already hold one.
+ */
+void ihold(struct inode *inode)
+{
+       WARN_ON(atomic_inc_return(&inode->i_count) < 2);
+}
+EXPORT_SYMBOL(ihold);
+
 static void inode_lru_list_add(struct inode *inode)
 {
        if (list_empty(&inode->i_list)) {
 
                mutex_unlock(&f->sem);
                d_instantiate(dentry, old_dentry->d_inode);
                dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
-               atomic_inc(&old_dentry->d_inode->i_count);
+               ihold(old_dentry->d_inode);
        }
        return ret;
 }
                printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
                /* Might as well let the VFS know */
                d_instantiate(new_dentry, old_dentry->d_inode);
-               atomic_inc(&old_dentry->d_inode->i_count);
+               ihold(old_dentry->d_inode);
                new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
                return ret;
        }
 
         * lazy commit thread finishes processing
         */
        if (tblk->xflag & COMMIT_DELETE) {
-               atomic_inc(&tblk->u.ip->i_count);
+               ihold(tblk->u.ip);
                /*
                 * Avoid a rare deadlock
                 *
 
        ip->i_ctime = CURRENT_TIME;
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        mark_inode_dirty(dir);
-       atomic_inc(&ip->i_count);
+       ihold(ip);
 
        iplist[0] = ip;
        iplist[1] = dir;
 
 
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        inc_nlink(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        dget(dentry);
        d_instantiate(dentry, inode);
        return 0;
 
                return -EMLINK;
 
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        inode->i_nlink++;
        mark_inode_dirty_sync(inode);
 
 
 
        inode->i_ctime = CURRENT_TIME_SEC;
        inode_inc_link_count(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        return add_nondir(dentry, inode);
 }
 
 
                        goto slashes;
                inode = dentry->d_inode;
                if (inode)
-                       atomic_inc(&inode->i_count);
+                       ihold(inode);
                error = mnt_want_write(nd.path.mnt);
                if (error)
                        goto exit2;
 
        d_drop(dentry);
        error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
        if (error == 0) {
-               atomic_inc(&inode->i_count);
+               ihold(inode);
                d_add(dentry, inode);
        }
        return error;
 
                        iput(inode);
                        return -ENOMEM;
                }
-               /* Circumvent igrab(): we know the inode is not being freed */
-               atomic_inc(&inode->i_count);
+               ihold(inode);
                /*
                 * Ensure that this dentry is invisible to d_find_alias().
                 * Otherwise, it may be spliced into the tree by
 
 
        inode->i_ctime = CURRENT_TIME;
        inode_inc_link_count(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
 
        err = nilfs_add_nondir(dentry, inode);
        if (!err)
 
                goto unl_upcase_iput_tmp_ino_err_out_now;
        }
        if ((sb->s_root = d_alloc_root(vol->root_ino))) {
-               /* We increment i_count simulating an ntfs_iget(). */
-               atomic_inc(&vol->root_ino->i_count);
+               /* We grab a reference, simulating an ntfs_iget(). */
+               ihold(vol->root_ino);
                ntfs_debug("Exiting, status successful.");
                /* Release the default upcase if it has no users. */
                mutex_lock(&ntfs_lock);
 
                goto out_commit;
        }
 
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
 
 
        inode->i_ctime = CURRENT_TIME_SEC;
        reiserfs_update_sd(&th, inode);
 
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        d_instantiate(dentry, inode);
        retval = journal_end(&th, dir->i_sb, jbegin_count);
        reiserfs_write_unlock(dir->i_sb);
 
 
        inode->i_ctime = CURRENT_TIME_SEC;
        inode_inc_link_count(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
 
        return add_nondir(dentry, inode);
 }
 
 
        lock_2_inodes(dir, inode);
        inc_nlink(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        inode->i_ctime = ubifs_current_time(inode);
        dir->i_size += sz_change;
        dir_ui->ui_size = dir->i_size;
 
        inc_nlink(inode);
        inode->i_ctime = current_fs_time(inode->i_sb);
        mark_inode_dirty(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        d_instantiate(dentry, inode);
        unlock_kernel();
 
 
 
        inode->i_ctime = CURRENT_TIME_SEC;
        inode_inc_link_count(inode);
-       atomic_inc(&inode->i_count);
+       ihold(inode);
 
        error = ufs_add_nondir(dentry, inode);
        unlock_kernel();
 
        if (unlikely(error))
                return -error;
 
-       atomic_inc(&inode->i_count);
+       ihold(inode);
        d_instantiate(dentry, inode);
        return 0;
 }
 
 #define IHOLD(ip) \
 do { \
        ASSERT(atomic_read(&VFS_I(ip)->i_count) > 0) ; \
-       atomic_inc(&(VFS_I(ip)->i_count)); \
+       ihold(VFS_I(ip)); \
        trace_xfs_ihold(ip, _THIS_IP_); \
 } while (0)
 
 
 
 extern int inode_init_always(struct super_block *, struct inode *);
 extern void inode_init_once(struct inode *);
+extern void ihold(struct inode * inode);
 extern void iput(struct inode *);
 extern struct inode * igrab(struct inode *);
 extern ino_t iunique(struct super_block *, ino_t);
 
 
        inode = dentry->d_inode;
        if (inode)
-               atomic_inc(&inode->i_count);
+               ihold(inode);
        err = mnt_want_write(ipc_ns->mq_mnt);
        if (err)
                goto out_err;
 
 
        switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
        case FUT_OFF_INODE:
-               atomic_inc(&key->shared.inode->i_count);
+               ihold(key->shared.inode);
                break;
        case FUT_OFF_MMSHARED:
                atomic_inc(&key->private.mm->mm_count);
 
        dir->i_size += BOGO_DIRENT_SIZE;
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        inc_nlink(inode);
-       atomic_inc(&inode->i_count);    /* New dentry reference */
+       ihold(inode);   /* New dentry reference */
        dget(dentry);           /* Extra pinning count for the created dentry */
        d_instantiate(dentry, inode);
 out:
 
                  &socket_file_ops);
        if (unlikely(!file)) {
                /* drop dentry, keep inode */
-               atomic_inc(&path.dentry->d_inode->i_count);
+               ihold(path.dentry->d_inode);
                path_put(&path);
                put_unused_fd(fd);
                return -ENFILE;