#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)
return ( B_LEVEL (p_s_bh) != FREE_LEVEL );
}
-
-
-
inline void copy_short_key (void * to, const void * from)
{
memcpy (to, from, SHORT_KEY_SIZE);
if (cpu_key_k_offset (key1) > cpu_key_k_offset (key2))
return 1;
- reiserfs_warning ("comp_cpu_keys: type are compared for %K and %K\n",
+ reiserfs_warning (NULL, "comp_cpu_keys: type are compared for %K and %K",
key1, key2);
if (cpu_key_k_type (key1) < cpu_key_k_type (key2))
blkh = (struct block_head *)buf;
if ( blkh_level(blkh) != DISK_LEAF_NODE_LEVEL) {
- printk ("is_leaf: this should be caught earlier\n");
+ reiserfs_warning (NULL, "is_leaf: this should be caught earlier");
return 0;
}
nr = blkh_nr_item(blkh);
if (nr < 1 || nr > ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN))) {
/* item number is too big or too small */
- reiserfs_warning ("is_leaf: nr_item seems wrong: %z\n", bh);
+ reiserfs_warning (NULL, "is_leaf: nr_item seems wrong: %z", bh);
return 0;
}
ih = (struct item_head *)(buf + BLKH_SIZE) + nr - 1;
used_space = BLKH_SIZE + IH_SIZE * nr + (blocksize - ih_location (ih));
if (used_space != blocksize - blkh_free_space(blkh)) {
/* free space does not match to calculated amount of use space */
- reiserfs_warning ("is_leaf: free space seems wrong: %z\n", bh);
+ reiserfs_warning (NULL, "is_leaf: free space seems wrong: %z", bh);
return 0;
}
prev_location = blocksize;
for (i = 0; i < nr; i ++, ih ++) {
if ( le_ih_k_type(ih) == TYPE_ANY) {
- reiserfs_warning ("is_leaf: wrong item type for item %h\n",ih);
+ reiserfs_warning (NULL, "is_leaf: wrong item type for item %h",ih);
return 0;
}
if (ih_location (ih) >= blocksize || ih_location (ih) < IH_SIZE * nr) {
- reiserfs_warning ("is_leaf: item location seems wrong: %h\n", ih);
+ reiserfs_warning (NULL, "is_leaf: item location seems wrong: %h", ih);
return 0;
}
if (ih_item_len (ih) < 1 || ih_item_len (ih) > MAX_ITEM_LEN (blocksize)) {
- reiserfs_warning ("is_leaf: item length seems wrong: %h\n", ih);
+ reiserfs_warning (NULL, "is_leaf: item length seems wrong: %h", ih);
return 0;
}
if (prev_location - ih_location (ih) != ih_item_len (ih)) {
- reiserfs_warning ("is_leaf: item location seems wrong (second one): %h\n", ih);
+ reiserfs_warning (NULL, "is_leaf: item location seems wrong (second one): %h", ih);
return 0;
}
prev_location = ih_location (ih);
nr = blkh_level(blkh);
if (nr <= DISK_LEAF_NODE_LEVEL || nr > MAX_HEIGHT) {
/* this level is not possible for internal nodes */
- printk ("is_internal: this should be caught earlier\n");
+ reiserfs_warning (NULL, "is_internal: this should be caught earlier");
return 0;
}
nr = blkh_nr_item(blkh);
if (nr > (blocksize - BLKH_SIZE - DC_SIZE) / (KEY_SIZE + DC_SIZE)) {
/* for internal which is not root we might check min number of keys */
- reiserfs_warning ("is_internal: number of key seems wrong: %z\n", bh);
+ reiserfs_warning (NULL, "is_internal: number of key seems wrong: %z", bh);
return 0;
}
used_space = BLKH_SIZE + KEY_SIZE * nr + DC_SIZE * (nr + 1);
if (used_space != blocksize - blkh_free_space(blkh)) {
- reiserfs_warning ("is_internal: free space seems wrong: %z\n", bh);
+ reiserfs_warning (NULL, "is_internal: free space seems wrong: %z", bh);
return 0;
}
static int is_tree_node (struct buffer_head * bh, int level)
{
if (B_LEVEL (bh) != level) {
- printk ("is_tree_node: node level %d does not match to the expected one %d\n",
+ reiserfs_warning (NULL, "is_tree_node: node level %d does not match to the expected one %d",
B_LEVEL (bh), level);
return 0;
}
-#ifdef SEARCH_BY_KEY_READA
+#define SEARCH_BY_KEY_READA 16
/* The function is NOT SCHEDULE-SAFE! */
-static void search_by_key_reada (struct super_block * s, int blocknr)
+static void search_by_key_reada (struct super_block * s,
+ struct buffer_head **bh,
+ unsigned long *b, int num)
{
- struct buffer_head * bh;
+ int i,j;
- if (blocknr == 0)
- return;
-
- bh = sb_getblk (s, blocknr);
-
- if (!buffer_uptodate (bh)) {
- ll_rw_block (READA, 1, &bh);
+ for (i = 0 ; i < num ; i++) {
+ bh[i] = sb_getblk (s, b[i]);
+ }
+ for (j = 0 ; j < i ; j++) {
+ /*
+ * note, this needs attention if we are getting rid of the BKL
+ * you have to make sure the prepared bit isn't set on this buffer
+ */
+ if (!buffer_uptodate(bh[j]))
+ ll_rw_block(READA, 1, bh + j);
+ brelse(bh[j]);
}
- bh->b_count --;
}
-#endif
-
/**************************************************************************
* Algorithm SearchByKey *
* look for item in the Disk S+Tree by its key *
int n_node_level, n_retval;
int right_neighbor_of_leaf_node;
int fs_gen;
+ struct buffer_head *reada_bh[SEARCH_BY_KEY_READA];
+ unsigned long reada_blocks[SEARCH_BY_KEY_READA];
+ int reada_count = 0;
#ifdef CONFIG_REISERFS_CHECK
int n_repeat_counter = 0;
#ifdef CONFIG_REISERFS_CHECK
if ( !(++n_repeat_counter % 50000) )
- reiserfs_warning ("PAP-5100: search_by_key: %s:"
+ reiserfs_warning (p_s_sb, "PAP-5100: search_by_key: %s:"
"there were %d iterations of while loop "
- "looking for key %K\n",
+ "looking for key %K",
current->comm, n_repeat_counter, p_s_key);
#endif
p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path, ++p_s_search_path->path_length);
fs_gen = get_generation (p_s_sb);
-#ifdef SEARCH_BY_KEY_READA
- /* schedule read of right neighbor */
- search_by_key_reada (p_s_sb, right_neighbor_of_leaf_node);
-#endif
-
/* Read the next tree node, and set the last element in the path to
have a pointer to it. */
- if ( ! (p_s_bh = p_s_last_element->pe_buffer =
- sb_bread(p_s_sb, n_block_number)) ) {
+ if ((p_s_bh = p_s_last_element->pe_buffer =
+ sb_getblk(p_s_sb, n_block_number)) ) {
+ if (!buffer_uptodate(p_s_bh) && reada_count > 1) {
+ search_by_key_reada (p_s_sb, reada_bh,
+ reada_blocks, reada_count);
+ }
+ ll_rw_block(READ, 1, &p_s_bh);
+ wait_on_buffer(p_s_bh);
+ if (!buffer_uptodate(p_s_bh))
+ goto io_error;
+ } else {
+io_error:
p_s_search_path->path_length --;
pathrelse(p_s_search_path);
return IO_ERROR;
}
+ reada_count = 0;
if (expected_level == -1)
expected_level = SB_TREE_HEIGHT (p_s_sb);
expected_level --;
// make sure, that the node contents look like a node of
// certain level
if (!is_tree_node (p_s_bh, expected_level)) {
- reiserfs_warning ("vs-5150: search_by_key: "
- "invalid format found in block %ld. Fsck?\n",
+ reiserfs_warning (p_s_sb, "vs-5150: search_by_key: "
+ "invalid format found in block %ld. Fsck?",
p_s_bh->b_blocknr);
pathrelse (p_s_search_path);
return IO_ERROR;
position in the node. */
n_block_number = B_N_CHILD_NUM(p_s_bh, p_s_last_element->pe_position);
-#ifdef SEARCH_BY_KEY_READA
- /* if we are going to read leaf node, then calculate its right neighbor if possible */
- if (n_node_level == DISK_LEAF_NODE_LEVEL + 1 && p_s_last_element->pe_position < B_NR_ITEMS (p_s_bh))
- right_neighbor_of_leaf_node = B_N_CHILD_NUM(p_s_bh, p_s_last_element->pe_position + 1);
-#endif
+ /* if we are going to read leaf nodes, try for read ahead as well */
+ if ((p_s_search_path->reada & PATH_READA) &&
+ n_node_level == DISK_LEAF_NODE_LEVEL + 1)
+ {
+ int pos = p_s_last_element->pe_position;
+ int limit = B_NR_ITEMS(p_s_bh);
+ struct key *le_key;
+
+ if (p_s_search_path->reada & PATH_READA_BACK)
+ limit = 0;
+ while(reada_count < SEARCH_BY_KEY_READA) {
+ if (pos == limit)
+ break;
+ reada_blocks[reada_count++] = B_N_CHILD_NUM(p_s_bh, pos);
+ if (p_s_search_path->reada & PATH_READA_BACK)
+ pos--;
+ else
+ pos++;
+
+ /*
+ * check to make sure we're in the same object
+ */
+ le_key = B_N_PDELIM_KEY(p_s_bh, pos);
+ if (le32_to_cpu(le_key->k_objectid) !=
+ p_s_key->on_disk_key.k_objectid)
+ {
+ break;
+ }
+ }
+ }
}
}
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 ;
}
}
-
-/* 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
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)*
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;
copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));
s_del_balance.insert_size[0] = n_del_size;
- n_ret_value = fix_nodes(M_DELETE, &s_del_balance, NULL, 0);
+ n_ret_value = fix_nodes(M_DELETE, &s_del_balance, NULL, NULL);
if ( n_ret_value != REPEAT_SEARCH )
break;
if (n_ret_value == IO_ERROR)
break;
if (n_ret_value == FILE_NOT_FOUND) {
- reiserfs_warning ("vs-5340: reiserfs_delete_item: "
- "no items of the file %K found\n", p_s_item_key);
+ reiserfs_warning (p_s_sb, "vs-5340: reiserfs_delete_item: "
+ "no items of the file %K found", p_s_item_key);
break;
}
} /* while (1) */
// 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;
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
+ reiserfs_debug (p_s_sb, "reiserquota delete_item(): freeing %u, id=%u type=%c", 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;
}
/* 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);
while (1) {
retval = search_item (th->t_super, &cpu_key, &path);
if (retval == IO_ERROR) {
- reiserfs_warning ("vs-5350: reiserfs_delete_solid_item: "
- "i/o failure occurred trying to delete %K\n", &cpu_key);
+ reiserfs_warning (th->t_super,
+ "vs-5350: reiserfs_delete_solid_item: "
+ "i/o failure occurred trying to delete %K",
+ &cpu_key);
break;
}
if (retval != ITEM_FOUND) {
// No need for a warning, if there is just no free space to insert '..' item into the newly-created subdir
if ( !( (unsigned long long) GET_HASH_VALUE (le_key_k_offset (le_key_version (key), key)) == 0 && \
(unsigned long long) GET_GENERATION_NUMBER (le_key_k_offset (le_key_version (key), key)) == 1 ) )
- reiserfs_warning ("vs-5355: reiserfs_delete_solid_item: %k not found", key);
+ reiserfs_warning (th->t_super, "vs-5355: reiserfs_delete_solid_item: %k not found", key);
break;
}
if (!tb_init) {
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);
+ retval = fix_nodes (M_DELETE, &tb, NULL, NULL);
if (retval == REPEAT_SEARCH) {
PROC_INFO_INC( th -> t_super, delete_solid_item_restarted );
continue;
}
if (retval == CARRY_ON) {
- do_balance (&tb, 0, 0, M_DELETE);
+ do_balance (&tb, NULL, NULL, M_DELETE);
+ if (inode) { /* Should we count quota for item? (we don't count quotas for save-links) */
+#ifdef REISERQUOTA_DEBUG
+ reiserfs_debug (th->t_super, "reiserquota delete_solid_item(): freeing %u id=%u type=%c", quota_cut_bytes, inode->i_uid, key2type(key));
+#endif
+ DQUOT_FREE_SPACE_NODIRTY(inode, quota_cut_bytes);
+ }
break;
}
// IO_ERROR, NO_DISK_SPACE, etc
- reiserfs_warning ("vs-5360: reiserfs_delete_solid_item: "
- "could not delete %K due to fix_nodes failure\n", &cpu_key);
+ reiserfs_warning (th->t_super, "vs-5360: reiserfs_delete_solid_item: "
+ "could not delete %K due to fix_nodes failure", &cpu_key);
unfix_nodes (&tb);
break;
}
}
/* USE_INODE_GENERATION_COUNTER */
#endif
- reiserfs_delete_solid_item (th, INODE_PKEY (inode));
+ reiserfs_delete_solid_item (th, inode, INODE_PKEY (inode));
}
+static void
+unmap_buffers(struct page *page, loff_t pos) {
+ struct buffer_head *bh ;
+ struct buffer_head *head ;
+ struct buffer_head *next ;
+ unsigned long tail_index ;
+ unsigned long cur_index ;
+
+ if (page) {
+ if (page_has_buffers(page)) {
+ tail_index = pos & (PAGE_CACHE_SIZE - 1) ;
+ cur_index = 0 ;
+ head = page_buffers(page) ;
+ bh = head ;
+ do {
+ next = bh->b_this_page ;
+
+ /* we want to unmap the buffers that contain the tail, and
+ ** all the buffers after it (since the tail must be at the
+ ** end of the file). We don't want to unmap file data
+ ** before the tail, since it might be dirty and waiting to
+ ** reach disk
+ */
+ cur_index += bh->b_size ;
+ if (cur_index > tail_index) {
+ reiserfs_unmap_buffer(bh) ;
+ }
+ bh = next ;
+ } while (bh != head) ;
+ if ( PAGE_SIZE == bh->b_size ) {
+ clear_page_dirty(page);
+ }
+ }
+ }
+}
static int maybe_indirect_to_direct (struct reiserfs_transaction_handle *th,
struct inode * p_s_inode,
"vs-5616: appended bytes found");
PATH_LAST_POSITION (path) --;
- removed = reiserfs_delete_item (th, path, &tail_key, inode, 0/*unbh not needed*/);
+ removed = reiserfs_delete_item (th, path, &tail_key, inode, NULL/*unbh not needed*/);
RFALSE( removed <= 0 || removed > tail_len,
"vs-5617: there was tail %d bytes, removed item length %d bytes",
tail_len, removed);
tail_len -= removed;
set_cpu_key_k_offset (&tail_key, cpu_key_k_offset (&tail_key) - removed);
}
- printk ("indirect_to_direct_roll_back: indirect_to_direct conversion has been rolled back due to lack of disk space\n");
+ reiserfs_warning (inode->i_sb, "indirect_to_direct_roll_back: indirect_to_direct conversion has been rolled back due to lack of disk space");
//mark_file_without_tail (inode);
mark_inode_dirty (inode);
}
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;
+ loff_t tail_pos = 0;
init_tb_struct(th, &s_cut_balance, p_s_inode->i_sb, p_s_path, n_cut_size);
set_cpu_key_k_type (p_s_item_key, TYPE_INDIRECT);
p_s_item_key->key_length = 4;
n_new_file_size -= (n_new_file_size & (p_s_sb->s_blocksize - 1));
+ tail_pos = n_new_file_size;
set_cpu_key_k_offset (p_s_item_key, n_new_file_size + 1);
if ( search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path) == POSITION_NOT_FOUND ){
print_block (PATH_PLAST_BUFFER (p_s_path), 3, PATH_LAST_POSITION (p_s_path) - 1, PATH_LAST_POSITION (p_s_path) + 1);
s_cut_balance.insert_size[0] = n_cut_size;
- n_ret_value = fix_nodes(c_mode, &s_cut_balance, NULL, 0);
+ n_ret_value = fix_nodes(c_mode, &s_cut_balance, NULL, NULL);
if ( n_ret_value != REPEAT_SEARCH )
break;
if (n_ret_value == POSITION_FOUND)
continue;
- reiserfs_warning ("PAP-5610: reiserfs_cut_from_item: item %K not found\n", p_s_item_key);
+ reiserfs_warning (p_s_sb, "PAP-5610: reiserfs_cut_from_item: item %K not found", p_s_item_key);
unfix_nodes (&s_cut_balance);
return (n_ret_value == IO_ERROR) ? -EIO : -ENOENT;
} /* while */
indirect_to_direct_roll_back (th, p_s_inode, p_s_path);
}
if (n_ret_value == NO_DISK_SPACE)
- reiserfs_warning ("NO_DISK_SPACE");
+ reiserfs_warning (p_s_sb, "NO_DISK_SPACE");
unfix_nodes (&s_cut_balance);
return -EIO;
}
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);
if ( n_is_inode_locked ) {
/* we've done an indirect->direct conversion. when the data block
** was freed, it was removed from the list of blocks that must
- ** be flushed before the transaction commits, so we don't need to
- ** deal with it here.
+ ** be flushed before the transaction commits, make sure to
+ ** unmap and invalidate it
*/
+ unmap_buffers(page, tail_pos);
REISERFS_I(p_s_inode)->i_flags &= ~i_pack_on_close_mask ;
}
+#ifdef REISERQUOTA_DEBUG
+ reiserfs_debug (p_s_inode->i_sb, "reiserquota cut_from_item(): freeing %u id=%u type=%c", 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)
- reiserfs_warning ("vs-5655: truncate_directory: link count != 0\n");
+ reiserfs_warning (inode->i_sb,
+ "vs-5655: truncate_directory: link count != 0");
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);
}
retval = search_for_position_by_key(p_s_inode->i_sb, &s_item_key, &s_search_path);
if (retval == IO_ERROR) {
- reiserfs_warning ("vs-5657: reiserfs_do_truncate: "
- "i/o failure occurred trying to truncate %K\n", &s_item_key);
+ reiserfs_warning (p_s_inode->i_sb, "vs-5657: reiserfs_do_truncate: "
+ "i/o failure occurred trying to truncate %K", &s_item_key);
return;
}
if (retval == POSITION_FOUND || retval == FILE_NOT_FOUND) {
pathrelse (&s_search_path);
- reiserfs_warning ("PAP-5660: reiserfs_do_truncate: "
- "wrong result %d of search for %K\n", retval, &s_item_key);
+ reiserfs_warning (p_s_inode->i_sb, "PAP-5660: reiserfs_do_truncate: "
+ "wrong result %d of search for %K", retval, &s_item_key);
return;
}
space, this file would have this file size */
n_file_size = offset + bytes - 1;
}
+ /*
+ * are we doing a full truncate or delete, if so
+ * kick in the reada code
+ */
+ if (n_new_file_size == 0)
+ s_search_path.reada = PATH_READA | PATH_READA_BACK;
if ( n_file_size == 0 || n_file_size < n_new_file_size ) {
goto update_and_out ;
/* Cut or delete file item. */
n_deleted = reiserfs_cut_from_item(th, &s_search_path, &s_item_key, p_s_inode, page, n_new_file_size);
if (n_deleted < 0) {
- reiserfs_warning ("vs-5665: reiserfs_do_truncate: reiserfs_cut_from_item failed");
+ reiserfs_warning (p_s_inode->i_sb, "vs-5665: reiserfs_do_truncate: reiserfs_cut_from_item failed");
reiserfs_check_path(&s_search_path) ;
return;
}
search_for_position_by_key(p_s_inode->i_sb, &s_item_key, &s_search_path) == POSITION_FOUND ) ;
RFALSE( n_file_size > ROUND_UP (n_new_file_size),
- "PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d\n",
+ "PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d",
n_new_file_size, n_file_size, s_item_key.on_disk_key.k_objectid);
update_and_out:
if (le_ih_k_offset (found_ih) + op_bytes_number (found_ih, get_last_bh (path)->b_size) !=
cpu_key_k_offset (p_s_key) ||
op_bytes_number (found_ih, get_last_bh (path)->b_size) != pos_in_item (path))
- reiserfs_panic (0, "PAP-5720: check_research_for_paste: "
+ reiserfs_panic (NULL, "PAP-5720: check_research_for_paste: "
"found direct item %h or position (%d) does not match to key %K",
found_ih, pos_in_item (path), p_s_key);
}
if (le_ih_k_offset (found_ih) + op_bytes_number (found_ih, get_last_bh (path)->b_size) != cpu_key_k_offset (p_s_key) ||
I_UNFM_NUM (found_ih) != pos_in_item (path) ||
get_ih_free_space (found_ih) != 0)
- reiserfs_panic (0, "PAP-5730: check_research_for_paste: "
+ reiserfs_panic (NULL, "PAP-5730: check_research_for_paste: "
"found indirect item (%h) or position (%d) does not match to key (%K)",
found_ih, pos_in_item (path), p_s_key);
}
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
+ reiserfs_debug (inode->i_sb, "reiserquota paste_into_item(): allocating %u id=%u type=%c", 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);
goto error_out ;
}
if (retval == POSITION_FOUND) {
- reiserfs_warning ("PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists\n", p_s_key);
+ reiserfs_warning (inode->i_sb, "PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists", p_s_key);
retval = -EEXIST ;
goto error_out ;
}
error_out:
/* this also releases the path */
unfix_nodes(&s_paste_balance);
+#ifdef REISERQUOTA_DEBUG
+ reiserfs_debug (inode->i_sb, "reiserquota paste_into_item(): freeing %u id=%u type=%c", n_pasted_size, inode->i_uid, key2type(&(p_s_key->on_disk_key)));
+#endif
+ DQUOT_FREE_SPACE_NODIRTY(inode, n_pasted_size);
return retval ;
}
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
+ reiserfs_debug (inode->i_sb, "reiserquota insert_item(): allocating %u id=%u type=%c", 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);
goto error_out ;
}
if (retval == ITEM_FOUND) {
- reiserfs_warning ("PAP-5760: reiserfs_insert_item: "
- "key %K already exists in the tree\n", key);
+ reiserfs_warning (th->t_super, "PAP-5760: reiserfs_insert_item: "
+ "key %K already exists in the tree", key);
retval = -EEXIST ;
goto error_out;
}
error_out:
/* also releases the path */
unfix_nodes(&s_ins_balance);
+#ifdef REISERQUOTA_DEBUG
+ reiserfs_debug (th->t_super, "reiserquota insert_item(): freeing %u id=%u type=%c", quota_bytes, inode->i_uid, head2type(p_s_ih));
+#endif
+ if (inode)
+ DQUOT_FREE_SPACE_NODIRTY(inode, quota_bytes) ;
return retval;
}