--- fs/reiserfs/bitmap.c Tue Aug 29 01:58:06 2000
+++ fs/reiserfs/bitmap.c Tue Aug 29 10:59:41 2000
@@ -12,6 +12,7 @@
#include <linux/reiserfs_fs.h>
#include <linux/locks.h>
#include <asm/bitops.h>
+#include <linux/quotaops.h>
#else
@@ -110,7 +111,7 @@
/* There would be a modest performance benefit if we write a version
to free a list of blocks at once. -Hans */
-void reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long block)
+void reiserfs_free_block (struct reiserfs_transaction_handle *th, struct inode *inode, unsigned long block, int for_unformatted)
{
struct super_block * s = th->t_super;
struct reiserfs_super_block * rs;
@@ -151,6 +152,13 @@
journal_mark_dirty (th, s, sbh);
s->s_dirt = 1;
+ if (for_unformatted) {
+ inode_sub_bytes(inode, s->s_blocksize);
+#ifdef REISERQUOTA_DEBUG
+ printk(KERN_DEBUG "reiserquota: freeing block id=%u\n", inode->i_uid);
+#endif
+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
+ }
}
@@ -288,6 +296,7 @@
return CARRY_ON if everything is ok
return NO_DISK_SPACE if out of disk space
+ return QUOTA_EXCEEDED if disk quota is exceeded (can only happen for unformatted nodes)
return NO_MORE_UNUSED_CONTIGUOUS_BLOCKS if the block we found is not contiguous to the last one
return block numbers found, in the array free_blocknrs. assumes
@@ -307,6 +316,7 @@
/* This function is NOT SCHEDULE-SAFE! */
static int do_reiserfs_new_blocknrs (struct reiserfs_transaction_handle *th,
+ struct inode *inode,
unsigned long * free_blocknrs,
unsigned long search_start,
int amount_needed, int priority,
@@ -315,6 +325,7 @@
{
struct super_block * s = th->t_super;
int i, j;
+ int quota_ret = 0;
unsigned long * block_list_start = free_blocknrs;
int init_amount_needed = amount_needed;
unsigned long new_block = 0 ;
@@ -365,9 +376,11 @@
-Hans */
free_and_return:
for ( ; block_list_start != free_blocknrs; block_list_start++) {
- reiserfs_free_block (th, *block_list_start);
+ reiserfs_free_block (th, inode, *block_list_start, for_unformatted);
*block_list_start = 0;
}
+ if (quota_ret)
+ return QUOTA_EXCEEDED;
if (for_prealloc)
return NO_MORE_UNUSED_CONTIGUOUS_BLOCKS;
else
@@ -417,7 +430,18 @@
amount_needed++ ;
continue ;
}
-
+ if (for_unformatted) { /* We directly account quotas only for unformatted nodes */
+#ifdef REISERQUOTA_DEBUG
+ printk(KERN_DEBUG "reiserquota: allocating block id=%u\n", inode->i_uid);
+#endif
+ if (for_prealloc)
+ quota_ret = DQUOT_PREALLOC_BLOCK(inode->i_sb, inode, 1);
+ else
+ quota_ret = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
+ if (quota_ret) /* Quota exceeded? */
+ goto free_and_return;
+ inode_add_bytes(inode, s->s_blocksize);
+ }
reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[i], 1) ;
@@ -432,6 +456,13 @@
if (reiserfs_test_and_set_le_bit (j, SB_AP_BITMAP (s)[i]->b_data)) {
reiserfs_warning("vs-4150: reiserfs_new_blocknrs, block not free");
reiserfs_restore_prepared_buffer(s, SB_AP_BITMAP(s)[i]) ;
+ if (for_unformatted) {
+#ifdef REISERQUOTA_DEBUG
+ printk(KERN_DEBUG "reiserquota: freeing block id=%u\n", inode->i_uid);
+#endif
+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
+ inode_sub_bytes(inode, s->s_blocksize);
+ }
amount_needed++ ;
continue ;
}
@@ -452,12 +483,12 @@
// this is called only by get_empty_nodes with for_preserve_list==0
int reiserfs_new_blocknrs (struct reiserfs_transaction_handle *th, unsigned long * free_blocknrs,
unsigned long search_start, int amount_needed) {
- return do_reiserfs_new_blocknrs(th, free_blocknrs, search_start, amount_needed, 0/*for_preserve_list-priority*/, 0/*for_formatted*/, 0/*for_prealloc */) ;
+ return do_reiserfs_new_blocknrs(th, NULL, free_blocknrs, search_start, amount_needed, 0/*for_preserve_list-priority*/, 0/*for_formatted*/, 0/*for_prealloc */) ;
}
// called by get_new_buffer and by reiserfs_get_block with amount_needed == 1 and for_preserve_list == 0
-int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle *th, unsigned long * free_blocknrs,
+int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle *th, struct inode *inode, unsigned long * free_blocknrs,
unsigned long search_start) {
#if 0
#ifdef REISERFS_PREALLOCATE
@@ -466,7 +497,7 @@
#endif
#endif
- return do_reiserfs_new_blocknrs(th, free_blocknrs, search_start,
+ return do_reiserfs_new_blocknrs(th, inode, free_blocknrs, search_start,
1/*amount_needed*/,
0/*for_preserve_list-priority*/,
1/*for formatted*/,
@@ -526,7 +557,7 @@
{
if ( search_start < border ) search_start=border;
- ret = do_reiserfs_new_blocknrs(th, free_blocknrs, search_start,
+ ret = do_reiserfs_new_blocknrs(th, p_s_inode, free_blocknrs, search_start,
1/*amount_needed*/,
/* someone please remove the preserve list detritus. -Hans */
0/*for_preserve_list-priority*/,
@@ -560,7 +591,7 @@
n = 8;
blks = n-1;
for (i=0; i<n; i++) {
- ret = do_reiserfs_new_blocknrs(th, free_blocknrs, search_start,
+ ret = do_reiserfs_new_blocknrs(th, p_s_inode, free_blocknrs, search_start,
1/*amount_needed*/,
0/*for_preserve_list-priority*/,
1/*for_formatted*/,
@@ -577,7 +608,7 @@
/* this should be caught by new_blocknrs now, checking code */
/* use your email name of yura, not yr, and I don't believe you have written 4050 error messages.... -Hans */
reiserfs_warning("yura-4160, reiserfs_new_unf_blocknrs2: pre-allocated not contiguous set of blocks!\n") ;
- reiserfs_free_block(th, allocated[i]);
+ reiserfs_free_block(th, p_s_inode, allocated[i], 1);
blks = i-1;
break;
}
@@ -620,7 +651,7 @@
{
if (inode->u.reiserfs_i.i_prealloc_count > 0) {
while (inode->u.reiserfs_i.i_prealloc_count--) {
- reiserfs_free_block(th,inode->u.reiserfs_i.i_prealloc_block);
+ reiserfs_free_block(th,inode,inode->u.reiserfs_i.i_prealloc_block,1);
inode->u.reiserfs_i.i_prealloc_block++;
}
}
--- fs/reiserfs/buffer2.c Tue Aug 29 01:58:06 2000
+++ fs/reiserfs/buffer2.c Fri Jul 21 15:14:06 2000
@@ -398,6 +398,7 @@
/* The function is NOT SCHEDULE-SAFE! */
int get_new_buffer(
struct reiserfs_transaction_handle *th,
+ struct inode *inode,
struct buffer_head * p_s_bh,
struct buffer_head ** pp_s_new_bh,
struct path * p_s_path
@@ -406,8 +407,10 @@
int n_repeat;
struct super_block * p_s_sb = th->t_super;
- if ( (n_repeat = reiserfs_new_unf_blocknrs (th, &n_new_blocknumber, p_s_bh->b_blocknr)) == NO_DISK_SPACE )
+ if ( (n_repeat = reiserfs_new_unf_blocknrs (th, inode, &n_new_blocknumber, p_s_bh->b_blocknr)) == NO_DISK_SPACE )
return NO_DISK_SPACE;
+ if (n_repeat == QUOTA_EXCEEDED)
+ return QUOTA_EXCEEDED;
*pp_s_new_bh = reiserfs_getblk(p_s_sb->s_dev, n_new_blocknumber, p_s_sb->s_blocksize);
if (atomic_read (&(*pp_s_new_bh)->b_count) > 1) {
--- fs/reiserfs/do_balan.c Tue Aug 29 01:58:06 2000
+++ fs/reiserfs/do_balan.c Fri Jul 21 14:10:54 2000
@@ -1640,7 +1640,7 @@
if (buffer_dirty (tb->thrown[i]))
printk ("free_thrown deals with dirty buffer %ld\n", blocknr);
brelse(tb->thrown[i]) ; /* incremented in store_thrown */
- reiserfs_free_block (tb->transaction_handle, blocknr);
+ reiserfs_free_block (tb->transaction_handle, NULL, blocknr, 0);
}
}
}
--- fs/reiserfs/fix_node.c Tue Aug 29 01:58:06 2000
+++ fs/reiserfs/fix_node.c Tue Aug 29 03:12:24 2000
@@ -2741,7 +2741,7 @@
/* de-allocated block which was not used by balancing and
bforget about buffer for it */
brelse (tb->FEB[i]);
- reiserfs_free_block (tb->transaction_handle, blocknr);
+ reiserfs_free_block (tb->transaction_handle, NULL, blocknr, 0);
}
if (tb->used[i]) {
/* release used as new nodes including a new root */
--- fs/reiserfs/inode.c Tue Aug 29 01:58:06 2000
+++ fs/reiserfs/inode.c Tue Aug 29 03:14:04 2000
@@ -7,6 +7,7 @@
#include <linux/reiserfs_fs.h>
#include <linux/locks.h>
#include <linux/smp_lock.h>
+#include <linux/quotaops.h>
#include <asm/uaccess.h>
#else
@@ -29,6 +30,10 @@
lock_kernel() ;
+ /* Quota might not be initialized when we get some just partly created inode and in that
+ case this inode also wasn't counted to quota. */
+ if (IS_QUOTAINIT(inode))
+ DQUOT_FREE_INODE(inode->i_sb, inode);
/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
if (INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
down (&inode->i_sem);
@@ -449,7 +454,7 @@
#ifdef REISERFS_PREALLOCATE
repeat = reiserfs_new_unf_blocknrs2 (&th, inode, &allocated_block_nr, tag);
#else
- repeat = reiserfs_new_unf_blocknrs (&th, &allocated_block_nr, tag);
+ repeat = reiserfs_new_unf_blocknrs (&th, inode, &allocated_block_nr, tag);
#endif
if (repeat == NO_DISK_SPACE) {
@@ -461,14 +466,21 @@
#ifdef REISERFS_PREALLOCATE
repeat = reiserfs_new_unf_blocknrs2 (&th, inode, &allocated_block_nr, tag);
#else
- repeat = reiserfs_new_unf_blocknrs (&th, &allocated_block_nr, tag);
+ repeat = reiserfs_new_unf_blocknrs (&th, inode, &allocated_block_nr, tag);
#endif
- if (repeat != NO_DISK_SPACE) {
+ if (repeat != NO_DISK_SPACE && repeat != QUOTA_EXCEEDED) {
allocated_block_nr = 0 ; /* just in case it got changed somehow */
goto research ;
}
- retval = -ENOSPC;
+ if (repeat == QUOTA_EXCEEDED)
+ retval = -EDQUOT;
+ else
+ retval = -ENOSPC;
+ goto failure;
+ }
+ if (repeat == QUOTA_EXCEEDED) {
+ retval = -EDQUOT;
goto failure;
}
@@ -532,17 +544,15 @@
set_cpu_key_k_offset (&tmp_key, 1);
PATH_LAST_POSITION(&path) ++;
- retval = reiserfs_insert_item (&th, &path, &tmp_key, &tmp_ih, (char *)&unp);
+ retval = reiserfs_insert_item (&th, &path, &tmp_key, &tmp_ih, inode, (char *)&unp);
if (retval) {
- reiserfs_free_block (&th, allocated_block_nr);
+ reiserfs_free_block (&th, inode, allocated_block_nr, 1);
#ifdef REISERFS_PREALLOCATE
reiserfs_discard_prealloc (&th, inode);
#endif
goto failure; // retval == -ENOSPC or -EIO or -EEXIST
}
- if (unp)
- inode->i_blocks += inode->i_sb->s_blocksize / 512;
//mark_tail_converted (inode);
} else if (is_direct_le_ih (ih)) {
/* direct item has to be converted */
@@ -565,15 +575,15 @@
fs_gen = get_generation (inode->i_sb);
- get_new_buffer (&th, bh, &unbh, &path);
+ get_new_buffer (&th, inode, bh, &unbh, &path);
if (!unbh) {
/* restart_transaction calls pathrelse for us */
restart_transaction(&th, inode, &path) ;
- get_new_buffer (&th, bh, &unbh, &path);
+ get_new_buffer (&th, inode, bh, &unbh, &path);
if (unbh) {
goto search_again ;
}
- reiserfs_free_block (&th, allocated_block_nr);
+ reiserfs_free_block (&th, inode, allocated_block_nr, 1);
#ifdef REISERFS_PREALLOCATE
reiserfs_discard_prealloc (&th, inode);
@@ -596,13 +606,13 @@
unsigned long tmp = unbh->b_blocknr;
bforget (unbh);
- reiserfs_free_block (&th, tmp);
+ reiserfs_free_block (&th, inode, tmp, 1);
#ifdef REISERFS_PREALLOCATE
reiserfs_discard_prealloc (&th, inode);
#endif
}
- reiserfs_free_block (&th, allocated_block_nr);
+ reiserfs_free_block (&th, inode, allocated_block_nr, 1);
#ifdef REISERFS_PREALLOCATE
reiserfs_discard_prealloc (&th, inode);
@@ -626,7 +636,6 @@
allow_flush_page_lock(inode->i_sb, unbh->b_page, inode) ;
brelse (unbh);
}
- //inode->i_blocks += inode->i_sb->s_blocksize / 512;
//mark_tail_converted (inode);
} else {
/* append indirect item with holes if needed, when appending
@@ -656,17 +665,15 @@
} else {
/* paste hole to the indirect item */
}
- retval = reiserfs_paste_into_item (&th, &path, &tmp_key, (char *)&un, UNFM_P_SIZE);
+ retval = reiserfs_paste_into_item (&th, &path, &tmp_key, inode, (char *)&un, UNFM_P_SIZE);
if (retval) {
- reiserfs_free_block (&th, allocated_block_nr);
+ reiserfs_free_block (&th, inode, allocated_block_nr, 1);
#ifdef REISERFS_PREALLOCATE
reiserfs_discard_prealloc (&th, inode);
#endif
goto failure;
}
- if (un.unfm_nodenum)
- inode->i_blocks += inode->i_sb->s_blocksize / 512;
//mark_tail_converted (inode);
}
@@ -1064,7 +1071,7 @@
/* stat data of new object is inserted already, this inserts the item
containing "." and ".." entries */
-static int reiserfs_new_directory (struct reiserfs_transaction_handle *th,
+static int reiserfs_new_directory (struct reiserfs_transaction_handle *th, struct inode *inode,
struct item_head * ih, struct path * path, const struct inode * dir)
{
struct super_block * sb = th->t_super;
@@ -1108,13 +1115,14 @@
}
/* insert item, that is empty directory item */
- return reiserfs_insert_item (th, path, &key, ih, body);
+ return reiserfs_insert_item (th, path, &key, ih, inode, body);
}
/* stat data of object has been inserted, this inserts the item
containing the body of symlink */
static int reiserfs_new_symlink (struct reiserfs_transaction_handle *th,
+ struct inode *inode, /* Inode of symlink */
struct item_head * ih,
struct path * path, const char * symname, int item_len)
{
@@ -1144,7 +1152,7 @@
}
/* insert item, that is body of symlink */
- return reiserfs_insert_item (th, path, &key, ih, symname);
+ return reiserfs_insert_item (th, path, &key, ih, inode, symname);
}
@@ -1221,7 +1229,6 @@
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_size = i_size;
- inode->i_blocks = (inode->i_size + 511) >> 9;
inode->u.reiserfs_i.i_first_direct_byte = S_ISLNK(mode) ? 1 :
U32_MAX/*NO_BYTES_IN_DIRECT_ITEM*/;
@@ -1235,6 +1242,16 @@
inode->i_blksize = PAGE_SIZE;
inode->i_dev = sb->s_dev;
+ // initialize quotas in inode
+ DQUOT_INIT(inode);
+ if (DQUOT_ALLOC_INODE(inode->i_sb, inode)) {
+ DQUOT_DROP(inode); /* Drop quotas for inode so that on delete no quota will be decremented */
+ inode->i_nlink = 0;
+ iput(inode);
+ *err = -EDQUOT;
+ reiserfs_check_path(&path_to_key);
+ return NULL;
+ }
// store in in-core inode the key of stat data and version all
// object items will have (directory items will have old offset
// format, other new objects will consist of new items)
@@ -1245,7 +1262,7 @@
inode_items_version (inode) = ITEM_VERSION_2;
/* insert the stat data into the tree */
- retval = reiserfs_insert_item (th, &path_to_key, &key, &ih, (char *)(&sd));
+ retval = reiserfs_insert_item (th, &path_to_key, &key, &ih, inode, (char *)(&sd));
if (retval) {
iput (inode);
*err = retval;
@@ -1255,14 +1272,14 @@
if (S_ISDIR(mode)) {
/* insert item with "." and ".." */
- retval = reiserfs_new_directory (th, &ih, &path_to_key, dir);
+ retval = reiserfs_new_directory (th, inode, &ih, &path_to_key, dir);
}
if (S_ISLNK(mode)) {
/* insert body of symlink */
if (!old_format_only (sb))
i_size = ROUND_UP(i_size);
- retval = reiserfs_new_symlink (th, &ih, &path_to_key, symname, i_size);
+ retval = reiserfs_new_symlink (th, inode, &ih, &path_to_key, symname, i_size);
}
if (retval) {
inode->i_nlink = 0;
--- fs/reiserfs/stree.c Tue Aug 29 01:58:06 2000
+++ fs/reiserfs/stree.c Tue Aug 29 11:14:49 2000
@@ -60,6 +60,7 @@
#include <linux/pagemap.h>
#include <linux/reiserfs_fs.h>
#include <linux/smp_lock.h>
+#include <linux/quotaops.h>
#else
@@ -1237,8 +1238,7 @@
*p_n_unfm_pointer = 0;
journal_mark_dirty (th, p_s_sb, p_s_bh);
bforget (p_s_un_bh);
- inode->i_blocks -= p_s_sb->s_blocksize / 512;
- reiserfs_free_block(th, tmp);
+ reiserfs_free_block(th, inode, tmp, 1);
if ( item_moved (&s_ih, p_s_path) ) {
need_research = 1;
break ;
@@ -1373,12 +1373,39 @@
item [--i] = 0;
}
+#ifdef REISERQUOTA_DEBUG
+char key2type(struct key *ih)
+{
+ if (is_direntry_le_key(2, ih))
+ return 'd';
+ if (is_direct_le_key(2, ih))
+ return 'D';
+ if (is_indirect_le_key(2, ih))
+ return 'i';
+ if (is_statdata_le_key(2, ih))
+ return 's';
+ return 'u';
+}
+
+char head2type(struct item_head *ih)
+{
+ if (is_direntry_le_ih(ih))
+ return 'd';
+ if (is_direct_le_ih(ih))
+ return 'D';
+ if (is_indirect_le_ih(ih))
+ return 'i';
+ if (is_statdata_le_ih(ih))
+ return 's';
+ return 'u';
+}
+#endif
/* Delete object item. */
int reiserfs_delete_item (struct reiserfs_transaction_handle *th,
struct path * p_s_path, /* Path to the deleted item. */
struct cpu_key * p_s_item_key, /* Key to search for the deleted item. */
- struct inode * p_s_inode,/* inode is here just to update i_blocks */
+ struct inode * p_s_inode,/* inode is here to update i_blocks and quotas */
struct buffer_head * p_s_un_bh) /* NULL or unformatted node pointer. */
{
struct super_block * p_s_sb = p_s_inode->i_sb;
@@ -1458,6 +1485,11 @@
B_I_PITEM(PATH_PLAST_BUFFER(p_s_path), &s_ih), n_ret_value);
}
+ inode_sub_bytes(p_s_inode, s_ih.ih_item_len);
+#ifdef REISERQUOTA_DEBUG
+ printk(KERN_DEBUG "reiserquota delete_item(): freeing %u, id=%u type=%c\n", s_ih.ih_item_len, p_s_inode->i_uid, head2type(&s_ih));
+#endif
+ DQUOT_FREE_SPACE(p_s_inode->i_sb, p_s_inode, s_ih.ih_item_len);
/* Perform balancing after all resources have been collected at once. */
do_balance(&s_del_balance, NULL, NULL, M_DELETE);
@@ -1503,11 +1535,12 @@
/* this deletes item which never gets split */
static void reiserfs_delete_solid_item (struct reiserfs_transaction_handle *th,
+ struct inode *inode,
struct key * key)
{
struct tree_balance tb;
INITIALIZE_PATH (path);
- int item_len;
+ int item_len = 0; /* Just to prevent bad gcc warning */
int tb_init = 0 ;
struct cpu_key cpu_key;
int retval;
@@ -1538,6 +1571,11 @@
continue;
if (retval == CARRY_ON) {
+#ifdef REISERQUOTA_DEBUG
+ printk(KERN_DEBUG "reiserquota delete_solid_item(): freeing %u id=%u type=%c\n", item_len, inode->i_uid, key2type(key));
+#endif
+ inode_sub_bytes(inode, item_len);
+ DQUOT_FREE_SPACE(inode->i_sb, inode, item_len);
do_balance (&tb, 0, 0, M_DELETE);
break;
}
@@ -1569,7 +1607,7 @@
reiserfs_warning("clm-4001: deleting inode with link count==%d\n", inode->i_nlink) ;
}
#endif
- reiserfs_delete_solid_item (th, INODE_PKEY (inode));
+ reiserfs_delete_solid_item (th, inode, INODE_PKEY (inode));
}
@@ -1758,6 +1796,15 @@
n_ret_value = calc_deleted_bytes_number(&s_cut_balance, c_mode);
else
n_ret_value = retval2;
+
+ { /* Update quotas and used space */
+ struct item_head *ih = PATH_PITEM_HEAD(s_cut_balance.tb_path);
+ inode_sub_bytes(p_s_inode, c_mode == M_DELETE ? ih->ih_item_len : -s_cut_balance.insert_size[0]);
+#ifdef REISERQUOTA_DEBUG
+ printk(KERN_DEBUG "reiserquota cut_from_item(): freeing %u id=%u type=%c\n", c_mode == M_DELETE ? ih->ih_item_len : -s_cut_balance.insert_size[0], p_s_inode->i_uid, head2type(ih));
+#endif
+ DQUOT_FREE_SPACE(p_s_inode->i_sb, p_s_inode, c_mode == M_DELETE ? ih->ih_item_len : -s_cut_balance.insert_size[0]);
+ }
if ( c_mode == M_DELETE ) {
struct item_head * p_le_ih = PATH_PITEM_HEAD (s_cut_balance.tb_path);
@@ -1767,10 +1814,8 @@
item(s) */
// FIXME: this is to keep 3.5 happy
p_s_inode->u.reiserfs_i.i_first_direct_byte = U32_MAX;
- p_s_inode->i_blocks -= p_s_sb->s_blocksize / 512;
}
}
-
#ifdef CONFIG_REISERFS_CHECK
if (n_is_inode_locked) {
struct item_head * le_ih = PATH_PITEM_HEAD (s_cut_balance.tb_path);
@@ -1817,7 +1862,7 @@
set_le_key_k_offset (ITEM_VERSION_1, INODE_PKEY (inode), DOT_OFFSET);
set_le_key_k_type (ITEM_VERSION_1, INODE_PKEY (inode), TYPE_DIRENTRY);
- reiserfs_delete_solid_item (th, INODE_PKEY (inode));
+ reiserfs_delete_solid_item (th, inode, INODE_PKEY (inode));
set_le_key_k_offset (ITEM_VERSION_1, INODE_PKEY (inode), SD_OFFSET);
set_le_key_k_type (ITEM_VERSION_1, INODE_PKEY (inode), TYPE_STAT_DATA);
@@ -1991,6 +2036,7 @@
int reiserfs_paste_into_item (struct reiserfs_transaction_handle *th,
struct path * p_s_search_path, /* Path to the pasted item. */
struct cpu_key * p_s_key, /* Key to search for the needed item.*/
+ struct inode * inode, /* Inode item belongs to */
const char * p_c_body, /* Pointer to the bytes to paste. */
int n_pasted_size) /* Size of pasted bytes. */
{
@@ -2014,6 +2060,15 @@
check_research_for_paste (p_s_search_path, p_s_key);
#endif
}
+ if (retval == CARRY_ON) {
+#ifdef REISERQUOTA_DEBUG
+ printk(KERN_DEBUG "reiserquota paste_into_item(): allocating %u id=%u type=%c\n", n_pasted_size, inode->i_uid, key2type(&(p_s_key->on_disk_key)));
+#endif
+ if (DQUOT_ALLOC_SPACE(inode->i_sb, inode, n_pasted_size))
+ retval = QUOTA_EXCEEDED;
+ else
+ inode_add_bytes(inode, n_pasted_size);
+ }
/* Perform balancing after all resources are collected by fix_nodes, and
accessing them will not risk triggering schedule. */
@@ -2023,7 +2078,14 @@
}
unfix_nodes(&s_paste_balance);
- return (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO;
+ switch (retval) {
+ case NO_DISK_SPACE:
+ return -ENOSPC;
+ case QUOTA_EXCEEDED:
+ return -EDQUOT;
+ default:
+ return -EIO;
+ }
}
@@ -2032,6 +2094,7 @@
struct path * p_s_path, /* Path to the inserteded item. */
struct cpu_key * key,
struct item_head * p_s_ih, /* Pointer to the item header to insert.*/
+ struct inode * inode, /* Inode item belongs to */
const char * p_c_body) /* Pointer to the bytes to insert. */
{
struct tree_balance s_ins_balance;
@@ -2058,6 +2121,16 @@
return -EEXIST;
}
}
+
+ if (retval == CARRY_ON) {
+#ifdef REISERQUOTA_DEBUG
+ printk(KERN_DEBUG "reiserquota insert_item(): allocating %u id=%u type=%c\n", p_s_ih->ih_item_len, inode->i_uid, head2type(p_s_ih));
+#endif
+ if (DQUOT_ALLOC_SPACE(inode->i_sb, inode, p_s_ih->ih_item_len))
+ retval = QUOTA_EXCEEDED;
+ else
+ inode_add_bytes(inode, p_s_ih->ih_item_len);
+ }
/* make balancing after all resources will be collected at a time */
if ( retval == CARRY_ON ) {
@@ -2066,7 +2139,14 @@
}
unfix_nodes(&s_ins_balance);
- return (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO;
+ switch (retval) {
+ case NO_DISK_SPACE:
+ return -ENOSPC;
+ case QUOTA_EXCEEDED:
+ return -EDQUOT;
+ default:
+ return -EIO;
+ }
}
--- fs/reiserfs/namei.c Tue Aug 29 01:58:06 2000
+++ fs/reiserfs/namei.c Tue Aug 29 03:15:14 2000
@@ -7,6 +7,7 @@
#include <linux/sched.h>
#include <linux/reiserfs_fs.h>
#include <linux/smp_lock.h>
+#include <linux/quotaops.h>
#else
@@ -460,7 +461,7 @@
}
/* perform the insertion of the entry that we have prepared */
- retval = reiserfs_paste_into_item (th, &path, &entry_key, buffer, paste_size);
+ retval = reiserfs_paste_into_item (th, &path, &entry_key, dir, buffer, paste_size);
if (buffer != small_buf)
reiserfs_kfree (buffer, buflen, dir->i_sb);
if (retval) {
@@ -469,7 +470,6 @@
}
dir->i_size += paste_size;
- dir->i_blocks = ((dir->i_size + 511) >> 9);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
if (!S_ISDIR (inode->i_mode) && visible)
// reiserfs_mkdir or reiserfs_rename will do that by itself
@@ -714,6 +714,7 @@
if (retval < 0)
goto end_rmdir;
+ DQUOT_INIT(inode); /* init quotas on deleted directory - it will be truncated... */
if (inode->i_nlink != 2)
printk ("reiserfs_rmdir: empty directory has nlink != 2 (%d)\n", inode->i_nlink);
@@ -723,7 +724,6 @@
dir->i_nlink --;
dir->i_size -= (DEH_SIZE + de.de_entrylen);
- dir->i_blocks = ((dir->i_size + 511) >> 9);
reiserfs_update_sd (&th, dir);
pop_journal_writer(windex) ;
@@ -786,12 +786,12 @@
if (retval < 0)
goto end_unlink;
+ DQUOT_INIT(inode); /* Initialize quotas - inode might be truncated... */
inode->i_nlink--;
inode->i_ctime = CURRENT_TIME;
reiserfs_update_sd (&th, inode);
dir->i_size -= (de.de_entrylen + DEH_SIZE);
- dir->i_blocks = ((dir->i_size + 511) >> 9);
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
reiserfs_update_sd (&th, dir);
@@ -1043,6 +1043,8 @@
return -EMLINK;
}
+ if (new_inode)
+ DQUOT_INIT(new_inode); /* Initialize quotas on inode - it will be unlinked */
journal_begin(&th, old_dir->i_sb, jbegin_count) ;
windex = push_journal_writer("reiserfs_rename") ;
@@ -1169,7 +1171,6 @@
reiserfs_warning ("vs-: reiserfs_rename: coudl not cut old name. Fsck later?\n");
old_dir->i_size -= DEH_SIZE + old_de.de_entrylen;
- old_dir->i_blocks = ((old_dir->i_size + 511) >> 9);
reiserfs_update_sd (&th, old_dir);
reiserfs_update_sd (&th, new_dir);
--- fs/reiserfs/super.c Tue Aug 29 01:58:06 2000
+++ fs/reiserfs/super.c Tue Aug 29 03:17:06 2000
@@ -173,7 +173,7 @@
printk("reiserfs: hash option requires a value\n");
return 0 ;
}
- } else {
+ } else if (strcmp (this_char, "usrquota") && strcmp (this_char, "grpquota")) { /* Ignore quota options */
printk ("reiserfs: Unrecognized mount option %s\n", this_char);
return 0;
}
--- fs/reiserfs/tail_conversion.c Tue Aug 29 01:58:06 2000
+++ fs/reiserfs/tail_conversion.c Tue Aug 29 03:23:17 2000
@@ -75,11 +75,11 @@
set_ih_free_space (&ind_ih, 0); /* delete at nearest future */
ind_ih.ih_item_len = cpu_to_le16 (UNFM_P_SIZE);
PATH_LAST_POSITION (path)++;
- n_retval = reiserfs_insert_item (th, path, &end_key, &ind_ih,
+ n_retval = reiserfs_insert_item (th, path, &end_key, &ind_ih, inode,
(char *)&unfm_ptr);
} else {
/* Paste into last indirect item of an object. */
- n_retval = reiserfs_paste_into_item(th, path, &end_key,
+ n_retval = reiserfs_paste_into_item(th, path, &end_key, inode,
(char *)&unfm_ptr, UNFM_P_SIZE);
}
if ( n_retval ) {
@@ -280,7 +280,7 @@
set_cpu_key_k_type (&key, TYPE_DIRECT);
key.key_length = 4;
/* Insert tail as new direct item in the tree */
- if ( reiserfs_insert_item(th, p_s_path, &key, &s_ih,
+ if ( reiserfs_insert_item(th, p_s_path, &key, &s_ih, p_s_inode,
tail ? tail : NULL) < 0 ) {
/* No disk memory. So we can not convert last unformatted node
to the direct item. In this case we used to adjust
@@ -308,7 +308,6 @@
/* We have inserted new direct item and must remove last
unformatted node. */
- p_s_inode->i_blocks += (p_s_sb->s_blocksize / 512);
*p_c_mode = M_CUT;
/* we store position of first direct item in the in-core inode */
--- fs/reiserfs/ioctl.c Tue Aug 29 03:39:03 2000
+++ fs/reiserfs/ioctl.c Tue Aug 29 03:38:23 2000
@@ -76,7 +76,7 @@
unsigned long tmp = unbh->b_blocknr;
bforget (unbh);
/* free what has been allocated by get_new_buffer */
- reiserfs_free_block (&th, tmp);
+ reiserfs_free_block (&th, inode, tmp, 1);
}
} else {
ih = get_ih (&path);
@@ -85,11 +85,14 @@
bh = get_bh (&path);
/* allocate new unformatted node to place tail */
if (!unbh) {
- retval = get_new_buffer (&th, bh, &unbh, &path);
+ retval = get_new_buffer (&th, inode, bh, &unbh, &path);
if (!unbh) {
/* can't allocate block */
pathrelse (&path);
- exitcode = -ENOSPC;
+ if (retval == QUOTA_EXCEEDED)
+ exitcode = -EDQUOT;
+ else
+ exitcode = -ENOSPC;
goto finish;
}
if (retval & SCHEDULE_OCCURRED) {
@@ -108,7 +111,7 @@
unsigned long tmp = unbh->b_blocknr;
bforget (unbh);
/* free what has been allocated by get_new_buffer */
- reiserfs_free_block (&th, tmp);
+ reiserfs_free_block (&th, inode, tmp, 1);
inode->u.reiserfs_i.nopack = 0;
exitcode = -ENOSPC; /* FIXME: what error has to be returned here? -az */
goto finish;
--- include/linux/reiserfs_fs.h Tue Aug 29 01:58:07 2000
+++ include/linux/reiserfs_fs.h Tue Aug 29 03:08:17 2000
@@ -130,6 +130,7 @@
#define NO_DISK_SPACE -3
#define NO_BALANCING_NEEDED (-4)
#define NO_MORE_UNUSED_CONTIGUOUS_BLOCKS (-5)
+#define QUOTA_EXCEEDED -6
//#define SCHEDULE_OCCURRED 1
//#define PATH_INCORRECT 2
@@ -1636,11 +1637,14 @@
int reiserfs_insert_item (struct reiserfs_transaction_handle *th,
struct path * path,
struct cpu_key * key,
- struct item_head * ih, const char * body);
+ struct item_head * ih,
+ struct inode *inode, const char * body);
+
int reiserfs_paste_into_item (struct reiserfs_transaction_handle *th,
struct path * path,
struct cpu_key * key,
+ struct inode *inode,
const char * body, int paste_size);
int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
@@ -1815,7 +1819,7 @@
extern struct inode_operations reiserfs_file_inode_operations;
extern struct file_operations reiserfs_file_operations;
extern struct address_space_operations reiserfs_address_space_operations ;
-int get_new_buffer (struct reiserfs_transaction_handle *th, struct buffer_head *,
+int get_new_buffer (struct reiserfs_transaction_handle *th, struct inode *, struct buffer_head *,
struct buffer_head **, struct path *);
@@ -1894,10 +1898,11 @@
/* bitmap.c */
int is_reusable (struct super_block * s, unsigned long block, int bit_value);
-void reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long);
+void reiserfs_free_block (struct reiserfs_transaction_handle *th, struct inode *inode, unsigned long, int);
int reiserfs_new_blocknrs (struct reiserfs_transaction_handle *th,
unsigned long * pblocknrs, unsigned long start_from, int amount_needed);
int reiserfs_new_unf_blocknrs (struct reiserfs_transaction_handle *th,
+ struct inode *inode,
unsigned long * pblocknr, unsigned long start_from);
#ifdef REISERFS_PREALLOCATE
int reiserfs_new_unf_blocknrs2 (struct reiserfs_transaction_handle *th,