Commit 446a7461 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] reiserfs: quota support

From: Chris Mason <mason@suse.com>

ReiserFS support for quotas.  Originally from Jan Kara
parent 30304fc9
......@@ -12,6 +12,7 @@
#include <linux/pagemap.h>
#include <linux/reiserfs_fs_sb.h>
#include <linux/reiserfs_fs_i.h>
#include <linux/quotaops.h>
#define PREALLOCATION_SIZE 9
......@@ -281,7 +282,8 @@ static int scan_bitmap (struct reiserfs_transaction_handle *th,
}
static void _reiserfs_free_block (struct reiserfs_transaction_handle *th,
b_blocknr_t block)
struct inode *inode, b_blocknr_t block,
int for_unformatted)
{
struct super_block * s = th->t_super;
struct reiserfs_super_block * rs;
......@@ -323,11 +325,13 @@ static void _reiserfs_free_block (struct reiserfs_transaction_handle *th,
set_sb_free_blocks( rs, sb_free_blocks(rs) + 1 );
journal_mark_dirty (th, s, sbh);
s->s_dirt = 1;
if (for_unformatted)
DQUOT_FREE_BLOCK_NODIRTY(inode, 1);
}
void reiserfs_free_block (struct reiserfs_transaction_handle *th,
b_blocknr_t block)
struct inode *inode, b_blocknr_t block,
int for_unformatted)
{
struct super_block * s = th->t_super;
......@@ -335,42 +339,46 @@ void reiserfs_free_block (struct reiserfs_transaction_handle *th,
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,
b_blocknr_t block) {
struct inode *inode, b_blocknr_t 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 reiserfs_inode_info *ei)
{
unsigned long save = ei->i_prealloc_block ;
int dirty = 0;
struct inode *inode = &ei->vfs_inode;
#ifdef CONFIG_REISERFS_CHECK
if (ei->i_prealloc_count < 0)
reiserfs_warning("zam-4001:%s: inode has negative prealloc blocks count.\n", __FUNCTION__ );
#endif
while (ei->i_prealloc_count > 0) {
reiserfs_free_prealloc_block(th,ei->i_prealloc_block);
reiserfs_free_prealloc_block(th, inode, ei->i_prealloc_block);
ei->i_prealloc_block++;
ei->i_prealloc_count --;
dirty = 1;
}
if (dirty)
reiserfs_update_sd(th, inode);
ei->i_prealloc_block = save;
list_del_init(&(ei->i_prealloc_list));
}
/* FIXME: It should be inline function */
void reiserfs_discard_prealloc (struct reiserfs_transaction_handle *th,
struct inode * inode)
struct inode *inode)
{
struct reiserfs_inode_info *ei = REISERFS_I(inode);
if (ei->i_prealloc_count) {
if (ei->i_prealloc_count)
__discard_prealloc(th, ei);
}
}
void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th)
......@@ -772,6 +780,24 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
int nr_allocated = 0;
determine_prealloc_size(hint);
if (!hint->formatted_node) {
int quota_ret;
#ifdef REISERQUOTA_DEBUG
printk(KERN_DEBUG "reiserquota: allocating %d blocks id=%u\n", amount_needed, hint->inode->i_uid);
#endif
quota_ret = DQUOT_ALLOC_BLOCK_NODIRTY(hint->inode, amount_needed);
if (quota_ret) /* Quota exceeded? */
return QUOTA_EXCEEDED;
if (hint->preallocate && hint->prealloc_size ) {
#ifdef REISERQUOTA_DEBUG
printk(KERN_DEBUG "reiserquota: allocating (prealloc) %d blocks id=%u\n", hint->prealloc_size, hint->inode->i_uid);
#endif
quota_ret = DQUOT_PREALLOC_BLOCK_NODIRTY(hint->inode, hint->prealloc_size);
if (quota_ret)
hint->preallocate=hint->prealloc_size=0;
}
}
while((nr_allocated
+= allocate_without_wrapping_disk(hint, new_blocknrs + nr_allocated, start, finish,
amount_needed - nr_allocated, hint->prealloc_size))
......@@ -779,8 +805,14 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
/* 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);
return NO_DISK_SPACE;
} else { /* refine search parameters for next pass */
......@@ -789,7 +821,19 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
start = 0;
continue;
}
}
}
if ( !hint->formatted_node &&
amount_needed + hint->prealloc_size >
nr_allocated + REISERFS_I(hint->inode)->i_prealloc_count) {
/* Some of preallocation blocks were not allocated */
#ifdef REISERQUOTA_DEBUG
printk(KERN_DEBUG "reiserquota: freeing (failed prealloc) %d blocks id=%u\n", amount_needed + hint->prealloc_size - nr_allocated - INODE_INFO(hint->inode)->i_prealloc_count, hint->inode->i_uid);
#endif
DQUOT_FREE_BLOCK_NODIRTY(hint->inode, amount_needed +
hint->prealloc_size - nr_allocated -
REISERFS_I(hint->inode)->i_prealloc_count);
}
return CARRY_ON;
}
......@@ -858,7 +902,7 @@ int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *hint,
if (ret != CARRY_ON) {
while (amount_needed ++ < initial_amount_needed) {
reiserfs_free_block(hint->th, *(--new_blocknrs));
reiserfs_free_block(hint->th, hint->inode, *(--new_blocknrs), 1);
}
}
return ret;
......
......@@ -1234,7 +1234,7 @@ static void free_thrown(struct tree_balance *tb) {
if (buffer_dirty (tb->thrown[i]))
printk ("free_thrown deals with dirty buffer %d\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);
}
}
}
......@@ -1247,10 +1247,6 @@ void reiserfs_invalidate_buffer (struct tree_balance * tb, struct buffer_head *
set_blkh_nr_item( blkh, 0 );
clear_buffer_dirty(bh);
/* reiserfs_free_block is no longer schedule safe
reiserfs_free_block (tb->transaction_handle, tb->tb_sb, bh->b_blocknr);
*/
store_thrown (tb, bh);
}
......
......@@ -13,6 +13,7 @@
#include <linux/writeback.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include <linux/quotaops.h>
/*
** We pack the tails of files on file close, not at the time they are written.
......@@ -274,7 +275,7 @@ int reiserfs_allocate_blocks_for_region(
/* Ok, there is existing indirect item already. Need to append it */
/* Calculate position past inserted item */
make_cpu_key( &key, inode, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize), TYPE_INDIRECT, 3);
res = reiserfs_paste_into_item( th, &path, &key, (char *)zeros, UNFM_P_SIZE*to_paste);
res = reiserfs_paste_into_item( th, &path, &key, inode, (char *)zeros, UNFM_P_SIZE*to_paste);
if ( res ) {
kfree(zeros);
goto error_exit_free_blocks;
......@@ -304,7 +305,7 @@ int reiserfs_allocate_blocks_for_region(
kfree(zeros);
goto error_exit_free_blocks;
}
res = reiserfs_insert_item( th, &path, &key, &ins_ih, (char *)zeros);
res = reiserfs_insert_item( th, &path, &key, &ins_ih, inode, (char *)zeros);
} else {
reiserfs_panic(inode->i_sb, "green-9011: Unexpected key type %K\n", &key);
}
......@@ -421,7 +422,7 @@ int reiserfs_allocate_blocks_for_region(
// position. We do not need to recalculate path as it should
// already point to correct place.
make_cpu_key( &key, inode, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize), TYPE_INDIRECT, 3);
res = reiserfs_paste_into_item( th, &path, &key, (char *)(allocated_blocks+curr_block), UNFM_P_SIZE*(blocks_to_allocate-curr_block));
res = reiserfs_paste_into_item( th, &path, &key, inode, (char *)(allocated_blocks+curr_block), UNFM_P_SIZE*(blocks_to_allocate-curr_block));
if ( res ) {
goto error_exit_free_blocks;
}
......@@ -452,7 +453,7 @@ int reiserfs_allocate_blocks_for_region(
goto error_exit_free_blocks;
}
/* Insert item into the tree with the data as its body */
res = reiserfs_insert_item( th, &path, &key, &ins_ih, (char *)(allocated_blocks+curr_block));
res = reiserfs_insert_item( th, &path, &key, &ins_ih, inode, (char *)(allocated_blocks+curr_block));
} else {
reiserfs_panic(inode->i_sb, "green-9010: unexpected item type for key %K\n",&key);
}
......@@ -462,7 +463,6 @@ int reiserfs_allocate_blocks_for_region(
// unless we return an error, they are also responsible for logging
// the inode.
//
inode->i_blocks += blocks_to_allocate << (inode->i_blkbits - 9);
pathrelse(&path);
reiserfs_write_unlock(inode->i_sb);
......@@ -508,7 +508,7 @@ int reiserfs_allocate_blocks_for_region(
pathrelse(&path);
// free blocks
for( i = 0; i < blocks_to_allocate; i++ )
reiserfs_free_block(th, le32_to_cpu(allocated_blocks[i]));
reiserfs_free_block(th, inode, le32_to_cpu(allocated_blocks[i]), 1);
error_exit:
reiserfs_update_sd(th, inode); // update any changes we made to blk count
......
......@@ -795,8 +795,9 @@ static int get_empty_nodes(
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 */
......@@ -2492,7 +2493,7 @@ void unfix_nodes (struct tree_balance * tb)
/* 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 */
......
......@@ -4,6 +4,7 @@
#include <linux/config.h>
#include <linux/time.h>
#include <linux/fs.h>
#include <linux/reiserfs_fs.h>
#include <linux/reiserfs_acl.h>
#include <linux/reiserfs_xattr.h>
......@@ -39,6 +40,7 @@ void reiserfs_delete_inode (struct inode * inode)
reiserfs_write_lock(inode->i_sb);
DQUOT_FREE_INODE(inode);
/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
down (&inode->i_sem);
......@@ -647,7 +649,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
repeat = _allocate_block(th, block, inode, &allocated_block_nr, &path, create);
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
......@@ -656,10 +658,13 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
restart_transaction(th, inode, &path) ;
repeat = _allocate_block(th, block, inode, &allocated_block_nr, NULL, create);
if (repeat != NO_DISK_SPACE) {
if (repeat != NO_DISK_SPACE && repeat != QUOTA_EXCEEDED) {
goto research ;
}
retval = -ENOSPC;
if (repeat == QUOTA_EXCEEDED)
retval = -EDQUOT;
else
retval = -ENOSPC;
goto failure;
}
......@@ -687,7 +692,6 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
put_block_num(item, pos_in_item, allocated_block_nr) ;
unfm_ptr = allocated_block_nr;
journal_mark_dirty (th, inode->i_sb, bh);
inode->i_blocks += (inode->i_sb->s_blocksize / 512) ;
reiserfs_update_sd(th, inode) ;
}
set_block_dev_mapped(bh_result, unfm_ptr, inode);
......@@ -734,13 +738,11 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
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);
goto failure; // retval == -ENOSPC or -EIO or -EEXIST
reiserfs_free_block (th, inode, allocated_block_nr, 1);
goto failure; // retval == -ENOSPC, -EDQUOT 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 */
......@@ -778,7 +780,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
if (!th)
th = reiserfs_persistent_transaction(inode->i_sb,3);
if (th)
reiserfs_free_block (th, allocated_block_nr);
reiserfs_free_block (th,inode,allocated_block_nr,1);
}
goto failure ;
}
......@@ -787,7 +789,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
retval = direct2indirect (th, inode, &path, unbh, tail_offset);
if (retval) {
reiserfs_unmap_buffer(unbh);
reiserfs_free_block (th, allocated_block_nr);
reiserfs_free_block (th, inode, allocated_block_nr, 1);
goto failure;
}
/* it is important the set_buffer_uptodate is done after
......@@ -820,9 +822,6 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
*/
mark_buffer_dirty(unbh) ;
}
//inode->i_blocks += inode->i_sb->s_blocksize / 512;
//mark_tail_converted (inode);
} else {
/* append indirect item with holes if needed, when appending
pointer to 'block'-th block use block, which is already
......@@ -870,24 +869,21 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
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. */
inode->i_size += inode->i_sb->s_blocksize * blocks_needed;
}
//mark_tail_converted (inode);
}
if (done == 1)
......@@ -919,7 +915,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
"%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;
}
......@@ -949,6 +945,58 @@ reiserfs_readpages(struct file *file, struct address_space *mapping,
return mpage_readpages(mapping, pages, nr_pages, reiserfs_get_block);
}
/* 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
......@@ -1014,6 +1062,14 @@ static void init_inode (struct inode * inode, struct path * path)
rdev = sd_v1_rdev(sd);
REISERFS_I(inode)->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 */
REISERFS_I(inode)->i_flags &= ~i_nopack_mask;
......@@ -1046,6 +1102,8 @@ static void init_inode (struct inode * inode, struct path * path)
set_inode_item_key_version (inode, KEY_FORMAT_3_6);
REISERFS_I(inode)->i_first_direct_byte = 0;
set_inode_sd_version (inode, STAT_DATA_V2);
inode_set_bytes(inode, to_real_used_space(inode, inode->i_blocks,
SD_V2_SIZE));
/* read persistent inode attributes from sd and initalise
generic inode flags from them */
REISERFS_I(inode)->i_attrs = sd_v2_attrs( sd );
......@@ -1072,7 +1130,7 @@ static void init_inode (struct inode * inode, struct path * path)
// update new stat data with inode fields
static void inode2sd (void * sd, struct inode * inode)
static void inode2sd (void * sd, struct inode * inode, loff_t size)
{
struct stat_data * sd_v2 = (struct stat_data *)sd;
__u16 flags;
......@@ -1080,12 +1138,12 @@ static void inode2sd (void * sd, struct inode * inode)
set_sd_v2_mode(sd_v2, inode->i_mode );
set_sd_v2_nlink(sd_v2, inode->i_nlink );
set_sd_v2_uid(sd_v2, inode->i_uid );
set_sd_v2_size(sd_v2, inode->i_size );
set_sd_v2_size(sd_v2, size );
set_sd_v2_gid(sd_v2, inode->i_gid );
set_sd_v2_mtime(sd_v2, inode->i_mtime.tv_sec );
set_sd_v2_atime(sd_v2, inode->i_atime.tv_sec );
set_sd_v2_ctime(sd_v2, inode->i_ctime.tv_sec );
set_sd_v2_blocks(sd_v2, inode->i_blocks );
set_sd_v2_blocks(sd_v2, to_fake_used_blocks(inode, SD_V2_SIZE));
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
set_sd_v2_rdev(sd_v2, new_encode_dev(inode->i_rdev));
else
......@@ -1097,7 +1155,7 @@ static void inode2sd (void * sd, struct inode * inode)
// used to copy inode's fields to old stat data
static void inode2sd_v1 (void * sd, struct inode * inode)
static void inode2sd_v1 (void * sd, struct inode * inode, loff_t size)
{
struct stat_data_v1 * sd_v1 = (struct stat_data_v1 *)sd;
......@@ -1105,7 +1163,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode)
set_sd_v1_uid(sd_v1, inode->i_uid );
set_sd_v1_gid(sd_v1, inode->i_gid );
set_sd_v1_nlink(sd_v1, inode->i_nlink );
set_sd_v1_size(sd_v1, inode->i_size );
set_sd_v1_size(sd_v1, size );
set_sd_v1_atime(sd_v1, inode->i_atime.tv_sec );
set_sd_v1_ctime(sd_v1, inode->i_ctime.tv_sec );
set_sd_v1_mtime(sd_v1, inode->i_mtime.tv_sec );
......@@ -1113,7 +1171,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode)
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
set_sd_v1_rdev(sd_v1, new_encode_dev(inode->i_rdev));
else
set_sd_v1_blocks(sd_v1, inode->i_blocks );
set_sd_v1_blocks(sd_v1, to_fake_used_blocks(inode, SD_V1_SIZE));
// Sigh. i_first_direct_byte is back
set_sd_v1_first_direct_byte(sd_v1, REISERFS_I(inode)->i_first_direct_byte);
......@@ -1123,7 +1181,8 @@ static void inode2sd_v1 (void * sd, struct inode * inode)
/* NOTE, you must prepare the buffer head before sending it here,
** and then log it after the call
*/
static void update_stat_data (struct path * path, struct inode * inode)
static void update_stat_data (struct path * path, struct inode * inode,
loff_t size)
{
struct buffer_head * bh;
struct item_head * ih;
......@@ -1137,17 +1196,17 @@ static void update_stat_data (struct path * path, struct inode * inode)
if (stat_data_v1 (ih)) {
// path points to old stat data
inode2sd_v1 (B_I_PITEM (bh, ih), inode);
inode2sd_v1 (B_I_PITEM (bh, ih), inode, size);
} else {
inode2sd (B_I_PITEM (bh, ih), inode);
inode2sd (B_I_PITEM (bh, ih), inode, size);
}
return;
}
void reiserfs_update_sd (struct reiserfs_transaction_handle *th,
struct inode * inode)
void reiserfs_update_sd_size (struct reiserfs_transaction_handle *th,
struct inode * inode, loff_t size)
{
struct cpu_key key;
INITIALIZE_PATH(path);
......@@ -1197,7 +1256,7 @@ void reiserfs_update_sd (struct reiserfs_transaction_handle *th,
}
break;
}
update_stat_data (&path, inode);
update_stat_data (&path, inode, size);
journal_mark_dirty(th, th->t_super, bh) ;
pathrelse (&path);
return;
......@@ -1480,6 +1539,7 @@ int reiserfs_sync_inode (struct reiserfs_transaction_handle *th, struct inode *
/* 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,
struct inode *inode,
struct item_head * ih, struct path * path,
struct inode * dir)
{
......@@ -1524,13 +1584,14 @@ static int reiserfs_new_directory (struct reiserfs_transaction_handle *th,
}
/* 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)
{
......@@ -1560,7 +1621,7 @@ static int reiserfs_new_symlink (struct reiserfs_transaction_handle *th,
}
/* 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);
}
......@@ -1628,7 +1689,8 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
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->i_blocks = 0;
inode->i_bytes = 0;
REISERFS_I(inode)->i_first_direct_byte = S_ISLNK(mode) ? 1 :
U32_MAX/*NO_BYTES_IN_DIRECT_ITEM*/;
......@@ -1673,9 +1735,9 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
err = -EINVAL;
goto out_bad_inode;
}
inode2sd_v1 (&sd, inode);
inode2sd_v1 (&sd, inode, inode->i_size);
} else {
inode2sd (&sd, inode);
inode2sd (&sd, inode, inode->i_size);
}
// these do not go to on-disk stat data
inode->i_ino = le32_to_cpu (ih.ih_key.k_objectid);
......@@ -1699,7 +1761,7 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
if (REISERFS_I(dir)->new_packing_locality)
th->displace_new_blocks = 1;
#endif
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) {
err = retval;
reiserfs_check_path(&path_to_key) ;
......@@ -1712,14 +1774,14 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
#endif
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) {
err = retval;
......@@ -1757,6 +1819,9 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
/* dquot_drop must be done outside a transaction */
journal_end(th, th->t_super, th->t_blocks_allocated) ;
DQUOT_FREE_INODE(inode);
DQUOT_DROP(inode);
inode->i_flags |= S_NOQUOTA;
make_bad_inode(inode);
out_inserted_sd:
......@@ -2294,6 +2359,7 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
struct inode *inode = page->mapping->host ;
loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
int ret = 0;
int update_sd = 0;
struct reiserfs_transaction_handle *th = NULL;
reiserfs_wait_on_write_block(inode->i_sb) ;
......@@ -2320,11 +2386,14 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
reiserfs_update_inode_transaction(inode) ;
inode->i_size = pos ;
reiserfs_update_sd(&myth, inode) ;
update_sd = 1;
journal_end(&myth, inode->i_sb, 1) ;
reiserfs_write_unlock(inode->i_sb);
}
if (th) {
reiserfs_write_lock(inode->i_sb);
if (!update_sd)
reiserfs_update_sd(th, inode) ;
reiserfs_end_persistent_transaction(th);
reiserfs_write_unlock(inode->i_sb);
}
......@@ -2533,7 +2602,6 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb,
offset, nr_segs, reiserfs_get_blocks_direct_io, NULL);
}
int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
struct inode *inode = dentry->d_inode ;
int error ;
......
......@@ -18,6 +18,7 @@
#include <linux/reiserfs_acl.h>
#include <linux/reiserfs_xattr.h>
#include <linux/smp_lock.h>
#include <linux/quotaops.h>
#define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { i->i_nlink++; if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; }
#define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) i->i_nlink--;
......@@ -519,7 +520,7 @@ static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct in
}
/* 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) {
......@@ -528,7 +529,6 @@ static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct in
}
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
......@@ -544,7 +544,9 @@ static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct in
** inserted into the tree yet.
*/
static int drop_new_inode(struct inode *inode) {
DQUOT_DROP(inode);
make_bad_inode(inode) ;
inode->i_flags |= S_NOQUOTA;
iput(inode) ;
return 0 ;
}
......@@ -570,6 +572,11 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode) {
} else {
inode->i_gid = current->fsgid;
}
DQUOT_INIT(inode);
if (DQUOT_ALLOC_INODE(inode)) {
drop_new_inode(inode);
return -EDQUOT;
}
return 0 ;
}
......@@ -836,7 +843,6 @@ static int reiserfs_rmdir (struct inode * dir, struct dentry *dentry)
DEC_DIR_INODE_NLINK(dir)
dir->i_size -= (DEH_SIZE + de.de_entrylen);
dir->i_blocks = ((dir->i_size + 511) >> 9);
reiserfs_update_sd (&th, dir);
/* prevent empty directory from getting lost */
......@@ -919,7 +925,6 @@ static int reiserfs_unlink (struct inode * dir, struct dentry *dentry)
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);
......@@ -1335,7 +1340,6 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
reiserfs_warning ("vs-7060: reiserfs_rename: couldn't 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);
......
......@@ -60,6 +60,7 @@
#include <linux/reiserfs_fs.h>
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
#include <linux/quotaops.h>
/* 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 @@ inline int B_IS_IN_TREE (const struct buffer_head * p_s_bh)
return ( B_LEVEL (p_s_bh) != FREE_LEVEL );
}
inline void copy_short_key (void * to, const void * from)
{
memcpy (to, from, SHORT_KEY_SIZE);
......@@ -1125,8 +1123,7 @@ static char prepare_for_delete_or_cut(
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);
if ( item_moved (&s_ih, p_s_path) ) {
need_research = 1;
break ;
......@@ -1155,8 +1152,7 @@ static char prepare_for_delete_or_cut(
}
}
/* 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
......@@ -1167,14 +1163,14 @@ int calc_deleted_bytes_number(
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];
if ( is_indirect_le_ih (p_le_ih) )
n_del_size = (n_del_size/UNFM_P_SIZE)*
......@@ -1208,17 +1204,46 @@ void padd_item (char * item, int total_length, int length)
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. */
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;
......@@ -1268,6 +1293,22 @@ int reiserfs_delete_item (struct reiserfs_transaction_handle *th,
// 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;
......@@ -1299,10 +1340,14 @@ int reiserfs_delete_item (struct reiserfs_transaction_handle *th,
B_I_PITEM(PATH_PLAST_BUFFER(p_s_path), &s_ih), n_ret_value);
kunmap_atomic(data, KM_USER0);
}
/* Perform balancing after all resources have been collected at once. */
do_balance(&s_del_balance, NULL, NULL, M_DELETE);
#ifdef REISERQUOTA_DEBUG
printk(KERN_DEBUG "reiserquota delete_item(): freeing %u, id=%u type=%c\n", quota_cut_bytes, p_s_inode->i_uid, head2type(&s_ih));
#endif
DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes);
/* Return deleted body length */
return n_ret_value;
}
......@@ -1327,14 +1372,16 @@ int reiserfs_delete_item (struct reiserfs_transaction_handle *th,
/* this deletes item which never gets split */
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;
int tb_init = 0 ;
struct cpu_key cpu_key;
int retval;
int quota_cut_bytes = 0;
le_key2cpu_key (&cpu_key, key);
......@@ -1358,6 +1405,7 @@ void reiserfs_delete_solid_item (struct reiserfs_transaction_handle *th,
item_len = ih_item_len( PATH_PITEM_HEAD(&path) );
init_tb_struct (th, &tb, th->t_super, &path, - (IH_SIZE + item_len));
}
quota_cut_bytes = ih_item_len(PATH_PITEM_HEAD(&path)) ;
retval = fix_nodes (M_DELETE, &tb, NULL, 0);
if (retval == REPEAT_SEARCH) {
......@@ -1367,6 +1415,12 @@ void reiserfs_delete_solid_item (struct reiserfs_transaction_handle *th,
if (retval == CARRY_ON) {
do_balance (&tb, 0, 0, M_DELETE);
if (inode) { /* Should we count quota for item? (we don't count quotas for save-links) */
#ifdef REISERQUOTA_DEBUG
printk(KERN_DEBUG "reiserquota delete_solid_item(): freeing %u id=%u type=%c\n", quota_cut_bytes, inode->i_uid, key2type(key));
#endif
DQUOT_FREE_SPACE_NODIRTY(inode, quota_cut_bytes);
}
break;
}
......@@ -1399,7 +1453,7 @@ void reiserfs_delete_object (struct reiserfs_transaction_handle *th, struct inod
}
/* USE_INODE_GENERATION_COUNTER */
#endif
reiserfs_delete_solid_item (th, INODE_PKEY (inode));
reiserfs_delete_solid_item (th, inode, INODE_PKEY (inode));
}
......@@ -1486,12 +1540,14 @@ int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
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;
int n_cut_size = 0, /* Amount to be cut. */
n_ret_value = CARRY_ON,
n_removed = 0, /* Number of the removed unformatted nodes. */
n_is_inode_locked = 0;
char c_mode; /* Mode of the balance. */
int retval2 = -1;
int quota_cut_bytes;
init_tb_struct(th, &s_cut_balance, p_s_inode->i_sb, p_s_path, n_cut_size);
......@@ -1579,23 +1635,27 @@ int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
RFALSE( c_mode == M_PASTE || c_mode == M_INSERT, "invalid mode");
/* Calculate number of bytes that need to be cut from the item. */
quota_cut_bytes = ( c_mode == M_DELETE ) ? ih_item_len(get_ih(p_s_path)) : -s_cut_balance.insert_size[0];
if (retval2 == -1)
n_ret_value = calc_deleted_bytes_number(&s_cut_balance, c_mode);
else
n_ret_value = retval2;
if ( c_mode == M_DELETE ) {
struct item_head * p_le_ih = PATH_PITEM_HEAD (s_cut_balance.tb_path);
if ( is_direct_le_ih (p_le_ih) && (le_ih_k_offset (p_le_ih) & (p_s_sb->s_blocksize - 1)) == 1 ) {
/* we delete first part of tail which was stored in direct
item(s) */
/* For direct items, we only change the quota when deleting the last
** item.
*/
p_le_ih = PATH_PITEM_HEAD (s_cut_balance.tb_path);
if (!S_ISLNK (p_s_inode->i_mode) && is_direct_le_ih(p_le_ih)) {
if (c_mode == M_DELETE &&
(le_ih_k_offset (p_le_ih) & (p_s_sb->s_blocksize - 1)) == 1 ) {
// FIXME: this is to keep 3.5 happy
REISERFS_I(p_s_inode)->i_first_direct_byte = U32_MAX;
p_s_inode->i_blocks -= p_s_sb->s_blocksize / 512;
quota_cut_bytes = p_s_sb->s_blocksize + UNFM_P_SIZE ;
} else {
quota_cut_bytes = 0 ;
}
}
#ifdef CONFIG_REISERFS_CHECK
if (n_is_inode_locked) {
struct item_head * le_ih = PATH_PITEM_HEAD (s_cut_balance.tb_path);
......@@ -1630,10 +1690,13 @@ int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
*/
REISERFS_I(p_s_inode)->i_flags &= ~i_pack_on_close_mask ;
}
#ifdef REISERQUOTA_DEBUG
printk(KERN_DEBUG "reiserquota cut_from_item(): freeing %u id=%u type=%c\n", quota_cut_bytes, p_s_inode->i_uid, '?');
#endif
DQUOT_FREE_SPACE_NODIRTY(p_s_inode, quota_cut_bytes);
return n_ret_value;
}
static void truncate_directory (struct reiserfs_transaction_handle *th, struct inode * inode)
{
if (inode->i_nlink)
......@@ -1641,8 +1704,8 @@ static void truncate_directory (struct reiserfs_transaction_handle *th, struct i
set_le_key_k_offset (KEY_FORMAT_3_5, INODE_PKEY (inode), DOT_OFFSET);
set_le_key_k_type (KEY_FORMAT_3_5, INODE_PKEY (inode), TYPE_DIRENTRY);
reiserfs_delete_solid_item (th, INODE_PKEY (inode));
reiserfs_delete_solid_item (th, inode, INODE_PKEY (inode));
reiserfs_update_sd(th, inode) ;
set_le_key_k_offset (KEY_FORMAT_3_5, INODE_PKEY (inode), SD_OFFSET);
set_le_key_k_type (KEY_FORMAT_3_5, INODE_PKEY (inode), TYPE_STAT_DATA);
}
......@@ -1809,18 +1872,37 @@ static void check_research_for_paste (struct path * path,
int reiserfs_paste_into_item (struct reiserfs_transaction_handle *th,
struct path * p_s_search_path, /* Path to the pasted item. */
const 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. */
{
struct tree_balance s_paste_balance;
int retval;
int fs_gen;
fs_gen = get_generation(inode->i_sb) ;
#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_NODIRTY(inode, n_pasted_size)) {
pathrelse(p_s_search_path);
return -EDQUOT;
}
init_tb_struct(th, &s_paste_balance, th->t_super, p_s_search_path, n_pasted_size);
#ifdef DISPLACE_NEW_PACKING_LOCALITIES
s_paste_balance.key = p_s_key->on_disk_key;
#endif
while ( (retval = fix_nodes(M_PASTE, &s_paste_balance, NULL, p_c_body)) == REPEAT_SEARCH ) {
/* DQUOT_* can schedule, must check before the fix_nodes */
if (fs_changed(fs_gen, inode->i_sb)) {
goto search_again;
}
while ((retval = fix_nodes(M_PASTE, &s_paste_balance, NULL, p_c_body)) ==
REPEAT_SEARCH ) {
search_again:
/* file system changed while we were in the fix_nodes */
PROC_INFO_INC( th -> t_super, paste_into_item_restarted );
retval = search_for_position_by_key (th->t_super, p_s_key, p_s_search_path);
......@@ -1849,6 +1931,10 @@ int reiserfs_paste_into_item (struct reiserfs_transaction_handle *th,
error_out:
/* this also releases the path */
unfix_nodes(&s_paste_balance);
#ifdef REISERQUOTA_DEBUG
printk(KERN_DEBUG "reiserquota paste_into_item(): freeing %u id=%u type=%c\n", n_pasted_size, inode->i_uid, key2type(&(p_s_key->on_disk_key)));
#endif
DQUOT_FREE_SPACE_NODIRTY(inode, n_pasted_size);
return retval ;
}
......@@ -1858,23 +1944,45 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
struct path * p_s_path, /* Path to the inserteded item. */
const struct cpu_key * key,
struct item_head * p_s_ih, /* Pointer to the item header to insert.*/
struct inode * inode,
const char * p_c_body) /* Pointer to the bytes to insert. */
{
struct tree_balance s_ins_balance;
int retval;
int fs_gen = 0 ;
int quota_bytes = 0 ;
if (inode) { /* Do we count quotas for item? */
fs_gen = get_generation(inode->i_sb);
quota_bytes = ih_item_len(p_s_ih);
/* hack so the quota code doesn't have to guess if the file has
** a tail, links are always tails, so there's no guessing needed
*/
if (!S_ISLNK (inode->i_mode) && is_direct_le_ih(p_s_ih)) {
quota_bytes = inode->i_sb->s_blocksize + UNFM_P_SIZE ;
}
#ifdef REISERQUOTA_DEBUG
printk(KERN_DEBUG "reiserquota insert_item(): allocating %u id=%u type=%c\n", quota_bytes, inode->i_uid, head2type(p_s_ih));
#endif
/* We can't dirty inode here. It would be immediately written but
* appropriate stat item isn't inserted yet... */
if (DQUOT_ALLOC_SPACE_NODIRTY(inode, quota_bytes)) {
pathrelse(p_s_path);
return -EDQUOT;
}
}
init_tb_struct(th, &s_ins_balance, th->t_super, p_s_path, IH_SIZE + ih_item_len(p_s_ih));
#ifdef DISPLACE_NEW_PACKING_LOCALITIES
s_ins_balance.key = key->on_disk_key;
#endif
/*
if (p_c_body == 0)
n_zeros_num = ih_item_len(p_s_ih);
*/
// le_key2cpu_key (&key, &(p_s_ih->ih_key));
/* DQUOT_* can schedule, must check to be sure calling fix_nodes is safe */
if (inode && fs_changed(fs_gen, inode->i_sb)) {
goto search_again;
}
while ( (retval = fix_nodes(M_INSERT, &s_ins_balance, p_s_ih, p_c_body)) == REPEAT_SEARCH) {
search_again:
/* file system changed while we were in the fix_nodes */
PROC_INFO_INC( th -> t_super, insert_item_restarted );
retval = search_item (th->t_super, key, p_s_path);
......@@ -1900,6 +2008,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
error_out:
/* also releases the path */
unfix_nodes(&s_ins_balance);
#ifdef REISERQUOTA_DEBUG
printk(KERN_DEBUG "reiserquota insert_item(): freeing %u id=%u type=%c\n", quota_bytes, inode->i_uid, head2type(p_s_ih));
#endif
if (inode)
DQUOT_FREE_SPACE_NODIRTY(inode, quota_bytes) ;
return retval;
}
......
......@@ -115,7 +115,7 @@ static void remove_save_link_only (struct super_block * s, struct key * key, int
/* 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));
......@@ -301,8 +301,8 @@ void add_save_link (struct reiserfs_transaction_handle * th,
/* body of "save" link */
link = INODE_PKEY (inode)->k_dir_id;
/* put "save" link inot tree */
retval = reiserfs_insert_item (th, &path, &key, &ih, (char *)&link);
/* put "save" link inot tree, don't charge quota to anyone */
retval = reiserfs_insert_item (th, &path, &key, &ih, NULL, (char *)&link);
if (retval) {
if (retval != -ENOSPC)
reiserfs_warning ("vs-2120: add_save_link: insert_item returned %d\n",
......@@ -344,7 +344,8 @@ void remove_save_link (struct inode * inode, int truncate)
( REISERFS_I(inode) -> i_flags & i_link_saved_truncate_mask ) ) ||
( !truncate &&
( REISERFS_I(inode) -> i_flags & i_link_saved_unlink_mask ) ) )
reiserfs_delete_solid_item (&th, &key);
/* don't take quota bytes from anywhere */
reiserfs_delete_solid_item (&th, NULL, &key);
if (!truncate) {
reiserfs_release_objectid (&th, inode->i_ino);
REISERFS_I(inode) -> i_flags &= ~i_link_saved_unlink_mask;
......@@ -714,6 +715,8 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
{"jdev", 'j', 0, 0, 0},
{"nolargeio", 'w', 0, 0, 0},
{"commit", 'c', 0, 0, 0},
{"usrquota", 0, 0, 0, 0},
{"grpquota", 0, 0, 0, 0},
{NULL, 0, 0, 0, 0}
};
......
......@@ -66,11 +66,11 @@ int direct2indirect (struct reiserfs_transaction_handle *th, struct inode * inod
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 ) {
......@@ -274,7 +274,7 @@ int indirect2direct (struct reiserfs_transaction_handle *th,
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
......@@ -292,13 +292,15 @@ int indirect2direct (struct reiserfs_transaction_handle *th,
*/
unmap_buffers(page, pos1) ;
/* 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 */
......
......@@ -268,6 +268,7 @@ int is_reiserfs_jr (struct reiserfs_super_block * rs);
#define NO_DISK_SPACE -3
#define NO_BALANCING_NEEDED (-4)
#define NO_MORE_UNUSED_CONTIGUOUS_BLOCKS (-5)
#define QUOTA_EXCEEDED -6
typedef __u32 b_blocknr_t;
typedef __u32 unp_t;
......@@ -1238,7 +1239,6 @@ excessive effort to avoid disturbing the precious VFS code.:-( The
gods only know how we are going to SMP the code that uses them.
znodes are the way! */
struct path {
int path_length; /* Length of the array above. */
struct path_element path_elements[EXTENDED_MAX_HEIGHT]; /* Array of the path elements. */
......@@ -1889,11 +1889,13 @@ void pathrelse_and_restore (struct super_block *s, struct path * p_s_search_path
int reiserfs_insert_item (struct reiserfs_transaction_handle *th,
struct path * path,
const 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,
const struct cpu_key * key,
struct inode *inode,
const char * body, int paste_size);
int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
......@@ -1910,7 +1912,7 @@ int reiserfs_delete_item (struct reiserfs_transaction_handle *th,
struct buffer_head * p_s_un_bh);
void reiserfs_delete_solid_item (struct reiserfs_transaction_handle *th,
struct key * key);
struct inode *inode, struct key * key);
void reiserfs_delete_object (struct reiserfs_transaction_handle *th, struct inode * p_s_inode);
void reiserfs_do_truncate (struct reiserfs_transaction_handle *th,
struct inode * p_s_inode, struct page *,
......@@ -1955,8 +1957,18 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
struct inode * dir, int mode,
const char * symname, loff_t i_size,
struct dentry *dentry, struct inode *inode);
int reiserfs_sync_inode (struct reiserfs_transaction_handle *th, struct inode * inode);
void reiserfs_update_sd (struct reiserfs_transaction_handle *th, struct inode * inode);
int reiserfs_sync_inode (struct reiserfs_transaction_handle *th,
struct inode * inode);
void reiserfs_update_sd_size (struct reiserfs_transaction_handle *th,
struct inode * inode, loff_t size);
static inline void reiserfs_update_sd(struct reiserfs_transaction_handle *th,
struct inode *inode)
{
reiserfs_update_sd_size(th, inode, inode->i_size) ;
}
void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode );
void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs );
......@@ -2139,7 +2151,7 @@ typedef struct __reiserfs_blocknr_hint reiserfs_blocknr_hint_t;
int reiserfs_parse_alloc_options (struct super_block *, char *);
int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value);
void reiserfs_free_block (struct reiserfs_transaction_handle *th, b_blocknr_t);
void reiserfs_free_block (struct reiserfs_transaction_handle *th, struct inode *, b_blocknr_t, int for_unformatted);
int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *, b_blocknr_t * , int, int);
extern inline int reiserfs_new_form_blocknrs (struct tree_balance * tb,
b_blocknr_t *new_blocknrs, int amount_needed)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment