--- 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 #include #include +#include #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; iu.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 #include #include +#include #include #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 #include #include +#include #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 #include #include +#include #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,