--- linux-2.6.16-rc4/fs/ext2/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/balloc.c	2006-02-17 23:26:32 +0100
@@ -109,6 +111,8 @@ static int reserve_blocks(struct super_b
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(es->s_r_blocks_count);
 
+	DLIMIT_ADJUST_BLOCK(sb, dx_current_tag(), &free_blocks, &root_blocks);
+
 	if (free_blocks < count)
 		count = free_blocks;
 
--- linux-2.6.16-rc4/fs/ext2/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/balloc.c	2006-02-17 23:26:32 +0100
@@ -259,6 +263,7 @@ do_more:
 	}
 error_return:
 	brelse(bitmap_bh);
+	DLIMIT_FREE_BLOCK(inode, freed);
 	release_blocks(sb, freed);
 	DQUOT_FREE_BLOCK(inode, freed);
 }
--- linux-2.6.16-rc4/fs/ext2/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/balloc.c	2006-02-17 23:26:32 +0100
@@ -362,6 +367,10 @@ int ext2_new_block(struct inode *inode, 
 		*err = -ENOSPC;
 		goto out_dquot;
 	}
+	if (DLIMIT_ALLOC_BLOCK(inode, es_alloc)) {
+		*err = -ENOSPC;
+		goto out_dlimit;
+	}
 
 	ext2_debug ("goal=%lu.\n", goal);
 
--- linux-2.6.16-rc4/fs/ext2/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/balloc.c	2006-02-17 23:26:32 +0100
@@ -509,6 +518,8 @@ got_block:
 	*err = 0;
 out_release:
 	group_release_blocks(sb, group_no, desc, gdp_bh, group_alloc);
+	DLIMIT_FREE_BLOCK(inode, es_alloc);
+out_dlimit:
 	release_blocks(sb, es_alloc);
 out_dquot:
 	DQUOT_FREE_BLOCK(inode, dq_alloc);
--- linux-2.6.16-rc4/fs/ext2/ialloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/ialloc.c	2006-02-17 23:26:32 +0100
@@ -126,6 +128,7 @@ void ext2_free_inode (struct inode * ino
 		ext2_xattr_delete_inode(inode);
 	    	DQUOT_FREE_INODE(inode);
 		DQUOT_DROP(inode);
+		DLIMIT_FREE_INODE(inode);
 	}
 
 	es = EXT2_SB(sb)->s_es;
--- linux-2.6.16-rc4/fs/ext2/ialloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/ialloc.c	2006-02-17 23:26:32 +0100
@@ -465,6 +468,11 @@ struct inode *ext2_new_inode(struct inod
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 
+	inode->i_tag = dx_current_fstag(sb);
+	if (DLIMIT_ALLOC_INODE(inode)) {
+		err = -ENOSPC;
+		goto fail_dlim;
+	}
 	ei = EXT2_I(inode);
 	sbi = EXT2_SB(sb);
 	es = sbi->s_es;
--- linux-2.6.16-rc4/fs/ext2/ialloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/ialloc.c	2006-02-17 23:26:32 +0100
@@ -627,6 +636,7 @@ fail_free_drop:
 
 fail_drop:
 	DQUOT_DROP(inode);
+	DLIMIT_FREE_INODE(inode);
 	inode->i_flags |= S_NOQUOTA;
 	inode->i_nlink = 0;
 	iput(inode);
--- linux-2.6.16-rc4/fs/ext2/ialloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/ialloc.c	2006-02-17 23:26:32 +0100
@@ -633,6 +643,8 @@ *****
 	return ERR_PTR(err);
 
 fail:
+	DLIMIT_FREE_INODE(inode);
+fail_dlim:
 	make_bad_inode(inode);
 	iput(inode);
 	return ERR_PTR(err);
--- linux-2.6.16-rc4/fs/ext2/xattr.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/xattr.c	2006-02-18 15:37:06 +0100
@@ -645,8 +646,12 @@ ext2_xattr_set2(struct inode *inode, str
 				   the inode.  */
 				ea_bdebug(new_bh, "reusing block");
 
+				error = -ENOSPC;
+				if (DLIMIT_ALLOC_BLOCK(inode, 1))
+					goto cleanup;
 				error = -EDQUOT;
 				if (DQUOT_ALLOC_BLOCK(inode, 1)) {
+					DLIMIT_FREE_BLOCK(inode, 1);
 					unlock_buffer(new_bh);
 					goto cleanup;
 				}
--- linux-2.6.16-rc4/fs/ext2/xattr.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/xattr.c	2006-02-18 15:37:06 +0100
@@ -740,6 +745,7 @@ ext2_xattr_set2(struct inode *inode, str
 				le32_to_cpu(HDR(old_bh)->h_refcount) - 1);
 			if (ce)
 				mb_cache_entry_release(ce);
+			DLIMIT_FREE_BLOCK(inode, 1);
 			DQUOT_FREE_BLOCK(inode, 1);
 			mark_buffer_dirty(old_bh);
 			ea_bdebug(old_bh, "refcount now=%d",
--- linux-2.6.16-rc4/fs/ext2/xattr.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext2/xattr.c	2006-02-18 15:37:06 +0100
@@ -804,6 +810,7 @@ ext2_xattr_delete_inode(struct inode *in
 		mark_buffer_dirty(bh);
 		if (IS_SYNC(inode))
 			sync_dirty_buffer(bh);
+		DLIMIT_FREE_BLOCK(inode, 1);
 		DQUOT_FREE_BLOCK(inode, 1);
 	}
 	EXT2_I(inode)->i_file_acl = 0;
--- linux-2.6.16-rc4/fs/ext3/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/balloc.c	2006-02-17 23:26:32 +0100
@@ -504,8 +506,10 @@ void ext3_free_blocks(handle_t *handle, 
 		return;
 	}
 	ext3_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
-	if (dquot_freed_blocks)
+	if (dquot_freed_blocks) {
+		DLIMIT_FREE_BLOCK(inode, dquot_freed_blocks);
 		DQUOT_FREE_BLOCK(inode, dquot_freed_blocks);
+	}
 	return;
 }
 
--- linux-2.6.16-rc4/fs/ext3/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/balloc.c	2006-02-17 23:26:32 +0100
@@ -1116,9 +1120,10 @@ out:
 	return ret;
 }
 
-static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
+static int ext3_has_free_blocks(struct super_block *sb)
 {
-	int free_blocks, root_blocks;
+	struct ext3_sb_info *sbi = EXT3_SB(sb);
+	int free_blocks, root_blocks, cond;
 
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
--- linux-2.6.16-rc4/fs/ext3/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/balloc.c	2006-02-17 23:26:32 +0100
@@ -1122,12 +1127,25 @@ *****
 
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
-	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
+
+	vxdprintk(VXD_CBIT(dlim, 3),
+		"ext3_has_free_blocks(%p): free=%u, root=%u",
+		sb, free_blocks, root_blocks);
+
+	DLIMIT_ADJUST_BLOCK(sb, dx_current_tag(), &free_blocks, &root_blocks);
+
+	cond = (free_blocks < root_blocks + 1 &&
+		!capable(CAP_SYS_RESOURCE) &&
 		sbi->s_resuid != current->fsuid &&
-		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
-		return 0;
-	}
-	return 1;
+		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid)));
+
+	vxdprintk(VXD_CBIT(dlim, 3),
+		"ext3_has_free_blocks(%p): %u<%u+1, %c, %u!=%u r=%d",
+		sb, free_blocks, root_blocks,
+		!capable(CAP_SYS_RESOURCE)?'1':'0',
+		sbi->s_resuid, current->fsuid, cond?0:1);
+
+	return (cond ? 0 : 1);
 }
 
 /*
--- linux-2.6.16-rc4/fs/ext3/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/balloc.c	2006-02-17 23:26:32 +0100
@@ -1138,7 +1156,7 @@ static int ext3_has_free_blocks(struct e
  */
 int ext3_should_retry_alloc(struct super_block *sb, int *retries)
 {
-	if (!ext3_has_free_blocks(EXT3_SB(sb)) || (*retries)++ > 3)
+	if (!ext3_has_free_blocks(sb) || (*retries)++ > 3)
 		return 0;
 
 	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
--- linux-2.6.16-rc4/fs/ext3/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/balloc.c	2006-02-17 23:26:32 +0100
@@ -1193,6 +1211,8 @@ int ext3_new_block(handle_t *handle, str
 		*errp = -EDQUOT;
 		return 0;
 	}
+	if (DLIMIT_ALLOC_BLOCK(inode, 1))
+	    goto out_dlimit;
 
 	sbi = EXT3_SB(sb);
 	es = EXT3_SB(sb)->s_es;
--- linux-2.6.16-rc4/fs/ext3/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/balloc.c	2006-02-17 23:26:32 +0100
@@ -1209,7 +1229,7 @@ int ext3_new_block(handle_t *handle, str
 	if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0))
 		my_rsv = &block_i->rsv_window_node;
 
