--- 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,