%patch
Index: linux.d/fs/reiserfs/tail_conversion.c
===================================================================
--- linux.d.orig/fs/reiserfs/tail_conversion.c 2003-12-03 19:38:26.000000000 -0500
+++ linux.d/fs/reiserfs/tail_conversion.c 2003-12-03 19:59:27.000000000 -0500
@@ -66,11 +66,11 @@
set_ih_free_space (&ind_ih, 0); /* delete at nearest future */
put_ih_item_len( &ind_ih, 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 ) {
@@ -228,7 +228,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
@@ -241,13 +241,15 @@
}
kunmap(page) ;
+ /* make sure to get the i_blocks changes from reiserfs_insert_item */
+ reiserfs_update_sd(th, p_s_inode);
+
// note: we have now the same as in above direct2indirect
// conversion: there are two keys which have matching first three
// key components. They only differ by the fouhth one.
/* 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 */
Index: linux.d/fs/reiserfs/bitmap.c
===================================================================
--- linux.d.orig/fs/reiserfs/bitmap.c 2003-12-03 19:32:59.000000000 -0500
+++ linux.d/fs/reiserfs/bitmap.c 2003-12-03 19:59:27.000000000 -0500
@@ -10,6 +10,7 @@
#include <linux/errno.h>
#include <linux/locks.h>
#include <linux/kernel.h>
+#include <linux/quotaops.h>
void reiserfs_free_block (struct reiserfs_transaction_handle *th,
- unsigned long block) {
+ struct inode *inode, unsigned long block,
+ int for_unformatted)
+{
struct super_block * s = th->t_super;
RFALSE(!s, "vs-4061: trying to free block on nonexistent device");
RFALSE(is_reusable (s, block, 1) == 0, "vs-4071: can not free such block");
/* mark it before we clear it, just in case */
journal_mark_freed(th, s, block) ;
- _reiserfs_free_block(th, block) ;
+ _reiserfs_free_block(th, inode, block, for_unformatted) ;
}
/* preallocated blocks don't need to be run through journal_mark_freed */
void reiserfs_free_prealloc_block (struct reiserfs_transaction_handle *th,
- unsigned long block) {
+ struct inode *inode,
+ unsigned long block)
+{
RFALSE(!th->t_super, "vs-4060: trying to free block on nonexistent device");
RFALSE(is_reusable (th->t_super, block, 1) == 0, "vs-4070: can not free such block");
- _reiserfs_free_block(th, block) ;
+ _reiserfs_free_block(th, inode, block, 1) ;
}
static void __discard_prealloc (struct reiserfs_transaction_handle * th,
struct inode * inode)
{
unsigned long save = inode->u.reiserfs_i.i_prealloc_block ;
+ int dirty=0;
#ifdef CONFIG_REISERFS_CHECK
if (inode->u.reiserfs_i.i_prealloc_count < 0)
reiserfs_warning(th->t_super, "zam-4001:%s: inode has negative prealloc blocks count.\n", __FUNCTION__ );
#endif
while (inode->u.reiserfs_i.i_prealloc_count > 0) {
- reiserfs_free_prealloc_block(th,inode->u.reiserfs_i.i_prealloc_block);
+ reiserfs_free_prealloc_block(th, inode, inode->u.reiserfs_i.i_prealloc_block);
inode->u.reiserfs_i.i_prealloc_block++;
inode->u.reiserfs_i.i_prealloc_count --;
+ dirty = 1 ;
+ }
+ if (dirty) {
+ reiserfs_update_sd(th, inode) ;
}
inode->u.reiserfs_i.i_prealloc_block = save ;
list_del (&(inode->u.reiserfs_i.i_prealloc_list));
@@ -773,6 +791,24 @@
int nr_allocated = 0;
/* not all blocks were successfully allocated yet*/
if (second_pass) { /* it was a second pass; we must free all blocks */
+ if (!hint->formatted_node) {
+#ifdef REISERQUOTA_DEBUG
+ printk(KERN_DEBUG "reiserquota: freeing (nospace) %d blocks id=%u\n", amount_needed + hint->prealloc_size - nr_allocated, hint->inode->i_uid);
+#endif
+ DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed + hint->prealloc_size - nr_allocated); /* Free not allocated blocks */
+ }
while (nr_allocated --)
- reiserfs_free_block(hint->th, new_blocknrs[nr_allocated]);
+ reiserfs_free_block(hint->th, hint->inode, new_blocknrs[nr_allocated], !hint->formatted_node);
/* Does the buffer contain a disk block which is in the tree. */
inline int B_IS_IN_TREE (const struct buffer_head * p_s_bh)
@@ -71,9 +72,6 @@
return ( B_LEVEL (p_s_bh) != FREE_LEVEL );
}
-
-
-
inline void copy_short_key (void * to, const void * from)
{
memcpy (to, from, SHORT_KEY_SIZE);
@@ -1126,8 +1124,7 @@
tmp = get_block_num(p_n_unfm_pointer,0);
put_block_num(p_n_unfm_pointer, 0, 0);
journal_mark_dirty (th, p_s_sb, p_s_bh);
- inode->i_blocks -= p_s_sb->s_blocksize / 512;
- reiserfs_free_block(th, tmp);
+ reiserfs_free_block(th, inode, tmp, 1);
/* In case of big fragmentation it is possible that each block
freed will cause dirtying of one more bitmap and then we will
quickly overflow our transaction space. This is a
@@ -1169,8 +1166,7 @@
}
}
-
-/* Calculate bytes number which will be deleted or cutted in the balance. */
+/* Calculate number of bytes which will be deleted or cut during balance */
int calc_deleted_bytes_number(
struct tree_balance * p_s_tb,
char c_mode
@@ -1181,14 +1177,14 @@
if ( is_statdata_le_ih (p_le_ih) )
return 0;
+ n_del_size = ( c_mode == M_DELETE ) ? ih_item_len(p_le_ih) : -p_s_tb->insert_size[0];
if ( is_direntry_le_ih (p_le_ih) ) {
// return EMPTY_DIR_SIZE; /* We delete emty directoris only. */
// we can't use EMPTY_DIR_SIZE, as old format dirs have a different
// empty size. ick. FIXME, is this right?
//
- return ih_item_len(p_le_ih);
+ return n_del_size ;
}
- n_del_size = ( c_mode == M_DELETE ) ? ih_item_len(p_le_ih) : -p_s_tb->insert_size[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. */
const 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 just 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;
struct tree_balance s_del_balance;
struct item_head s_ih;
+ struct item_head *q_ih;
+ int quota_cut_bytes;
int n_ret_value,
n_del_size,
n_removed;
@@ -1282,6 +1307,22 @@
// reiserfs_delete_item returns item length when success
n_ret_value = calc_deleted_bytes_number(&s_del_balance, M_DELETE);
+ q_ih = get_ih(p_s_path) ;
+ quota_cut_bytes = ih_item_len(q_ih) ;
+
+ /* hack so the quota code doesn't have to guess if the file
+ ** has a tail. On tail insert, we allocate quota for 1 unformatted node.
+ ** We test the offset because the tail might have been
+ ** split into multiple items, and we only want to decrement for
+ ** the unfm node once
+ */
+ if (!S_ISLNK (p_s_inode->i_mode) && is_direct_le_ih(q_ih)) {
+ if ((le_ih_k_offset(q_ih) & (p_s_sb->s_blocksize - 1)) == 1) {
+ quota_cut_bytes = p_s_sb->s_blocksize + UNFM_P_SIZE;
+ } else {
+ quota_cut_bytes = 0 ;
+ }
+ }
if ( p_s_un_bh ) {
int off;
@@ -1313,10 +1354,14 @@
memcpy(data + off,
B_I_PITEM(PATH_PLAST_BUFFER(p_s_path), &s_ih), n_ret_value);
}
-
/* Perform balancing after all resources have been collected at once. */
do_balance(&s_del_balance, NULL, NULL, M_DELETE);
@@ -1532,6 +1586,7 @@
structure by using the init_tb_struct and fix_nodes functions.
After that we can make tree balancing. */
struct tree_balance s_cut_balance;
+ struct item_head *p_le_ih;
loff_t tail_pos = 0;
int n_cut_size = 0, /* Amount to be cut. */
n_ret_value = CARRY_ON,
@@ -1539,6 +1594,7 @@
n_is_inode_locked = 0;
char c_mode; /* Mode of the balance. */
int retval2 = -1;
+ int quota_cut_bytes;
reiserfs_update_sd (&th, old_dir);
reiserfs_update_sd (&th, new_dir);
Index: linux.d/fs/reiserfs/super.c
===================================================================
--- linux.d.orig/fs/reiserfs/super.c 2003-12-03 19:38:26.000000000 -0500
+++ linux.d/fs/reiserfs/super.c 2003-12-03 19:59:27.000000000 -0500
@@ -109,7 +109,7 @@
/* we are going to do one balancing */
journal_begin (&th, s, JOURNAL_PER_BALANCE_CNT);
- reiserfs_delete_solid_item (&th, key);
+ reiserfs_delete_solid_item (&th, NULL, key);
if (oid_free)
/* removals are protected by direct items */
reiserfs_release_objectid (&th, le32_to_cpu (key->k_objectid));
@@ -295,8 +295,8 @@
/* body of "save" link */
link = INODE_PKEY (inode)->k_dir_id;
/*
** We pack the tails of files on file close, not at the time they are written.
@@ -92,7 +93,9 @@
static int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
struct inode *inode = dentry->d_inode ;
int error ;
- if (attr->ia_valid & ATTR_SIZE) {
+ unsigned int ia_valid = attr->ia_valid ;
+
+ if (ia_valid & ATTR_SIZE) {
/* version 2 items will be caught by the s_maxbytes check
** done for us in vmtruncate
*/
@@ -131,9 +134,14 @@
return -EINVAL;
Index: linux.d/fs/reiserfs/fix_node.c
===================================================================
--- linux.d.orig/fs/reiserfs/fix_node.c 2003-12-03 19:38:26.000000000 -0500
+++ linux.d/fs/reiserfs/fix_node.c 2003-12-03 19:59:27.000000000 -0500
@@ -795,8 +795,9 @@
else /* If we have enough already then there is nothing to do. */
return CARRY_ON;
- if ( reiserfs_new_form_blocknrs (p_s_tb, a_n_blocknrs,
- n_amount_needed) == NO_DISK_SPACE )
+ /* No need to check quota - is not allocated for blocks used for formatted nodes */
+ if (reiserfs_new_form_blocknrs (p_s_tb, a_n_blocknrs,
+ n_amount_needed) == NO_DISK_SPACE)
return NO_DISK_SPACE;
/* for each blocknumber we just got, get a buffer and stick it on FEB */
@@ -2519,7 +2520,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 */
Index: linux.d/fs/reiserfs/inode.c
===================================================================
--- linux.d.orig/fs/reiserfs/inode.c 2003-12-03 19:43:20.000000000 -0500
+++ linux.d/fs/reiserfs/inode.c 2003-12-03 20:03:02.000000000 -0500
@@ -4,9 +4,11 @@
+ DQUOT_FREE_INODE(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);
@@ -681,7 +684,7 @@
- if (repeat == NO_DISK_SPACE) {
+ if (repeat == NO_DISK_SPACE || repeat == QUOTA_EXCEEDED) {
/* restart the transaction to give the journal a chance to free
** some blocks. releases the path, so we have to go back to
** research if we succeed on the second try
@@ -693,10 +696,13 @@
restart_transaction(th, inode, &path, jbegin_count) ;
repeat = _allocate_block(th, block, inode, &allocated_block_nr, NULL, create);
@@ -917,18 +920,16 @@
only have space for one block */
blocks_needed=max_to_insert?max_to_insert:1;
}
- retval = reiserfs_paste_into_item (th, &path, &tmp_key, (char *)un, UNFM_P_SIZE * blocks_needed);
+ retval = reiserfs_paste_into_item (th, &path, &tmp_key, inode, (char *)un, UNFM_P_SIZE * blocks_needed);
if (blocks_needed != 1)
kfree(un);
if (retval) {
- reiserfs_free_block (th, allocated_block_nr);
+ reiserfs_free_block (th, inode, allocated_block_nr, 1);
goto failure;
}
- if (done) {
- inode->i_blocks += inode->i_sb->s_blocksize / 512;
- } else {
+ if (!done) {
/* We need to mark new file size in case this function will be
interrupted/aborted later on. And we may do this only for
holes. */
@@ -970,7 +971,7 @@
"%K should not be found\n", &key);
retval = -EEXIST;
if (allocated_block_nr)
- reiserfs_free_block (th, allocated_block_nr);
+ reiserfs_free_block (th, inode, allocated_block_nr, 1);
pathrelse(&path) ;
goto failure;
}
@@ -1006,6 +1007,58 @@
}
+/* Compute real number of used bytes by file
+ * Following three functions can go away when we'll have enough space in stat item
+ */
+static int real_space_diff(struct inode *inode, int sd_size)
+{
+ int bytes;
+ loff_t blocksize = inode->i_sb->s_blocksize ;
+
+ if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode))
+ return sd_size ;
+
+ /* End of file is also in full block with indirect reference, so round
+ ** up to the next block.
+ **
+ ** there is just no way to know if the tail is actually packed
+ ** on the file, so we have to assume it isn't. When we pack the
+ ** tail, we add 4 bytes to pretend there really is an unformatted
+ ** node pointer
+ */
+ bytes = ((inode->i_size + (blocksize-1)) >> inode->i_sb->s_blocksize_bits) * UNFM_P_SIZE + sd_size;
+ return bytes ;
+}
+
+static inline loff_t to_real_used_space(struct inode *inode, ulong blocks,
+ int sd_size)
+{
+ if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) {
+ return inode->i_size + (loff_t)(real_space_diff(inode, sd_size)) ;
+ }
+ return ((loff_t)real_space_diff(inode, sd_size)) + (((loff_t)blocks) << 9);
+}
+
+/* Compute number of blocks used by file in ReiserFS counting */
+static inline ulong to_fake_used_blocks(struct inode *inode, int sd_size)
+{
+ loff_t bytes = inode_get_bytes(inode) ;
+ loff_t real_space = real_space_diff(inode, sd_size) ;
+
+ /* keeps fsck and non-quota versions of reiserfs happy */
+ if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) {
+ bytes += (loff_t)511 ;
+ }
+
+ /* files from before the quota patch might i_blocks such that
+ ** bytes < real_space. Deal with that here to prevent it from
+ ** going negative.
+ */
+ if (bytes < real_space)
+ return 0 ;
+ return (bytes - real_space) >> 9;
+}
+
//
// BAD: new directories have stat data of new type and all other items
// of old type. Version stored in the inode says about body items, so
@@ -1061,6 +1114,14 @@
rdev = sd_v1_rdev(sd);
inode->u.reiserfs_i.i_first_direct_byte = sd_v1_first_direct_byte(sd);
+ /* an early bug in the quota code can give us an odd number for the
+ ** block count. This is incorrect, fix it here.
+ */
+ if (inode->i_blocks & 1) {
+ inode->i_blocks++ ;
+ }
+ inode_set_bytes(inode, to_real_used_space(inode, inode->i_blocks,
+ SD_V1_SIZE));
/* nopack is initially zero for v1 objects. For v2 objects,
nopack is initialised from sd_attrs */
inode->u.reiserfs_i.i_flags &= ~i_nopack_mask;
@@ -1090,6 +1151,8 @@
set_inode_item_key_version (inode, KEY_FORMAT_3_6);
/* 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)
{
@@ -1617,7 +1682,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);
}