-	if (!ext3_has_free_blocks(sbi)) {
+	if (!ext3_has_free_blocks(sb)) {
 		*errp = -ENOSPC;
 		goto out;
 	}
--- linux-2.6.16-rc4/fs/ext3/balloc.c	2006-02-18 14:40:21 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/balloc.c	2006-02-17 23:26:32 +0100
@@ -1393,6 +1413,9 @@ allocated:
 io_error:
 	*errp = -EIO;
 out:
+	if (!performed_allocation)
+		DLIMIT_FREE_BLOCK(inode, 1);
+out_dlimit:
 	if (fatal) {
 		*errp = fatal;
 		ext3_std_error(sb, fatal);
--- linux-2.6.16-rc4/fs/ext3/ialloc.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/ialloc.c	2006-02-17 23:26:32 +0100
@@ -127,6 +129,7 @@ void ext3_free_inode (handle_t *handle, 
 	ext3_xattr_delete_inode(handle, inode);
 	DQUOT_FREE_INODE(inode);
 	DQUOT_DROP(inode);
+	DLIMIT_FREE_INODE(inode);
 
 	is_directory = S_ISDIR(inode->i_mode);
 
--- linux-2.6.16-rc4/fs/ext3/ialloc.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/ialloc.c	2006-02-17 23:26:32 +0100
@@ -443,6 +446,12 @@ struct inode *ext3_new_inode(handle_t *h
 	inode = new_inode(sb);
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
+
+	inode->i_tag = dx_current_fstag(sb);
+	if (DLIMIT_ALLOC_INODE(inode)) {
+		err = -ENOSPC;
+		goto out_dlimit;
+	}
 	ei = EXT3_I(inode);
 
 	sbi = EXT3_SB(sb);
--- linux-2.6.16-rc4/fs/ext3/ialloc.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/ialloc.c	2006-02-17 23:26:32 +0100
@@ -620,6 +630,8 @@ got:
 fail:
 	ext3_std_error(sb, err);
 out:
+	DLIMIT_FREE_INODE(inode);
+out_dlimit:
 	iput(inode);
 	ret = ERR_PTR(err);
 really_out:
--- linux-2.6.16-rc4/fs/ext3/ialloc.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/ialloc.c	2006-02-17 23:26:32 +0100
@@ -631,6 +643,7 @@ fail_free_drop:
 
 fail_drop:
 	DQUOT_DROP(inode);
+	DLIMIT_FREE_INODE(inode);
 	inode->i_flags |= S_NOQUOTA;
 	inode->i_nlink = 0;
 	iput(inode);
--- linux-2.6.16-rc4/fs/ext3/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/xattr.c	2006-02-17 23:26:32 +0100
@@ -495,6 +496,7 @@ ext3_xattr_release_block(handle_t *handl
 			ext3_journal_dirty_metadata(handle, bh);
 			if (IS_SYNC(inode))
 				handle->h_sync = 1;
+			DLIMIT_FREE_BLOCK(inode, 1);
 			DQUOT_FREE_BLOCK(inode, 1);
 			unlock_buffer(bh);
 			ea_bdebug(bh, "refcount now=%d; releasing",
--- linux-2.6.16-rc4/fs/ext3/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/xattr.c	2006-02-17 23:26:32 +0100
@@ -763,6 +765,9 @@ inserted:
 			if (new_bh == bs->bh)
 				ea_bdebug(new_bh, "keeping");
 			else {
+				error = -ENOSPC;
+				if (DLIMIT_ALLOC_BLOCK(inode, 1))
+					goto cleanup;
 				/* The old block is released after updating
 				   the inode. */
 				error = -EDQUOT;
--- linux-2.6.16-rc4/fs/ext3/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/xattr.c	2006-02-17 23:26:32 +0100
@@ -767,7 +772,7 @@ *****
 				   the inode. */
 				error = -EDQUOT;
 				if (DQUOT_ALLOC_BLOCK(inode, 1))
-					goto cleanup;
+					goto cleanup_dlimit;
 				error = ext3_journal_get_write_access(handle,
 								      new_bh);
 				if (error)
--- linux-2.6.16-rc4/fs/ext3/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/ext3/xattr.c	2006-02-17 23:26:32 +0100
@@ -843,6 +848,8 @@ cleanup:
 
 cleanup_dquot:
 	DQUOT_FREE_BLOCK(inode, 1);
+cleanup_dlimit:
+	DLIMIT_FREE_BLOCK(inode, 1);
 	goto cleanup;
 
 bad_block:
--- linux-2.6.16-rc4/fs/jfs/inode.c	2005-10-28 20:49:44 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/inode.c	2006-02-17 23:26:32 +0100
@@ -143,6 +145,7 @@ void jfs_delete_inode(struct inode *inod
 		DQUOT_INIT(inode);
 		DQUOT_FREE_INODE(inode);
 		DQUOT_DROP(inode);
+		DLIMIT_FREE_INODE(inode);
 	}
 
 	clear_inode(inode);
--- linux-2.6.16-rc4/fs/jfs/jfs_dtree.c	2005-08-29 22:25:31 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_dtree.c	2006-02-17 23:26:32 +0100
@@ -383,10 +384,10 @@ static u32 add_index(tid_t tid, struct i
 		 */
 		if (DQUOT_ALLOC_BLOCK(ip, sbi->nbperpage))
 			goto clean_up;
-		if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr)) {
-			DQUOT_FREE_BLOCK(ip, sbi->nbperpage);
-			goto clean_up;
-		}
+		if (DLIMIT_ALLOC_BLOCK(ip, sbi->nbperpage))
+			goto clean_up_dquot;
+		if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr))
+			goto clean_up_dlimit;
 
 		/*
 		 * Save the table, we're going to overwrite it with the
--- linux-2.6.16-rc4/fs/jfs/jfs_dtree.c	2005-08-29 22:25:31 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_dtree.c	2006-02-17 23:26:32 +0100
@@ -479,6 +480,12 @@ static u32 add_index(tid_t tid, struct i
 
 	return index;
 
+      clean_up_dlimit:
+	DLIMIT_FREE_BLOCK(ip, sbi->nbperpage);
+
+      clean_up_dquot:
+	DQUOT_FREE_BLOCK(ip, sbi->nbperpage);
+
       clean_up:
 
 	jfs_ip->next_index--;
--- linux-2.6.16-rc4/fs/jfs/jfs_dtree.c	2005-08-29 22:25:31 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_dtree.c	2006-02-17 23:26:32 +0100
@@ -952,6 +960,7 @@ static int dtSplitUp(tid_t tid,
 	struct tlock *tlck;
 	struct lv *lv;
 	int quota_allocation = 0;
+	int dlimit_allocation = 0;
 
 	/* get split page */
 	smp = split->mp;
--- linux-2.6.16-rc4/fs/jfs/jfs_dtree.c	2005-08-29 22:25:31 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_dtree.c	2006-02-17 23:26:32 +0100
@@ -1033,6 +1042,12 @@ static int dtSplitUp(tid_t tid,
 		}
 		quota_allocation += n;
 
+		if (DLIMIT_ALLOC_BLOCK(ip, n)) {
+			rc = -ENOSPC;
+			goto extendOut;
+		}
+		dlimit_allocation += n;
+
 		if ((rc = dbReAlloc(sbi->ipbmap, xaddr, (s64) xlen,
 				    (s64) n, &nxaddr)))
 			goto extendOut;
--- linux-2.6.16-rc4/fs/jfs/jfs_dtree.c	2005-08-29 22:25:31 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_dtree.c	2006-02-17 23:26:32 +0100
@@ -1301,6 +1316,9 @@ static int dtSplitUp(tid_t tid,
       freeKeyName:
 	kfree(key.name);
 
+	/* Rollback dlimit allocation */
+	if (rc && dlimit_allocation)
+		DLIMIT_FREE_BLOCK(ip, dlimit_allocation);
 	/* Rollback quota allocation */
 	if (rc && quota_allocation)
 		DQUOT_FREE_BLOCK(ip, quota_allocation);
--- linux-2.6.16-rc4/fs/jfs/jfs_dtree.c	2005-08-29 22:25:31 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_dtree.c	2006-02-17 23:26:32 +0100
@@ -1368,6 +1386,12 @@ static int dtSplitPage(tid_t tid, struct
 		release_metapage(rmp);
 		return -EDQUOT;
 	}
+	/* Allocate blocks to dlimit. */
+	if (DLIMIT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		DQUOT_FREE_BLOCK(ip, lengthPXD(pxd));
+		release_metapage(rmp);
+		return -ENOSPC;
+	}
 
 	jfs_info("dtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
 
--- linux-2.6.16-rc4/fs/jfs/jfs_dtree.c	2005-08-29 22:25:31 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_dtree.c	2006-02-17 23:26:32 +0100
@@ -1918,6 +1942,12 @@ static int dtSplitRoot(tid_t tid,
 		release_metapage(rmp);
 		return -EDQUOT;
 	}
+	/* Allocate blocks to dlimit. */
+	if (DLIMIT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		DQUOT_FREE_BLOCK(ip, lengthPXD(pxd));
+		release_metapage(rmp);
+		return -ENOSPC;
+	}
 
 	BT_MARK_DIRTY(rmp, ip);
 	/*
--- linux-2.6.16-rc4/fs/jfs/jfs_dtree.c	2005-08-29 22:25:31 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_dtree.c	2006-02-17 23:26:32 +0100
@@ -2284,6 +2314,8 @@ static int dtDeleteUp(tid_t tid, struct 
 
 	xlen = lengthPXD(&fp->header.self);
 
+	/* Free dlimit allocation. */
+	DLIMIT_FREE_BLOCK(ip, xlen);
 	/* Free quota allocation. */
 	DQUOT_FREE_BLOCK(ip, xlen);
 
--- linux-2.6.16-rc4/fs/jfs/jfs_dtree.c	2005-08-29 22:25:31 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_dtree.c	2006-02-17 23:26:32 +0100
@@ -2360,6 +2392,8 @@ static int dtDeleteUp(tid_t tid, struct 
 
 				xlen = lengthPXD(&p->header.self);
 
+				/* Free dlimit allocation */
+				DLIMIT_FREE_BLOCK(ip, xlen);
 				/* Free quota allocation */
 				DQUOT_FREE_BLOCK(ip, xlen);
 
--- linux-2.6.16-rc4/fs/jfs/jfs_extent.c	2005-08-29 22:25:32 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_extent.c	2006-02-17 23:26:32 +0100
@@ -146,6 +147,13 @@ extAlloc(struct inode *ip, s64 xlen, s64
 		up(&JFS_IP(ip)->commit_sem);
 		return -EDQUOT;
 	}
+	/* Allocate blocks to dlimit. */
+	if (DLIMIT_ALLOC_BLOCK(ip, nxlen)) {
+		DQUOT_FREE_BLOCK(ip, nxlen);
+		dbFree(ip, nxaddr, (s64) nxlen);
+		up(&JFS_IP(ip)->commit_sem);
+		return -ENOSPC;
+	}
 
 	/* determine the value of the extent flag */
 	xflag = (abnr == TRUE) ? XAD_NOTRECORDED : 0;
--- linux-2.6.16-rc4/fs/jfs/jfs_extent.c	2005-08-29 22:25:32 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_extent.c	2006-02-17 23:26:32 +0100
@@ -164,6 +172,7 @@ extAlloc(struct inode *ip, s64 xlen, s64
 	 */
 	if (rc) {
 		dbFree(ip, nxaddr, nxlen);
+		DLIMIT_FREE_BLOCK(ip, nxlen);
 		DQUOT_FREE_BLOCK(ip, nxlen);
 		up(&JFS_IP(ip)->commit_sem);
 		return (rc);
--- linux-2.6.16-rc4/fs/jfs/jfs_extent.c	2005-08-29 22:25:32 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_extent.c	2006-02-17 23:26:32 +0100
@@ -261,6 +270,13 @@ int extRealloc(struct inode *ip, s64 nxl
 		up(&JFS_IP(ip)->commit_sem);
 		return -EDQUOT;
 	}
+	/* Allocate blocks to dlimit. */
+	if (DLIMIT_ALLOC_BLOCK(ip, nxlen)) {
+		DQUOT_FREE_BLOCK(ip, nxlen);
+		dbFree(ip, nxaddr, (s64) nxlen);
+		up(&JFS_IP(ip)->commit_sem);
+		return -ENOSPC;
+	}
 
 	delta = nxlen - xlen;
 
--- linux-2.6.16-rc4/fs/jfs/jfs_extent.c	2005-08-29 22:25:32 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_extent.c	2006-02-17 23:26:32 +0100
@@ -297,6 +313,7 @@ int extRealloc(struct inode *ip, s64 nxl
 		/* extend the extent */
 		if ((rc = xtExtend(0, ip, xoff + xlen, (int) nextend, 0))) {
 			dbFree(ip, xaddr + xlen, delta);
+			DLIMIT_FREE_BLOCK(ip, nxlen);
 			DQUOT_FREE_BLOCK(ip, nxlen);
 			goto exit;
 		}
--- linux-2.6.16-rc4/fs/jfs/jfs_extent.c	2005-08-29 22:25:32 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_extent.c	2006-02-17 23:26:32 +0100
@@ -308,6 +325,7 @@ int extRealloc(struct inode *ip, s64 nxl
 		 */
 		if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) {
 			dbFree(ip, nxaddr, nxlen);
+			DLIMIT_FREE_BLOCK(ip, nxlen);
 			DQUOT_FREE_BLOCK(ip, nxlen);
 			goto exit;
 		}
--- linux-2.6.16-rc4/fs/jfs/jfs_inode.c	2005-08-29 22:25:32 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_inode.c	2006-02-17 23:26:32 +0100
@@ -62,6 +124,12 @@ struct inode *ialloc(struct inode *paren
 	} else
 		inode->i_gid = current->fsgid;
 
+	inode->i_tag = dx_current_fstag(sb);
+	if (DLIMIT_ALLOC_INODE(inode)) {
+		iput(inode);
+		return NULL;
+	}
+
 	/*
 	 * Allocate inode to quota.
 	 */
--- linux-2.6.16-rc4/fs/jfs/jfs_inode.c	2005-08-29 22:25:32 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_inode.c	2006-02-17 23:26:32 +0100
@@ -66,6 +134,7 @@ *****
 	 * Allocate inode to quota.
 	 */
 	if (DQUOT_ALLOC_INODE(inode)) {
+		DLIMIT_FREE_INODE(inode);
 		DQUOT_DROP(inode);
 		inode->i_flags |= S_NOQUOTA;
 		inode->i_nlink = 0;
--- linux-2.6.16-rc4/fs/jfs/jfs_xtree.c	2006-01-03 17:29:57 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_xtree.c	2006-02-17 23:26:32 +0100
@@ -841,7 +842,12 @@ int xtInsert(tid_t tid,		/* transaction 
 			hint = 0;
 		if ((rc = DQUOT_ALLOC_BLOCK(ip, xlen)))
 			goto out;
+		if ((rc = DLIMIT_ALLOC_BLOCK(ip, xlen))) {
+			DQUOT_FREE_BLOCK(ip, xlen);
+			goto out;
+		}
 		if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr))) {
+			DLIMIT_FREE_BLOCK(ip, xlen);
 			DQUOT_FREE_BLOCK(ip, xlen);
 			goto out;
 		}
--- linux-2.6.16-rc4/fs/jfs/jfs_xtree.c	2006-01-03 17:29:57 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_xtree.c	2006-02-17 23:26:32 +0100
@@ -871,6 +877,7 @@ int xtInsert(tid_t tid,		/* transaction 
 			/* undo data extent allocation */
 			if (*xaddrp == 0) {
 				dbFree(ip, xaddr, (s64) xlen);
+				DLIMIT_FREE_BLOCK(ip, xlen);
 				DQUOT_FREE_BLOCK(ip, xlen);
 			}
 			return rc;
--- linux-2.6.16-rc4/fs/jfs/jfs_xtree.c	2006-01-03 17:29:57 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_xtree.c	2006-02-17 23:26:32 +0100
@@ -1231,6 +1238,7 @@ xtSplitPage(tid_t tid, struct inode *ip,
 	struct tlock *tlck;
 	struct xtlock *sxtlck = NULL, *rxtlck = NULL;
 	int quota_allocation = 0;
+	int dlimit_allocation = 0;
 
 	smp = split->mp;
 	sp = XT_PAGE(ip, smp);
--- linux-2.6.16-rc4/fs/jfs/jfs_xtree.c	2006-01-03 17:29:57 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_xtree.c	2006-02-17 23:26:32 +0100
@@ -1250,6 +1258,13 @@ *****
 
 	quota_allocation += lengthPXD(pxd);
 
+	/* Allocate blocks to dlimit. */
+	if (DLIMIT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+	       rc = -ENOSPC;
+	       goto clean_up;
+	}
+	dlimit_allocation += lengthPXD(pxd);
+
 	/*
 	 * allocate the new right page for the split
 	 */
--- linux-2.6.16-rc4/fs/jfs/jfs_xtree.c	2006-01-03 17:29:57 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_xtree.c	2006-02-17 23:26:32 +0100
@@ -1451,6 +1466,9 @@ xtSplitPage(tid_t tid, struct inode *ip,
 
       clean_up:
 
+	/* Rollback dlimit allocation. */
+	if (dlimit_allocation)
+		DLIMIT_FREE_BLOCK(ip, dlimit_allocation);
 	/* Rollback quota allocation. */
 	if (quota_allocation)
 		DQUOT_FREE_BLOCK(ip, quota_allocation);
--- linux-2.6.16-rc4/fs/jfs/jfs_xtree.c	2006-01-03 17:29:57 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_xtree.c	2006-02-17 23:26:32 +0100
@@ -1515,6 +1533,12 @@ xtSplitRoot(tid_t tid,
 		release_metapage(rmp);
 		return -EDQUOT;
 	}
+	/* Allocate blocks to dlimit. */
+	if (DLIMIT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		DQUOT_FREE_BLOCK(ip, lengthPXD(pxd));
+		release_metapage(rmp);
+		return -ENOSPC;
+	}
 
 	jfs_info("xtSplitRoot: ip:0x%p rmp:0x%p", ip, rmp);
 
--- linux-2.6.16-rc4/fs/jfs/jfs_xtree.c	2006-01-03 17:29:57 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/jfs_xtree.c	2006-02-17 23:26:32 +0100
@@ -3941,6 +3965,8 @@ s64 xtTruncate(tid_t tid, struct inode *
 	else
 		ip->i_size = newsize;
 
+	/* update dlimit allocation to reflect freed blocks */
+	DLIMIT_FREE_BLOCK(ip, nfreed);
 	/* update quota allocation to reflect freed blocks */
 	DQUOT_FREE_BLOCK(ip, nfreed);
 
--- linux-2.6.16-rc4/fs/jfs/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/xattr.c	2006-02-17 23:26:32 +0100
@@ -263,6 +264,11 @@ static int ea_write(struct inode *ip, st
 	if (DQUOT_ALLOC_BLOCK(ip, nblocks)) {
 		return -EDQUOT;
 	}
+	/* Allocate new blocks to dlimit. */
+	if (DLIMIT_ALLOC_BLOCK(ip, nblocks)) {
+		DQUOT_FREE_BLOCK(ip, nblocks);
+		return -ENOSPC;
+	}
 
 	rc = dbAlloc(ip, INOHINT(ip), nblocks, &blkno);
 	if (rc) {
--- linux-2.6.16-rc4/fs/jfs/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/xattr.c	2006-02-17 23:26:32 +0100
@@ -266,6 +272,8 @@ *****
 
 	rc = dbAlloc(ip, INOHINT(ip), nblocks, &blkno);
 	if (rc) {
+		/*Rollback dlimit allocation. */
+		DLIMIT_FREE_BLOCK(ip, nblocks);
 		/*Rollback quota allocation. */
 		DQUOT_FREE_BLOCK(ip, nblocks);
 		return rc;
--- linux-2.6.16-rc4/fs/jfs/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/xattr.c	2006-02-17 23:26:32 +0100
@@ -332,6 +340,8 @@ static int ea_write(struct inode *ip, st
 
       failed:
 	/* Rollback quota allocation. */
+	DLIMIT_FREE_BLOCK(ip, nblocks);
+	/* Rollback quota allocation. */
 	DQUOT_FREE_BLOCK(ip, nblocks);
 
 	dbFree(ip, blkno, nblocks);
--- linux-2.6.16-rc4/fs/jfs/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/xattr.c	2006-02-17 23:26:32 +0100
@@ -468,6 +478,7 @@ static int ea_get(struct inode *inode, s
 	s64 blkno;
 	int rc;
 	int quota_allocation = 0;
+	int dlimit_allocation = 0;
 
 	/* When fsck.jfs clears a bad ea, it doesn't clear the size */
 	if (ji->ea.flag == 0)
--- linux-2.6.16-rc4/fs/jfs/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/xattr.c	2006-02-17 23:26:32 +0100
@@ -543,6 +554,12 @@ static int ea_get(struct inode *inode, s
 
 		quota_allocation = blocks_needed;
 
+		/* Allocate new blocks to dlimit. */
+		rc = -ENOSPC;
+		if (DLIMIT_ALLOC_BLOCK(inode, blocks_needed))
+			goto clean_up;
+		dlimit_allocation = blocks_needed;
+
 		rc = dbAlloc(inode, INOHINT(inode), (s64) blocks_needed,
 			     &blkno);
 		if (rc)
--- linux-2.6.16-rc4/fs/jfs/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/xattr.c	2006-02-17 23:26:32 +0100
@@ -599,6 +616,9 @@ static int ea_get(struct inode *inode, s
 	return ea_size;
 
       clean_up:
+	/* Rollback dlimit allocation */
+	if (dlimit_allocation)
+		DLIMIT_FREE_BLOCK(inode, dlimit_allocation);
 	/* Rollback quota allocation */
 	if (quota_allocation)
 		DQUOT_FREE_BLOCK(inode, quota_allocation);
--- linux-2.6.16-rc4/fs/jfs/xattr.c	2006-02-18 14:40:22 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/jfs/xattr.c	2006-02-17 23:26:32 +0100
@@ -675,8 +695,10 @@ static int ea_put(tid_t tid, struct inod
 	}
 
 	/* If old blocks exist, they must be removed from quota allocation. */
-	if (old_blocks)
+	if (old_blocks) {
+		DLIMIT_FREE_BLOCK(inode, old_blocks);
 		DQUOT_FREE_BLOCK(inode, old_blocks);
+	}
 
 	inode->i_ctime = CURRENT_TIME;
 
--- linux-2.6.16-rc4/fs/reiserfs/bitmap.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/bitmap.c	2006-02-17 23:26:32 +0100
@@ -411,8 +412,10 @@ static void _reiserfs_free_block(struct 
 	set_sb_free_blocks(rs, sb_free_blocks(rs) + 1);
 
 	journal_mark_dirty(th, s, sbh);
-	if (for_unformatted)
+	if (for_unformatted) {
+		DLIMIT_FREE_BLOCK(inode, 1);
 		DQUOT_FREE_BLOCK_NODIRTY(inode, 1);
+	}
 }
 
 void reiserfs_free_block(struct reiserfs_transaction_handle *th,
--- linux-2.6.16-rc4/fs/reiserfs/bitmap.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/bitmap.c	2006-02-17 23:26:32 +0100
@@ -1021,6 +1024,7 @@ static inline int blocknrs_and_prealloc_
 	int passno = 0;
 	int nr_allocated = 0;
 	int bigalloc = 0;
+	int blocks;
 
 	determine_prealloc_size(hint);
 	if (!hint->formatted_node) {
--- linux-2.6.16-rc4/fs/reiserfs/bitmap.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/bitmap.c	2006-02-17 23:26:32 +0100
@@ -1030,10 +1034,16 @@ static inline int blocknrs_and_prealloc_
 			       "reiserquota: allocating %d blocks id=%u",
 			       amount_needed, hint->inode->i_uid);
 #endif
-		quota_ret =
-		    DQUOT_ALLOC_BLOCK_NODIRTY(hint->inode, amount_needed);
-		if (quota_ret)	/* Quota exceeded? */
+		quota_ret = DQUOT_ALLOC_BLOCK_NODIRTY(hint->inode,
+			amount_needed);
+		if (quota_ret)
 			return QUOTA_EXCEEDED;
+		if (DLIMIT_ALLOC_BLOCK(hint->inode, amount_needed)) {
+			DQUOT_FREE_BLOCK_NODIRTY(hint->inode,
+				amount_needed);
+			return NO_DISK_SPACE;
+		}
+
 		if (hint->preallocate && hint->prealloc_size) {
 #ifdef REISERQUOTA_DEBUG
 			reiserfs_debug(s, REISERFS_DEBUG_CODE,
--- linux-2.6.16-rc4/fs/reiserfs/bitmap.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/bitmap.c	2006-02-17 23:26:32 +0100
@@ -1040,9 +1050,14 @@ *****
 				       "reiserquota: allocating (prealloc) %d blocks id=%u",
 				       hint->prealloc_size, hint->inode->i_uid);
 #endif
-			quota_ret =
-			    DQUOT_PREALLOC_BLOCK_NODIRTY(hint->inode,
-							 hint->prealloc_size);
+			quota_ret = DQUOT_PREALLOC_BLOCK_NODIRTY(hint->inode,
+				hint->prealloc_size);
+			if (!quota_ret &&
+				DLIMIT_ALLOC_BLOCK(hint->inode, hint->prealloc_size)) {
+				DQUOT_FREE_BLOCK_NODIRTY(hint->inode,
+					hint->prealloc_size);
+				quota_ret = 1;
+			}
 			if (quota_ret)
 				hint->preallocate = hint->prealloc_size = 0;
 		}
--- linux-2.6.16-rc4/fs/reiserfs/bitmap.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/bitmap.c	2006-02-17 23:26:32 +0100
@@ -1093,7 +1108,10 @@ static inline int blocknrs_and_prealloc_
 					       nr_allocated,
 					       hint->inode->i_uid);
 #endif
-				DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed + hint->prealloc_size - nr_allocated);	/* Free not allocated blocks */
+				/* Free not allocated blocks */
+				blocks = amount_needed + hint->prealloc_size - nr_allocated;
+				DLIMIT_FREE_BLOCK(hint->inode, blocks);
+				DQUOT_FREE_BLOCK_NODIRTY(hint->inode, blocks);
 			}
 			while (nr_allocated--)
 				reiserfs_free_block(hint->th, hint->inode,
--- linux-2.6.16-rc4/fs/reiserfs/bitmap.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/bitmap.c	2006-02-17 23:26:32 +0100
@@ -1125,10 +1143,10 @@ static inline int blocknrs_and_prealloc_
 			       REISERFS_I(hint->inode)->i_prealloc_count,
 			       hint->inode->i_uid);
 #endif
-		DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed +
-					 hint->prealloc_size - nr_allocated -
-					 REISERFS_I(hint->inode)->
-					 i_prealloc_count);
+		blocks = amount_needed + hint->prealloc_size - nr_allocated -
+			REISERFS_I(hint->inode)->i_prealloc_count;
+		DLIMIT_FREE_BLOCK(hint->inode, blocks);
+		DQUOT_FREE_BLOCK_NODIRTY(hint->inode, blocks);
 	}
 
 	return CARRY_ON;
--- linux-2.6.16-rc4/fs/reiserfs/inode.c	2006-02-18 14:40:26 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/inode.c	2006-02-17 23:26:32 +0100
@@ -57,6 +59,7 @@ void reiserfs_delete_inode(struct inode 
 		 * stat data deletion */
 		if (!err) 
 			DQUOT_FREE_INODE(inode);
+		DLIMIT_FREE_INODE(inode);
 
 		if (journal_end(&th, inode->i_sb, jbegin_count)) {
 			mutex_unlock(&inode->i_mutex);
--- linux-2.6.16-rc4/fs/reiserfs/inode.c	2006-02-18 14:40:26 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/inode.c	2006-02-17 23:26:32 +0100
@@ -1793,6 +1806,10 @@ int reiserfs_new_inode(struct reiserfs_t
 
 	BUG_ON(!th->t_trans_id);
 
+	if (DLIMIT_ALLOC_INODE(inode)) {
+		err = -ENOSPC;
+		goto out_bad_dlimit;
+	}
 	if (DQUOT_ALLOC_INODE(inode)) {
 		err = -EDQUOT;
 		goto out_end_trans;
--- linux-2.6.16-rc4/fs/reiserfs/inode.c	2006-02-18 14:40:26 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/inode.c	2006-02-17 23:26:32 +0100
@@ -1978,6 +1995,9 @@ int reiserfs_new_inode(struct reiserfs_t
 	DQUOT_FREE_INODE(inode);
 
       out_end_trans:
+	DLIMIT_FREE_INODE(inode);
+
+      out_bad_dlimit:
 	journal_end(th, th->t_super, th->t_blocks_allocated);
 	/* Drop can be outside and it needs more credits so it's better to have it outside */
 	DQUOT_DROP(inode);
--- linux-2.6.16-rc4/fs/reiserfs/stree.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/stree.c	2006-02-17 23:26:32 +0100
@@ -1365,6 +1366,7 @@ int reiserfs_delete_item(struct reiserfs
 		       "reiserquota delete_item(): freeing %u, id=%u type=%c",
 		       quota_cut_bytes, p_s_inode->i_uid, head2type(&s_ih));
 #endif
+	DLIMIT_FREE_SPACE(p_s_inode, quota_cut_bytes);
 	DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes);
 
 	/* Return deleted body length */
--- linux-2.6.16-rc4/fs/reiserfs/stree.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/stree.c	2006-02-17 23:26:32 +0100
@@ -1453,6 +1455,7 @@ void reiserfs_delete_solid_item(struct r
 #endif
 				DQUOT_FREE_SPACE_NODIRTY(inode,
 							 quota_cut_bytes);
+				DLIMIT_FREE_SPACE(inode, quota_cut_bytes);
 			}
 			break;
 		}
--- linux-2.6.16-rc4/fs/reiserfs/stree.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/stree.c	2006-02-17 23:26:32 +0100
@@ -1808,6 +1811,7 @@ int reiserfs_cut_from_item(struct reiser
 		       "reiserquota cut_from_item(): freeing %u id=%u type=%c",
 		       quota_cut_bytes, p_s_inode->i_uid, '?');
 #endif
+	DLIMIT_FREE_SPACE(p_s_inode, quota_cut_bytes);
 	DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes);
 	return n_ret_value;
 }
--- linux-2.6.16-rc4/fs/reiserfs/stree.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/stree.c	2006-02-17 23:26:32 +0100
@@ -2048,6 +2052,11 @@ int reiserfs_paste_into_item(struct reis
 		pathrelse(p_s_search_path);
 		return -EDQUOT;
 	}
+	if (DLIMIT_ALLOC_SPACE(inode, n_pasted_size)) {
+		DQUOT_FREE_SPACE_NODIRTY(inode, n_pasted_size);
+		pathrelse(p_s_search_path);
+		return -ENOSPC;
+	}
 	init_tb_struct(th, &s_paste_balance, th->t_super, p_s_search_path,
 		       n_pasted_size);
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
--- linux-2.6.16-rc4/fs/reiserfs/stree.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/stree.c	2006-02-17 23:26:32 +0100
@@ -2100,6 +2109,7 @@ int reiserfs_paste_into_item(struct reis
 		       n_pasted_size, inode->i_uid,
 		       key2type(&(p_s_key->on_disk_key)));
 #endif
+	DLIMIT_FREE_SPACE(inode, n_pasted_size);
 	DQUOT_FREE_SPACE_NODIRTY(inode, n_pasted_size);
 	return retval;
 }
--- linux-2.6.16-rc4/fs/reiserfs/stree.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/stree.c	2006-02-17 23:26:32 +0100
@@ -2137,6 +2147,11 @@ int reiserfs_insert_item(struct reiserfs
 			pathrelse(p_s_path);
 			return -EDQUOT;
 		}
+		if (DLIMIT_ALLOC_SPACE(inode, quota_bytes)) {
+			DQUOT_FREE_SPACE_NODIRTY(inode, quota_bytes);
+			pathrelse(p_s_path);
+			return -ENOSPC;
+		}
 	}
 	init_tb_struct(th, &s_ins_balance, th->t_super, p_s_path,
 		       IH_SIZE + ih_item_len(p_s_ih));
--- linux-2.6.16-rc4/fs/reiserfs/stree.c	2005-08-29 22:25:33 +0200
+++ linux-2.6.16-rc4-vs2.1.1-rc8/fs/reiserfs/stree.c	2006-02-17 23:26:32 +0100
@@ -2184,7 +2199,9 @@ int reiserfs_insert_item(struct reiserfs
 		       "reiserquota insert_item(): freeing %u id=%u type=%c",
 		       quota_bytes, inode->i_uid, head2type(p_s_ih));
 #endif
-	if (inode)
+	if (inode) {
+		DLIMIT_FREE_SPACE(inode, quota_bytes);
 		DQUOT_FREE_SPACE_NODIRTY(inode, quota_bytes);
+	}
 	return retval;
 }
--- linux-2.6.16-rc4/include/linux/vserver/dlimit.h	1970-01-01 01:00:00 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/include/linux/vserver/dlimit.h	2006-02-17 23:26:33 +0100
@@ -0,0 +1,53 @@
+#ifndef _VX_DLIMIT_H
+#define _VX_DLIMIT_H
+
+#include "switch.h"
+
+
+#ifdef	__KERNEL__
+
+/*      keep in sync with CDLIM_INFINITY	*/
+
+#define DLIM_INFINITY		(~0ULL)
+
+#include <linux/spinlock.h>
+
+struct super_block;
+
+struct dl_info {
+	struct hlist_node dl_hlist;		/* linked list of contexts */
+	struct rcu_head dl_rcu;			/* the rcu head */
+	tag_t dl_tag;				/* context tag */
+	atomic_t dl_usecnt;			/* usage count */
+	atomic_t dl_refcnt;			/* reference count */
+
+	struct super_block *dl_sb;		/* associated superblock */
+
+	spinlock_t dl_lock;			/* protect the values */
+
+	unsigned long long dl_space_used;	/* used space in bytes */
+	unsigned long long dl_space_total;	/* maximum space in bytes */
+	unsigned long dl_inodes_used;		/* used inodes */
+	unsigned long dl_inodes_total;		/* maximum inodes */
+
+	unsigned int dl_nrlmult;		/* non root limit mult */
+};
+
+struct rcu_head;
+
+extern void rcu_free_dl_info(struct rcu_head *);
+extern void unhash_dl_info(struct dl_info *);
+
+extern struct dl_info *locate_dl_info(struct super_block *, tag_t);
+
+
+struct kstatfs;
+
+extern void vx_vsi_statfs(struct super_block *, struct kstatfs *);
+
+typedef uint64_t dlsize_t;
+
+#endif	/* __KERNEL__ */
+#else	/* _VX_DLIMIT_H */
+#warning duplicate inclusion
+#endif	/* _VX_DLIMIT_H */
--- linux-2.6.16-rc4/kernel/vserver/dlimit.c	1970-01-01 01:00:00 +0100
+++ linux-2.6.16-rc4-vs2.1.1-rc8/kernel/vserver/dlimit.c	2006-02-17 23:26:33 +0100
@@ -0,0 +1,547 @@
+/*
+ *  linux/kernel/vserver/dlimit.c
+ *
+ *  Virtual Server: Context Disk Limits
+ *
+ *  Copyright (C) 2004-2005  Herbert Pötzl
+ *
+ *  V0.01  initial version
+ *  V0.02  compat32 splitup
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/namespace.h>
+#include <linux/namei.h>
+#include <linux/statfs.h>
+#include <linux/compat.h>
+#include <linux/vserver/switch.h>
+#include <linux/vs_context.h>
+#include <linux/vs_tag.h>
+#include <linux/vs_dlimit.h>
+#include <linux/vserver/dlimit_cmd.h>
+
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+/*	__alloc_dl_info()
+
+	* allocate an initialized dl_info struct
+	* doesn't make it visible (hash)			*/
+
+static struct dl_info *__alloc_dl_info(struct super_block *sb, tag_t tag)
+{
+	struct dl_info *new = NULL;
+
+	vxdprintk(VXD_CBIT(dlim, 5),
+		"alloc_dl_info(%p,%d)*", sb, tag);
+
+	/* would this benefit from a slab cache? */
+	new = kmalloc(sizeof(struct dl_info), GFP_KERNEL);
+	if (!new)
+		return 0;
+
+	memset (new, 0, sizeof(struct dl_info));
+	new->dl_tag = tag;
+	new->dl_sb = sb;
+	INIT_RCU_HEAD(&new->dl_rcu);
+	INIT_HLIST_NODE(&new->dl_hlist);
+	spin_lock_init(&new->dl_lock);
+	atomic_set(&new->dl_refcnt, 0);
+	atomic_set(&new->dl_usecnt, 0);
+
+	/* rest of init goes here */
+
+	vxdprintk(VXD_CBIT(dlim, 4),
+		"alloc_dl_info(%p,%d) = %p", sb, tag, new);
+	return new;
+}
+
+/*	__dealloc_dl_info()
+
+	* final disposal of dl_info				*/
+
+static void __dealloc_dl_info(struct dl_info *dli)
+{
+	vxdprintk(VXD_CBIT(dlim, 4),
+		"dealloc_dl_info(%p)", dli);
+
+	dli->dl_hlist.next = LIST_POISON1;
+	dli->dl_tag = -1;
+	dli->dl_sb = 0;
+
+	BUG_ON(atomic_read(&dli->dl_usecnt));
+	BUG_ON(atomic_read(&dli->dl_refcnt));
+
+	kfree(dli);
+}
+
+
+/*	hash table for dl_info hash */
+
+#define DL_HASH_SIZE	13
+
+struct hlist_head dl_info_hash[DL_HASH_SIZE];
+
+static spinlock_t dl_info_hash_lock = SPIN_LOCK_UNLOCKED;
+
+
+static inline unsigned int __hashval(struct super_block *sb, tag_t tag)
+{
+	return ((tag ^ (unsigned long)sb) % DL_HASH_SIZE);
+}
+
+
+
+/*	__hash_dl_info()
+
+	* add the dli to the global hash table
+	* requires the hash_lock to be held			*/
+
+static inline void __hash_dl_info(struct dl_info *dli)
+{
+	struct hlist_head *head;
+
+	vxdprintk(VXD_CBIT(dlim, 6),
+		"__hash_dl_info: %p[#%d]", dli, dli->dl_tag);
+	get_dl_info(dli);
+	head = &dl_info_hash[__hashval(dli->dl_sb, dli->dl_tag)];
+	hlist_add_head_rcu(&dli->dl_hlist, head);
+}
+
+/*	__unhash_dl_info()
+
+	* remove the dli from the global hash table
+	* requires the hash_lock to be held			*/
+
+static inline void __unhash_dl_info(struct dl_info *dli)
+{
+	vxdprintk(VXD_CBIT(dlim, 6),
+		"__unhash_dl_info: %p[#%d]", dli, dli->dl_tag);
+	hlist_del_rcu(&dli->dl_hlist);
+	put_dl_info(dli);
+}
+
+
+/*	__lookup_dl_info()
+
+	* requires the rcu_read_lock()
+	* doesn't increment the dl_refcnt			*/
+
+static inline struct dl_info *__lookup_dl_info(struct super_block *sb, tag_t tag)
+{
+	struct hlist_head *head = &dl_info_hash[__hashval(sb, tag)];
+	struct hlist_node *pos;
+	struct dl_info *dli;
+
+	hlist_for_each_entry_rcu(dli, pos, head, dl_hlist) {
+//	hlist_for_each_rcu(pos, head) {
+//		struct dl_info *dli =
+//			hlist_entry(pos, struct dl_info, dl_hlist);
+
+		if (dli->dl_tag == tag && dli->dl_sb == sb) {
+			return dli;
+		}
+	}
+	return NULL;
+}
+
+
+struct dl_info *locate_dl_info(struct super_block *sb, tag_t tag)
+{
+	struct dl_info *dli;
+
+	rcu_read_lock();
+	dli = get_dl_info(__lookup_dl_info(sb, tag));
+	vxdprintk(VXD_CBIT(dlim, 7),
+		"locate_dl_info(%p,#%d) = %p", sb, tag, dli);
+	rcu_read_unlock();
+	return dli;
+}
+
+void rcu_free_dl_info(struct rcu_head *head)
+{
+	struct dl_info *dli = container_of(head, struct dl_info, dl_rcu);
+	int usecnt, refcnt;
+
+	BUG_ON(!dli || !head);
+
+	usecnt = atomic_read(&dli->dl_usecnt);
+	BUG_ON(usecnt < 0);
+
+	refcnt = atomic_read(&dli->dl_refcnt);
+	BUG_ON(refcnt < 0);
+
+	vxdprintk(VXD_CBIT(dlim, 3),
+		"rcu_free_dl_info(%p)", dli);
+	if (!usecnt)
+		__dealloc_dl_info(dli);
+	else
+		printk("!!! rcu didn't free\n");
+}
+
+
+
+
+int do_addrem_dlimit(uint32_t id, const char __user *name,
+	uint32_t flags, int add)
+{
+	struct nameidata nd;
+	int ret;
+
+	ret = user_path_walk_link(name, &nd);
+	if (!ret) {
+		struct super_block *sb;
+		struct dl_info *dli;
+
+		ret = -EINVAL;
+		if (!nd.dentry->d_inode)
+			goto out_release;
+		if (!(sb = nd.dentry->d_inode->i_sb))
+			goto out_release;
+
+		if (add) {
+			dli = __alloc_dl_info(sb, id);
+			spin_lock(&dl_info_hash_lock);
+
+			ret = -EEXIST;
+			if (__lookup_dl_info(sb, id))
+				goto out_unlock;
+			__hash_dl_info(dli);
+			dli = NULL;
+		} else {
+			spin_lock(&dl_info_hash_lock);
+			dli = __lookup_dl_info(sb, id);
+
+			ret = -ESRCH;
+			if (!dli)
+				goto out_unlock;
+			__unhash_dl_info(dli);
+		}
+		ret = 0;
+	out_unlock:
+		spin_unlock(&dl_info_hash_lock);
+		if (add && dli)
+			__dealloc_dl_info(dli);
+	out_release:
+		path_release(&nd);
+	}
+	return ret;
+}
+
+int vc_add_dlimit(uint32_t id, void __user *data)
+{
+	struct vcmd_ctx_dlimit_base_v0 vc_data;
+
+	if (!vx_check(0, VX_ADMIN))
+		return -ENOSYS;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	return do_addrem_dlimit(id, vc_data.name, vc_data.flags, 1);
+}
+
+int vc_rem_dlimit(uint32_t id, void __user *data)
+{
+	struct vcmd_ctx_dlimit_base_v0 vc_data;
+
+	if (!vx_check(0, VX_ADMIN))
+		return -ENOSYS;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	return do_addrem_dlimit(id, vc_data.name, vc_data.flags, 0);
+}
+
+#ifdef	CONFIG_COMPAT
+
+int vc_add_dlimit_x32(uint32_t id, void __user *data)
+{
+	struct vcmd_ctx_dlimit_base_v0_x32 vc_data;
+
+	if (!vx_check(0, VX_ADMIN))
+		return -ENOSYS;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	return do_addrem_dlimit(id,
+		compat_ptr(vc_data.name_ptr), vc_data.flags, 1);
+}
+
+int vc_rem_dlimit_x32(uint32_t id, void __user *data)
+{
+	struct vcmd_ctx_dlimit_base_v0_x32 vc_data;
+
+	if (!vx_check(0, VX_ADMIN))
+		return -ENOSYS;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	return do_addrem_dlimit(id,
+		compat_ptr(vc_data.name_ptr), vc_data.flags, 0);
+}
+
+#endif	/* CONFIG_COMPAT */
+
+
+static inline
+int do_set_dlimit(uint32_t id, const char __user *name,
+	uint32_t space_used, uint32_t space_total,
+	uint32_t inodes_used, uint32_t inodes_total,
+	uint32_t reserved, uint32_t flags)
+{
+	struct nameidata nd;
+	int ret;
+
+	ret = user_path_walk_link(name, &nd);
+	if (!ret) {
+		struct super_block *sb;
+		struct dl_info *dli;
+
+		ret = -EINVAL;
+		if (!nd.dentry->d_inode)
+			goto out_release;
+		if (!(sb = nd.dentry->d_inode->i_sb))
+			goto out_release;
+		if ((reserved != CDLIM_KEEP &&
+			reserved > 100) ||
+			(inodes_used != CDLIM_KEEP &&
+			inodes_used > inodes_total) ||
+			(space_used != CDLIM_KEEP &&
+			space_used > space_total))
+			goto out_release;
+
+		ret = -ESRCH;
+		dli = locate_dl_info(sb, id);
+		if (!dli)
+			goto out_release;
+
+		spin_lock(&dli->dl_lock);
+
+		if (inodes_used != CDLIM_KEEP)
+			dli->dl_inodes_used = inodes_used;
+		if (inodes_total != CDLIM_KEEP)
+			dli->dl_inodes_total = inodes_total;
+		if (space_used != CDLIM_KEEP) {
+			dli->dl_space_used = space_used;
+			dli->dl_space_used <<= 10;
+		}
+		if (space_total == CDLIM_INFINITY)
+			dli->dl_space_total = DLIM_INFINITY;
+		else if (space_total != CDLIM_KEEP) {
+			dli->dl_space_total = space_total;
+			dli->dl_space_total <<= 10;
+		}
+		if (reserved != CDLIM_KEEP)
+			dli->dl_nrlmult = (1 << 10) * (100 - reserved) / 100;
+
+		spin_unlock(&dli->dl_lock);
+
+		put_dl_info(dli);
+		ret = 0;
+
+	out_release:
+		path_release(&nd);
+	}
+	return ret;
+}
+
+int vc_set_dlimit(uint32_t id, void __user *data)
+{
+	struct vcmd_ctx_dlimit_v0 vc_data;
+
+	if (!vx_check(0, VX_ADMIN))
+		return -ENOSYS;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	return do_set_dlimit(id, vc_data.name,
+		vc_data.space_used, vc_data.space_total,
+		vc_data.inodes_used, vc_data.inodes_total,
+		vc_data.reserved, vc_data.flags);
+}
+
+#ifdef	CONFIG_COMPAT
+
+int vc_set_dlimit_x32(uint32_t id, void __user *data)
+{
+	struct vcmd_ctx_dlimit_v0_x32 vc_data;
+
+	if (!vx_check(0, VX_ADMIN))
+		return -ENOSYS;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	return do_set_dlimit(id, compat_ptr(vc_data.name_ptr),
+		vc_data.space_used, vc_data.space_total,
+		vc_data.inodes_used, vc_data.inodes_total,
+		vc_data.reserved, vc_data.flags);
+}
+
+#endif	/* CONFIG_COMPAT */
+
+
+static inline
+int do_get_dlimit(uint32_t id, const char __user *name,
+	uint32_t *space_used, uint32_t *space_total,
+	uint32_t *inodes_used, uint32_t *inodes_total,
+	uint32_t *reserved, uint32_t *flags)
+{
+	struct nameidata nd;
+	int ret;
+
+	ret = user_path_walk_link(name, &nd);
+	if (!ret) {
+		struct super_block *sb;
+		struct dl_info *dli;
+
+		ret = -EINVAL;
+		if (!nd.dentry->d_inode)
+			goto out_release;
+		if (!(sb = nd.dentry->d_inode->i_sb))
+			goto out_release;
+
+		ret = -ESRCH;
+		dli = locate_dl_info(sb, id);
+		if (!dli)
+			goto out_release;
+
+		spin_lock(&dli->dl_lock);
+		*inodes_used = dli->dl_inodes_used;
+		*inodes_total = dli->dl_inodes_total;
+		*space_used = dli->dl_space_used >> 10;
+		if (dli->dl_space_total == DLIM_INFINITY)
+			*space_total = CDLIM_INFINITY;
+		else
+			*space_total = dli->dl_space_total >> 10;
+
+		*reserved = 100 - ((dli->dl_nrlmult * 100 + 512) >> 10);
+		spin_unlock(&dli->dl_lock);
+
+		put_dl_info(dli);
+		ret = -EFAULT;
+
+		ret = 0;
+	out_release:
+		path_release(&nd);
+	}
+	return ret;
+}
+
+
+int vc_get_dlimit(uint32_t id, void __user *data)
+{
+	struct vcmd_ctx_dlimit_v0 vc_data;
+	int ret;
+
+	if (!vx_check(0, VX_ADMIN))
+		return -ENOSYS;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	ret = do_get_dlimit(id, vc_data.name,
+		&vc_data.space_used, &vc_data.space_total,
+		&vc_data.inodes_used, &vc_data.inodes_total,
+		&vc_data.reserved, &vc_data.flags);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(data, &vc_data, sizeof(vc_data)))
+		return -EFAULT;
+	return 0;
+}
+
+#ifdef	CONFIG_COMPAT
+
+int vc_get_dlimit_x32(uint32_t id, void __user *data)
+{
+	struct vcmd_ctx_dlimit_v0_x32 vc_data;
+	int ret;
+
+	if (!vx_check(0, VX_ADMIN))
+		return -ENOSYS;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	ret = do_get_dlimit(id, compat_ptr(vc_data.name_ptr),
+		&vc_data.space_used, &vc_data.space_total,
+		&vc_data.inodes_used, &vc_data.inodes_total,
+		&vc_data.reserved, &vc_data.flags);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(data, &vc_data, sizeof(vc_data)))
+		return -EFAULT;
+	return 0;
+}
+
+#endif	/* CONFIG_COMPAT */
+
+
+void vx_vsi_statfs(struct super_block *sb, struct kstatfs *buf)
+{
+	struct dl_info *dli;
+	__u64 blimit, bfree, bavail;
+	__u32 ifree;
+
+	dli = locate_dl_info(sb, dx_current_tag());
+	if (!dli)
+		return;
+
+	spin_lock(&dli->dl_lock);
+	if (dli->dl_inodes_total == (unsigned long)DLIM_INFINITY)
+		goto no_ilim;
+
+	/* reduce max inodes available to limit */
+	if (buf->f_files > dli->dl_inodes_total)
+		buf->f_files = dli->dl_inodes_total;
+
+	ifree = dli->dl_inodes_total - dli->dl_inodes_used;
+	/* reduce free inodes to min */
+	if (ifree < buf->f_ffree)
+		buf->f_ffree = ifree;
+
+no_ilim:
+	if (dli->dl_space_total == DLIM_INFINITY)
+		goto no_blim;
+
+	blimit = dli->dl_space_total >> sb->s_blocksize_bits;
+
+	if (dli->dl_space_total < dli->dl_space_used)
+		bfree = 0;
+	else
+		bfree = (dli->dl_space_total - dli->dl_space_used)
+			>> sb->s_blocksize_bits;
+
+	bavail = ((dli->dl_space_total >> 10) * dli->dl_nrlmult);
+	if (bavail < dli->dl_space_used)
+		bavail = 0;
+	else
+		bavail = (bavail - dli->dl_space_used)
+			>> sb->s_blocksize_bits;
+
+	/* reduce max space available to limit */
+	if (buf->f_blocks > blimit)
+		buf->f_blocks = blimit;
+
+	/* reduce free space to min */
+	if (bfree < buf->f_bfree)
+		buf->f_bfree = bfree;
+
+	/* reduce avail space to min */
+	if (bavail < buf->f_bavail)
+		buf->f_bavail = bavail;
+
+no_blim:
+	spin_unlock(&dli->dl_lock);
+	put_dl_info(dli);
+
+	return;
+}
+
+#include <linux/module.h>
+
+EXPORT_SYMBOL_GPL(locate_dl_info);
+EXPORT_SYMBOL_GPL(rcu_free_dl_info);
+
