Freeing inode

Jan Kara (jack@ucw.cz)
Fri, 7 Sep 2001 19:39:35 +0200


--qDbXVdCdHGoSgWSk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hello,

Vladimir pointed me to another bug in ext2 quota allocation. The problem is
that when inode is being created but creation fails (either from user being
over quota or from some other reason) then quota is decremented incorrectly
(previously the usual case when user is over quota was handled by DQUOT_DROP()
but this works no more because of DQUOT_INIT() in iput() and ext2_free_inode()).
I made a patch which marks inode as bad and then quota is not initialized on
bad inodes (which makes sence anyway). The patch which is attached is just preliminary
and nontested (just now I'm realizing that inode being marked as bad might be
dirty which is not probably the best combination). I'd just like to know whether
this approach is ok with you or whether you have some better ideas.

Honza

--qDbXVdCdHGoSgWSk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="freeinode.diff"

--- fs/inode.c.orig Fri Sep 7 19:01:50 2001
+++ fs/inode.c Fri Sep 7 19:14:55 2001
@@ -1049,7 +1049,8 @@

if (op && op->delete_inode) {
void (*delete)(struct inode *) = op->delete_inode;
- DQUOT_INIT(inode);
+ if (!is_bad_inode(inode))
+ DQUOT_INIT(inode);
/* s_op->delete_inode internally recalls clear_inode() */
delete(inode);
} else
--- fs/ext2/ialloc.c.orig Fri Sep 7 18:52:51 2001
+++ fs/ext2/ialloc.c Fri Sep 7 19:14:43 2001
@@ -194,9 +194,11 @@
* Note: we must free any quota before locking the superblock,
* as writing the quota to disk may need the lock as well.
*/
- DQUOT_INIT(inode);
- DQUOT_FREE_INODE(sb, inode);
- DQUOT_DROP(inode);
+ if (!is_bad_inode(inode)) {
+ /* Quota is already initialized in iput() */
+ DQUOT_FREE_INODE(sb, inode);
+ DQUOT_DROP(inode);
+ }

lock_super (sb);
es = sb->u.ext2_sb.s_es;
@@ -453,8 +455,9 @@

unlock_super (sb);
if(DQUOT_ALLOC_INODE(sb, inode)) {
- sb->dq_op->drop(inode);
+ DQUOT_DROP(inode);
inode->i_nlink = 0;
+ make_bad_inode(inode);
iput(inode);
return ERR_PTR(-EDQUOT);
}
@@ -463,6 +466,7 @@

fail:
unlock_super(sb);
+ make_bad_inode(inode);
iput(inode);
return ERR_PTR(err);
}

--qDbXVdCdHGoSgWSk--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/