Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull reiserfs and ext3 changes from Jan Kara: "Big reiserfs cleanup from Jeff, an ext3 deadlock fix, and some small cleanups" * 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: (34 commits) reiserfs: Fix compilation breakage with CONFIG_REISERFS_CHECK ext3: Fix deadlock in data=journal mode when fs is frozen reiserfs: call truncate_setsize under tailpack mutex fs/jbd/revoke.c: replace shift loop by ilog2 reiserfs: remove obsolete __constant_cpu_to_le32 reiserfs: balance_leaf refactor, split up balance_leaf_when_delete reiserfs: balance_leaf refactor, format balance_leaf_finish_node reiserfs: balance_leaf refactor, format balance_leaf_new_nodes_paste reiserfs: balance_leaf refactor, format balance_leaf_paste_right reiserfs: balance_leaf refactor, format balance_leaf_insert_right reiserfs: balance_leaf refactor, format balance_leaf_paste_left reiserfs: balance_leaf refactor, format balance_leaf_insert_left reiserfs: balance_leaf refactor, pull out balance_leaf{left, right, new_nodes, finish_node} reiserfs: balance_leaf refactor, pull out balance_leaf_finish_node_paste reiserfs: balance_leaf refactor pull out balance_leaf_finish_node_insert reiserfs: balance_leaf refactor, pull out balance_leaf_new_nodes_paste reiserfs: balance_leaf refactor, pull out balance_leaf_new_nodes_insert reiserfs: balance_leaf refactor, pull out balance_leaf_paste_right reiserfs: balance_leaf refactor, pull out balance_leaf_insert_right reiserfs: balance_leaf refactor, pull out balance_leaf_paste_left ...
This commit is contained in:
Коммит
2840c566e9
|
@ -1716,17 +1716,17 @@ static int ext3_journalled_writepage(struct page *page,
|
|||
WARN_ON_ONCE(IS_RDONLY(inode) &&
|
||||
!(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ERROR_FS));
|
||||
|
||||
trace_ext3_journalled_writepage(page);
|
||||
if (!page_has_buffers(page) || PageChecked(page)) {
|
||||
if (ext3_journal_current_handle())
|
||||
goto no_write;
|
||||
|
||||
trace_ext3_journalled_writepage(page);
|
||||
handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode));
|
||||
handle = ext3_journal_start(inode,
|
||||
ext3_writepage_trans_blocks(inode));
|
||||
if (IS_ERR(handle)) {
|
||||
ret = PTR_ERR(handle);
|
||||
goto no_write;
|
||||
}
|
||||
|
||||
if (!page_has_buffers(page) || PageChecked(page)) {
|
||||
/*
|
||||
* It's mmapped pagecache. Add buffers and journal it. There
|
||||
* doesn't seem much point in redirtying the page here.
|
||||
|
@ -1749,17 +1749,18 @@ static int ext3_journalled_writepage(struct page *page,
|
|||
atomic_set(&EXT3_I(inode)->i_datasync_tid,
|
||||
handle->h_transaction->t_tid);
|
||||
unlock_page(page);
|
||||
} else {
|
||||
/*
|
||||
* It may be a page full of checkpoint-mode buffers. We don't
|
||||
* really know unless we go poke around in the buffer_heads.
|
||||
* But block_write_full_page will do the right thing.
|
||||
*/
|
||||
ret = block_write_full_page(page, ext3_get_block, wbc);
|
||||
}
|
||||
err = ext3_journal_stop(handle);
|
||||
if (!ret)
|
||||
ret = err;
|
||||
} else {
|
||||
/*
|
||||
* It is a page full of checkpoint-mode buffers. Go and write
|
||||
* them. They should have been already mapped when they went
|
||||
* to the journal so provide NULL get_block function to catch
|
||||
* errors.
|
||||
*/
|
||||
ret = block_write_full_page(page, NULL, wbc);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -231,19 +231,15 @@ record_cache_failure:
|
|||
|
||||
static struct jbd_revoke_table_s *journal_init_revoke_table(int hash_size)
|
||||
{
|
||||
int shift = 0;
|
||||
int tmp = hash_size;
|
||||
int i;
|
||||
struct jbd_revoke_table_s *table;
|
||||
|
||||
table = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
|
||||
if (!table)
|
||||
goto out;
|
||||
|
||||
while((tmp >>= 1UL) != 0UL)
|
||||
shift++;
|
||||
|
||||
table->hash_size = hash_size;
|
||||
table->hash_shift = shift;
|
||||
table->hash_shift = ilog2(hash_size);
|
||||
table->hash_table =
|
||||
kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
|
||||
if (!table->hash_table) {
|
||||
|
@ -252,8 +248,8 @@ static struct jbd_revoke_table_s *journal_init_revoke_table(int hash_size)
|
|||
goto out;
|
||||
}
|
||||
|
||||
for (tmp = 0; tmp < hash_size; tmp++)
|
||||
INIT_LIST_HEAD(&table->hash_table[tmp]);
|
||||
for (i = 0; i < hash_size; i++)
|
||||
INIT_LIST_HEAD(&table->hash_table[i]);
|
||||
|
||||
out:
|
||||
return table;
|
||||
|
|
|
@ -50,8 +50,10 @@ static inline void get_bit_address(struct super_block *s,
|
|||
unsigned int *bmap_nr,
|
||||
unsigned int *offset)
|
||||
{
|
||||
/* It is in the bitmap block number equal to the block
|
||||
* number divided by the number of bits in a block. */
|
||||
/*
|
||||
* It is in the bitmap block number equal to the block
|
||||
* number divided by the number of bits in a block.
|
||||
*/
|
||||
*bmap_nr = block >> (s->s_blocksize_bits + 3);
|
||||
/* Within that bitmap block it is located at bit offset *offset. */
|
||||
*offset = block & ((s->s_blocksize << 3) - 1);
|
||||
|
@ -71,10 +73,12 @@ int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
|
|||
|
||||
get_bit_address(s, block, &bmap, &offset);
|
||||
|
||||
/* Old format filesystem? Unlikely, but the bitmaps are all up front so
|
||||
* we need to account for it. */
|
||||
/*
|
||||
* Old format filesystem? Unlikely, but the bitmaps are all
|
||||
* up front so we need to account for it.
|
||||
*/
|
||||
if (unlikely(test_bit(REISERFS_OLD_FORMAT,
|
||||
&(REISERFS_SB(s)->s_properties)))) {
|
||||
&REISERFS_SB(s)->s_properties))) {
|
||||
b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1;
|
||||
if (block >= bmap1 &&
|
||||
block <= bmap1 + bmap_count) {
|
||||
|
@ -108,8 +112,11 @@ int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* searches in journal structures for a given block number (bmap, off). If block
|
||||
is found in reiserfs journal it suggests next free block candidate to test. */
|
||||
/*
|
||||
* Searches in journal structures for a given block number (bmap, off).
|
||||
* If block is found in reiserfs journal it suggests next free block
|
||||
* candidate to test.
|
||||
*/
|
||||
static inline int is_block_in_journal(struct super_block *s, unsigned int bmap,
|
||||
int off, int *next)
|
||||
{
|
||||
|
@ -129,8 +136,10 @@ static inline int is_block_in_journal(struct super_block *s, unsigned int bmap,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* it searches for a window of zero bits with given minimum and maximum lengths in one bitmap
|
||||
* block; */
|
||||
/*
|
||||
* Searches for a window of zero bits with given minimum and maximum
|
||||
* lengths in one bitmap block
|
||||
*/
|
||||
static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
|
||||
unsigned int bmap_n, int *beg, int boundary,
|
||||
int min, int max, int unfm)
|
||||
|
@ -145,10 +154,6 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
|
|||
RFALSE(bmap_n >= reiserfs_bmap_count(s), "Bitmap %u is out of "
|
||||
"range (0..%u)", bmap_n, reiserfs_bmap_count(s) - 1);
|
||||
PROC_INFO_INC(s, scan_bitmap.bmap);
|
||||
/* this is unclear and lacks comments, explain how journal bitmaps
|
||||
work here for the reader. Convey a sense of the design here. What
|
||||
is a window? */
|
||||
/* - I mean `a window of zero bits' as in description of this function - Zam. */
|
||||
|
||||
if (!bi) {
|
||||
reiserfs_error(s, "jdm-4055", "NULL bitmap info pointer "
|
||||
|
@ -161,18 +166,21 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
|
|||
return 0;
|
||||
|
||||
while (1) {
|
||||
cont:
|
||||
cont:
|
||||
if (bi->free_count < min) {
|
||||
brelse(bh);
|
||||
return 0; // No free blocks in this bitmap
|
||||
return 0; /* No free blocks in this bitmap */
|
||||
}
|
||||
|
||||
/* search for a first zero bit -- beginning of a window */
|
||||
*beg = reiserfs_find_next_zero_le_bit
|
||||
((unsigned long *)(bh->b_data), boundary, *beg);
|
||||
|
||||
if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block
|
||||
* cannot contain a zero window of minimum size */
|
||||
/*
|
||||
* search for a zero bit fails or the rest of bitmap block
|
||||
* cannot contain a zero window of minimum size
|
||||
*/
|
||||
if (*beg + min > boundary) {
|
||||
brelse(bh);
|
||||
return 0;
|
||||
}
|
||||
|
@ -186,49 +194,75 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th,
|
|||
next = end;
|
||||
break;
|
||||
}
|
||||
/* finding the other end of zero bit window requires looking into journal structures (in
|
||||
* case of searching for free blocks for unformatted nodes) */
|
||||
|
||||
/*
|
||||
* finding the other end of zero bit window requires
|
||||
* looking into journal structures (in case of
|
||||
* searching for free blocks for unformatted nodes)
|
||||
*/
|
||||
if (unfm && is_block_in_journal(s, bmap_n, end, &next))
|
||||
break;
|
||||
}
|
||||
|
||||
/* now (*beg) points to beginning of zero bits window,
|
||||
* (end) points to one bit after the window end */
|
||||
if (end - *beg >= min) { /* it seems we have found window of proper size */
|
||||
/*
|
||||
* now (*beg) points to beginning of zero bits window,
|
||||
* (end) points to one bit after the window end
|
||||
*/
|
||||
|
||||
/* found window of proper size */
|
||||
if (end - *beg >= min) {
|
||||
int i;
|
||||
reiserfs_prepare_for_journal(s, bh, 1);
|
||||
/* try to set all blocks used checking are they still free */
|
||||
/*
|
||||
* try to set all blocks used checking are
|
||||
* they still free
|
||||
*/
|
||||
for (i = *beg; i < end; i++) {
|
||||
/* It seems that we should not check in journal again. */
|
||||
/* Don't check in journal again. */
|
||||
if (reiserfs_test_and_set_le_bit
|
||||
(i, bh->b_data)) {
|
||||
/* bit was set by another process
|
||||
* while we slept in prepare_for_journal() */
|
||||
/*
|
||||
* bit was set by another process while
|
||||
* we slept in prepare_for_journal()
|
||||
*/
|
||||
PROC_INFO_INC(s, scan_bitmap.stolen);
|
||||
if (i >= *beg + min) { /* we can continue with smaller set of allocated blocks,
|
||||
* if length of this set is more or equal to `min' */
|
||||
|
||||
/*
|
||||
* we can continue with smaller set
|
||||
* of allocated blocks, if length of
|
||||
* this set is more or equal to `min'
|
||||
*/
|
||||
if (i >= *beg + min) {
|
||||
end = i;
|
||||
break;
|
||||
}
|
||||
/* otherwise we clear all bit were set ... */
|
||||
|
||||
/*
|
||||
* otherwise we clear all bit
|
||||
* were set ...
|
||||
*/
|
||||
while (--i >= *beg)
|
||||
reiserfs_clear_le_bit
|
||||
(i, bh->b_data);
|
||||
reiserfs_restore_prepared_buffer(s, bh);
|
||||
*beg = org;
|
||||
/* ... and search again in current block from beginning */
|
||||
|
||||
/*
|
||||
* Search again in current block
|
||||
* from beginning
|
||||
*/
|
||||
goto cont;
|
||||
}
|
||||
}
|
||||
bi->free_count -= (end - *beg);
|
||||
journal_mark_dirty(th, s, bh);
|
||||
journal_mark_dirty(th, bh);
|
||||
brelse(bh);
|
||||
|
||||
/* free block count calculation */
|
||||
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s),
|
||||
1);
|
||||
PUT_SB_FREE_BLOCKS(s, SB_FREE_BLOCKS(s) - (end - *beg));
|
||||
journal_mark_dirty(th, s, SB_BUFFER_WITH_SB(s));
|
||||
journal_mark_dirty(th, SB_BUFFER_WITH_SB(s));
|
||||
|
||||
return end - (*beg);
|
||||
} else {
|
||||
|
@ -267,11 +301,13 @@ static inline int block_group_used(struct super_block *s, u32 id)
|
|||
int bm = bmap_hash_id(s, id);
|
||||
struct reiserfs_bitmap_info *info = &SB_AP_BITMAP(s)[bm];
|
||||
|
||||
/* If we don't have cached information on this bitmap block, we're
|
||||
/*
|
||||
* If we don't have cached information on this bitmap block, we're
|
||||
* going to have to load it later anyway. Loading it here allows us
|
||||
* to make a better decision. This favors long-term performance gain
|
||||
* with a better on-disk layout vs. a short term gain of skipping the
|
||||
* read and potentially having a bad placement. */
|
||||
* read and potentially having a bad placement.
|
||||
*/
|
||||
if (info->free_count == UINT_MAX) {
|
||||
struct buffer_head *bh = reiserfs_read_bitmap_block(s, bm);
|
||||
brelse(bh);
|
||||
|
@ -304,25 +340,26 @@ __le32 reiserfs_choose_packing(struct inode * dir)
|
|||
return packing;
|
||||
}
|
||||
|
||||
/* Tries to find contiguous zero bit window (given size) in given region of
|
||||
* bitmap and place new blocks there. Returns number of allocated blocks. */
|
||||
/*
|
||||
* Tries to find contiguous zero bit window (given size) in given region of
|
||||
* bitmap and place new blocks there. Returns number of allocated blocks.
|
||||
*/
|
||||
static int scan_bitmap(struct reiserfs_transaction_handle *th,
|
||||
b_blocknr_t * start, b_blocknr_t finish,
|
||||
int min, int max, int unfm, sector_t file_block)
|
||||
{
|
||||
int nr_allocated = 0;
|
||||
struct super_block *s = th->t_super;
|
||||
/* find every bm and bmap and bmap_nr in this file, and change them all to bitmap_blocknr
|
||||
* - Hans, it is not a block number - Zam. */
|
||||
|
||||
unsigned int bm, off;
|
||||
unsigned int end_bm, end_off;
|
||||
unsigned int off_max = s->s_blocksize << 3;
|
||||
|
||||
BUG_ON(!th->t_trans_id);
|
||||
PROC_INFO_INC(s, scan_bitmap.call);
|
||||
|
||||
/* No point in looking for more free blocks */
|
||||
if (SB_FREE_BLOCKS(s) <= 0)
|
||||
return 0; // No point in looking for more free blocks
|
||||
return 0;
|
||||
|
||||
get_bit_address(s, *start, &bm, &off);
|
||||
get_bit_address(s, finish, &end_bm, &end_off);
|
||||
|
@ -331,7 +368,8 @@ static int scan_bitmap(struct reiserfs_transaction_handle *th,
|
|||
if (end_bm > reiserfs_bmap_count(s))
|
||||
end_bm = reiserfs_bmap_count(s);
|
||||
|
||||
/* When the bitmap is more than 10% free, anyone can allocate.
|
||||
/*
|
||||
* When the bitmap is more than 10% free, anyone can allocate.
|
||||
* When it's less than 10% free, only files that already use the
|
||||
* bitmap are allowed. Once we pass 80% full, this restriction
|
||||
* is lifted.
|
||||
|
@ -369,7 +407,7 @@ static int scan_bitmap(struct reiserfs_transaction_handle *th,
|
|||
nr_allocated =
|
||||
scan_bitmap_block(th, bm, &off, end_off + 1, min, max, unfm);
|
||||
|
||||
ret:
|
||||
ret:
|
||||
*start = bm * off_max + off;
|
||||
return nr_allocated;
|
||||
|
||||
|
@ -411,14 +449,14 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th,
|
|||
"block %lu: bit already cleared", block);
|
||||
}
|
||||
apbi[nr].free_count++;
|
||||
journal_mark_dirty(th, s, bmbh);
|
||||
journal_mark_dirty(th, bmbh);
|
||||
brelse(bmbh);
|
||||
|
||||
reiserfs_prepare_for_journal(s, sbh, 1);
|
||||
/* update super block */
|
||||
set_sb_free_blocks(rs, sb_free_blocks(rs) + 1);
|
||||
|
||||
journal_mark_dirty(th, s, sbh);
|
||||
journal_mark_dirty(th, sbh);
|
||||
if (for_unformatted) {
|
||||
int depth = reiserfs_write_unlock_nested(s);
|
||||
dquot_free_block_nodirty(inode, 1);
|
||||
|
@ -483,7 +521,7 @@ static void __discard_prealloc(struct reiserfs_transaction_handle *th,
|
|||
if (dirty)
|
||||
reiserfs_update_sd(th, inode);
|
||||
ei->i_prealloc_block = save;
|
||||
list_del_init(&(ei->i_prealloc_list));
|
||||
list_del_init(&ei->i_prealloc_list);
|
||||
}
|
||||
|
||||
/* FIXME: It should be inline function */
|
||||
|
@ -529,7 +567,8 @@ int reiserfs_parse_alloc_options(struct super_block *s, char *options)
|
|||
{
|
||||
char *this_char, *value;
|
||||
|
||||
REISERFS_SB(s)->s_alloc_options.bits = 0; /* clear default settings */
|
||||
/* clear default settings */
|
||||
REISERFS_SB(s)->s_alloc_options.bits = 0;
|
||||
|
||||
while ((this_char = strsep(&options, ":")) != NULL) {
|
||||
if ((value = strchr(this_char, '=')) != NULL)
|
||||
|
@ -731,7 +770,7 @@ static inline void new_hashed_relocation(reiserfs_blocknr_hint_t * hint)
|
|||
hash_in = (char *)&hint->key.k_dir_id;
|
||||
} else {
|
||||
if (!hint->inode) {
|
||||
//hint->search_start = hint->beg;
|
||||
/*hint->search_start = hint->beg;*/
|
||||
hash_in = (char *)&hint->key.k_dir_id;
|
||||
} else
|
||||
if (TEST_OPTION(displace_based_on_dirid, hint->th->t_super))
|
||||
|
@ -785,7 +824,8 @@ static void oid_groups(reiserfs_blocknr_hint_t * hint)
|
|||
|
||||
dirid = le32_to_cpu(INODE_PKEY(hint->inode)->k_dir_id);
|
||||
|
||||
/* keep the root dir and it's first set of subdirs close to
|
||||
/*
|
||||
* keep the root dir and it's first set of subdirs close to
|
||||
* the start of the disk
|
||||
*/
|
||||
if (dirid <= 2)
|
||||
|
@ -799,7 +839,8 @@ static void oid_groups(reiserfs_blocknr_hint_t * hint)
|
|||
}
|
||||
}
|
||||
|
||||
/* returns 1 if it finds an indirect item and gets valid hint info
|
||||
/*
|
||||
* returns 1 if it finds an indirect item and gets valid hint info
|
||||
* from it, otherwise 0
|
||||
*/
|
||||
static int get_left_neighbor(reiserfs_blocknr_hint_t * hint)
|
||||
|
@ -811,25 +852,29 @@ static int get_left_neighbor(reiserfs_blocknr_hint_t * hint)
|
|||
__le32 *item;
|
||||
int ret = 0;
|
||||
|
||||
if (!hint->path) /* reiserfs code can call this function w/o pointer to path
|
||||
* structure supplied; then we rely on supplied search_start */
|
||||
/*
|
||||
* reiserfs code can call this function w/o pointer to path
|
||||
* structure supplied; then we rely on supplied search_start
|
||||
*/
|
||||
if (!hint->path)
|
||||
return 0;
|
||||
|
||||
path = hint->path;
|
||||
bh = get_last_bh(path);
|
||||
RFALSE(!bh, "green-4002: Illegal path specified to get_left_neighbor");
|
||||
ih = get_ih(path);
|
||||
ih = tp_item_head(path);
|
||||
pos_in_item = path->pos_in_item;
|
||||
item = get_item(path);
|
||||
item = tp_item_body(path);
|
||||
|
||||
hint->search_start = bh->b_blocknr;
|
||||
|
||||
/*
|
||||
* for indirect item: go to left and look for the first non-hole entry
|
||||
* in the indirect item
|
||||
*/
|
||||
if (!hint->formatted_node && is_indirect_le_ih(ih)) {
|
||||
/* for indirect item: go to left and look for the first non-hole entry
|
||||
in the indirect item */
|
||||
if (pos_in_item == I_UNFM_NUM(ih))
|
||||
pos_in_item--;
|
||||
// pos_in_item = I_UNFM_NUM (ih) - 1;
|
||||
while (pos_in_item >= 0) {
|
||||
int t = get_block_num(item, pos_in_item);
|
||||
if (t) {
|
||||
|
@ -845,10 +890,12 @@ static int get_left_neighbor(reiserfs_blocknr_hint_t * hint)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* should be, if formatted node, then try to put on first part of the device
|
||||
specified as number of percent with mount option device, else try to put
|
||||
on last of device. This is not to say it is good code to do so,
|
||||
but the effect should be measured. */
|
||||
/*
|
||||
* should be, if formatted node, then try to put on first part of the device
|
||||
* specified as number of percent with mount option device, else try to put
|
||||
* on last of device. This is not to say it is good code to do so,
|
||||
* but the effect should be measured.
|
||||
*/
|
||||
static inline void set_border_in_hint(struct super_block *s,
|
||||
reiserfs_blocknr_hint_t * hint)
|
||||
{
|
||||
|
@ -974,21 +1021,27 @@ static void determine_search_start(reiserfs_blocknr_hint_t * hint,
|
|||
set_border_in_hint(s, hint);
|
||||
|
||||
#ifdef DISPLACE_NEW_PACKING_LOCALITIES
|
||||
/* whenever we create a new directory, we displace it. At first we will
|
||||
hash for location, later we might look for a moderately empty place for
|
||||
it */
|
||||
/*
|
||||
* whenever we create a new directory, we displace it. At first
|
||||
* we will hash for location, later we might look for a moderately
|
||||
* empty place for it
|
||||
*/
|
||||
if (displacing_new_packing_localities(s)
|
||||
&& hint->th->displace_new_blocks) {
|
||||
displace_new_packing_locality(hint);
|
||||
|
||||
/* we do not continue determine_search_start,
|
||||
* if new packing locality is being displaced */
|
||||
/*
|
||||
* we do not continue determine_search_start,
|
||||
* if new packing locality is being displaced
|
||||
*/
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* all persons should feel encouraged to add more special cases here and
|
||||
* test them */
|
||||
/*
|
||||
* all persons should feel encouraged to add more special cases
|
||||
* here and test them
|
||||
*/
|
||||
|
||||
if (displacing_large_files(s) && !hint->formatted_node
|
||||
&& this_blocknr_allocation_would_make_it_a_large_file(hint)) {
|
||||
|
@ -996,8 +1049,10 @@ static void determine_search_start(reiserfs_blocknr_hint_t * hint,
|
|||
return;
|
||||
}
|
||||
|
||||
/* if none of our special cases is relevant, use the left neighbor in the
|
||||
tree order of the new node we are allocating for */
|
||||
/*
|
||||
* if none of our special cases is relevant, use the left
|
||||
* neighbor in the tree order of the new node we are allocating for
|
||||
*/
|
||||
if (hint->formatted_node && TEST_OPTION(hashed_formatted_nodes, s)) {
|
||||
hash_formatted_node(hint);
|
||||
return;
|
||||
|
@ -1005,10 +1060,13 @@ static void determine_search_start(reiserfs_blocknr_hint_t * hint,
|
|||
|
||||
unfm_hint = get_left_neighbor(hint);
|
||||
|
||||
/* Mimic old block allocator behaviour, that is if VFS allowed for preallocation,
|
||||
new blocks are displaced based on directory ID. Also, if suggested search_start
|
||||
is less than last preallocated block, we start searching from it, assuming that
|
||||
HDD dataflow is faster in forward direction */
|
||||
/*
|
||||
* Mimic old block allocator behaviour, that is if VFS allowed for
|
||||
* preallocation, new blocks are displaced based on directory ID.
|
||||
* Also, if suggested search_start is less than last preallocated
|
||||
* block, we start searching from it, assuming that HDD dataflow
|
||||
* is faster in forward direction
|
||||
*/
|
||||
if (TEST_OPTION(old_way, s)) {
|
||||
if (!hint->formatted_node) {
|
||||
if (!reiserfs_hashed_relocation(s))
|
||||
|
@ -1037,11 +1095,13 @@ static void determine_search_start(reiserfs_blocknr_hint_t * hint,
|
|||
TEST_OPTION(old_hashed_relocation, s)) {
|
||||
old_hashed_relocation(hint);
|
||||
}
|
||||
|
||||
/* new_hashed_relocation works with both formatted/unformatted nodes */
|
||||
if ((!unfm_hint || hint->formatted_node) &&
|
||||
TEST_OPTION(new_hashed_relocation, s)) {
|
||||
new_hashed_relocation(hint);
|
||||
}
|
||||
|
||||
/* dirid grouping works only on unformatted nodes */
|
||||
if (!unfm_hint && !hint->formatted_node && TEST_OPTION(dirid_groups, s)) {
|
||||
dirid_groups(hint);
|
||||
|
@ -1079,8 +1139,6 @@ static int determine_prealloc_size(reiserfs_blocknr_hint_t * hint)
|
|||
return CARRY_ON;
|
||||
}
|
||||
|
||||
/* XXX I know it could be merged with upper-level function;
|
||||
but may be result function would be too complex. */
|
||||
static inline int allocate_without_wrapping_disk(reiserfs_blocknr_hint_t * hint,
|
||||
b_blocknr_t * new_blocknrs,
|
||||
b_blocknr_t start,
|
||||
|
@ -1108,7 +1166,10 @@ static inline int allocate_without_wrapping_disk(reiserfs_blocknr_hint_t * hint,
|
|||
|
||||
/* do we have something to fill prealloc. array also ? */
|
||||
if (nr_allocated > 0) {
|
||||
/* it means prealloc_size was greater that 0 and we do preallocation */
|
||||
/*
|
||||
* it means prealloc_size was greater that 0 and
|
||||
* we do preallocation
|
||||
*/
|
||||
list_add(&REISERFS_I(hint->inode)->i_prealloc_list,
|
||||
&SB_JOURNAL(hint->th->t_super)->
|
||||
j_prealloc_list);
|
||||
|
@ -1176,7 +1237,8 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
|
|||
start = 0;
|
||||
finish = hint->beg;
|
||||
break;
|
||||
default: /* We've tried searching everywhere, not enough space */
|
||||
default:
|
||||
/* We've tried searching everywhere, not enough space */
|
||||
/* Free the blocks */
|
||||
if (!hint->formatted_node) {
|
||||
#ifdef REISERQUOTA_DEBUG
|
||||
|
@ -1261,8 +1323,11 @@ static int use_preallocated_list_if_available(reiserfs_blocknr_hint_t * hint,
|
|||
return amount_needed;
|
||||
}
|
||||
|
||||
int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t * hint, b_blocknr_t * new_blocknrs, int amount_needed, int reserved_by_us /* Amount of blocks we have
|
||||
already reserved */ )
|
||||
int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *hint,
|
||||
b_blocknr_t *new_blocknrs,
|
||||
int amount_needed,
|
||||
/* Amount of blocks we have already reserved */
|
||||
int reserved_by_us)
|
||||
{
|
||||
int initial_amount_needed = amount_needed;
|
||||
int ret;
|
||||
|
@ -1274,15 +1339,21 @@ int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t * hint, b_blocknr_t * new
|
|||
return NO_DISK_SPACE;
|
||||
/* should this be if !hint->inode && hint->preallocate? */
|
||||
/* do you mean hint->formatted_node can be removed ? - Zam */
|
||||
/* hint->formatted_node cannot be removed because we try to access
|
||||
inode information here, and there is often no inode assotiated with
|
||||
metadata allocations - green */
|
||||
/*
|
||||
* hint->formatted_node cannot be removed because we try to access
|
||||
* inode information here, and there is often no inode associated with
|
||||
* metadata allocations - green
|
||||
*/
|
||||
|
||||
if (!hint->formatted_node && hint->preallocate) {
|
||||
amount_needed = use_preallocated_list_if_available
|
||||
(hint, new_blocknrs, amount_needed);
|
||||
if (amount_needed == 0) /* all blocknrs we need we got from
|
||||
prealloc. list */
|
||||
|
||||
/*
|
||||
* We have all the block numbers we need from the
|
||||
* prealloc list
|
||||
*/
|
||||
if (amount_needed == 0)
|
||||
return CARRY_ON;
|
||||
new_blocknrs += (initial_amount_needed - amount_needed);
|
||||
}
|
||||
|
@ -1296,10 +1367,12 @@ int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t * hint, b_blocknr_t * new
|
|||
ret = blocknrs_and_prealloc_arrays_from_search_start
|
||||
(hint, new_blocknrs, amount_needed);
|
||||
|
||||
/* we used prealloc. list to fill (partially) new_blocknrs array. If final allocation fails we
|
||||
* need to return blocks back to prealloc. list or just free them. -- Zam (I chose second
|
||||
* variant) */
|
||||
|
||||
/*
|
||||
* We used prealloc. list to fill (partially) new_blocknrs array.
|
||||
* If final allocation fails we need to return blocks back to
|
||||
* prealloc. list or just free them. -- Zam (I chose second
|
||||
* variant)
|
||||
*/
|
||||
if (ret != CARRY_ON) {
|
||||
while (amount_needed++ < initial_amount_needed) {
|
||||
reiserfs_free_block(hint->th, hint->inode,
|
||||
|
@ -1338,10 +1411,12 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
|
|||
struct reiserfs_bitmap_info *info = SB_AP_BITMAP(sb) + bitmap;
|
||||
struct buffer_head *bh;
|
||||
|
||||
/* Way old format filesystems had the bitmaps packed up front.
|
||||
* I doubt there are any of these left, but just in case... */
|
||||
/*
|
||||
* Way old format filesystems had the bitmaps packed up front.
|
||||
* I doubt there are any of these left, but just in case...
|
||||
*/
|
||||
if (unlikely(test_bit(REISERFS_OLD_FORMAT,
|
||||
&(REISERFS_SB(sb)->s_properties))))
|
||||
&REISERFS_SB(sb)->s_properties)))
|
||||
block = REISERFS_SB(sb)->s_sbh->b_blocknr + 1 + bitmap;
|
||||
else if (bitmap == 0)
|
||||
block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1;
|
||||
|
|
|
@ -59,7 +59,10 @@ static inline bool is_privroot_deh(struct inode *dir, struct reiserfs_de_head *d
|
|||
|
||||
int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
|
||||
{
|
||||
struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */
|
||||
|
||||
/* key of current position in the directory (key of directory entry) */
|
||||
struct cpu_key pos_key;
|
||||
|
||||
INITIALIZE_PATH(path_to_entry);
|
||||
struct buffer_head *bh;
|
||||
int item_num, entry_num;
|
||||
|
@ -77,21 +80,28 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
|
|||
|
||||
reiserfs_check_lock_depth(inode->i_sb, "readdir");
|
||||
|
||||
/* form key for search the next directory entry using f_pos field of
|
||||
file structure */
|
||||
/*
|
||||
* form key for search the next directory entry using
|
||||
* f_pos field of file structure
|
||||
*/
|
||||
make_cpu_key(&pos_key, inode, ctx->pos ?: DOT_OFFSET, TYPE_DIRENTRY, 3);
|
||||
next_pos = cpu_key_k_offset(&pos_key);
|
||||
|
||||
path_to_entry.reada = PATH_READA;
|
||||
while (1) {
|
||||
research:
|
||||
/* search the directory item, containing entry with specified key */
|
||||
research:
|
||||
/*
|
||||
* search the directory item, containing entry with
|
||||
* specified key
|
||||
*/
|
||||
search_res =
|
||||
search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry,
|
||||
&de);
|
||||
if (search_res == IO_ERROR) {
|
||||
// FIXME: we could just skip part of directory which could
|
||||
// not be read
|
||||
/*
|
||||
* FIXME: we could just skip part of directory
|
||||
* which could not be read
|
||||
*/
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
@ -102,41 +112,49 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
|
|||
store_ih(&tmp_ih, ih);
|
||||
|
||||
/* we must have found item, that is item of this directory, */
|
||||
RFALSE(COMP_SHORT_KEYS(&(ih->ih_key), &pos_key),
|
||||
RFALSE(COMP_SHORT_KEYS(&ih->ih_key, &pos_key),
|
||||
"vs-9000: found item %h does not match to dir we readdir %K",
|
||||
ih, &pos_key);
|
||||
RFALSE(item_num > B_NR_ITEMS(bh) - 1,
|
||||
"vs-9005 item_num == %d, item amount == %d",
|
||||
item_num, B_NR_ITEMS(bh));
|
||||
|
||||
/* and entry must be not more than number of entries in the item */
|
||||
RFALSE(I_ENTRY_COUNT(ih) < entry_num,
|
||||
/*
|
||||
* and entry must be not more than number of entries
|
||||
* in the item
|
||||
*/
|
||||
RFALSE(ih_entry_count(ih) < entry_num,
|
||||
"vs-9010: entry number is too big %d (%d)",
|
||||
entry_num, I_ENTRY_COUNT(ih));
|
||||
entry_num, ih_entry_count(ih));
|
||||
|
||||
/*
|
||||
* go through all entries in the directory item beginning
|
||||
* from the entry, that has been found
|
||||
*/
|
||||
if (search_res == POSITION_FOUND
|
||||
|| entry_num < I_ENTRY_COUNT(ih)) {
|
||||
/* go through all entries in the directory item beginning from the entry, that has been found */
|
||||
|| entry_num < ih_entry_count(ih)) {
|
||||
struct reiserfs_de_head *deh =
|
||||
B_I_DEH(bh, ih) + entry_num;
|
||||
|
||||
for (; entry_num < I_ENTRY_COUNT(ih);
|
||||
for (; entry_num < ih_entry_count(ih);
|
||||
entry_num++, deh++) {
|
||||
int d_reclen;
|
||||
char *d_name;
|
||||
ino_t d_ino;
|
||||
loff_t cur_pos = deh_offset(deh);
|
||||
|
||||
if (!de_visible(deh))
|
||||
/* it is hidden entry */
|
||||
if (!de_visible(deh))
|
||||
continue;
|
||||
d_reclen = entry_length(bh, ih, entry_num);
|
||||
d_name = B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh);
|
||||
|
||||
if (d_reclen <= 0 ||
|
||||
d_name + d_reclen > bh->b_data + bh->b_size) {
|
||||
/* There is corrupted data in entry,
|
||||
* We'd better stop here */
|
||||
/*
|
||||
* There is corrupted data in entry,
|
||||
* We'd better stop here
|
||||
*/
|
||||
pathrelse(&path_to_entry);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
|
@ -145,10 +163,10 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
|
|||
if (!d_name[d_reclen - 1])
|
||||
d_reclen = strlen(d_name);
|
||||
|
||||
/* too big to send back to VFS */
|
||||
if (d_reclen >
|
||||
REISERFS_MAX_NAME(inode->i_sb->
|
||||
s_blocksize)) {
|
||||
/* too big to send back to VFS */
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -173,10 +191,14 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
|
|||
goto research;
|
||||
}
|
||||
}
|
||||
// Note, that we copy name to user space via temporary
|
||||
// buffer (local_buf) because filldir will block if
|
||||
// user space buffer is swapped out. At that time
|
||||
// entry can move to somewhere else
|
||||
|
||||
/*
|
||||
* Note, that we copy name to user space via
|
||||
* temporary buffer (local_buf) because
|
||||
* filldir will block if user space buffer is
|
||||
* swapped out. At that time entry can move to
|
||||
* somewhere else
|
||||
*/
|
||||
memcpy(local_buf, d_name, d_reclen);
|
||||
|
||||
/*
|
||||
|
@ -209,22 +231,26 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
|
|||
} /* for */
|
||||
}
|
||||
|
||||
/* end of directory has been reached */
|
||||
if (item_num != B_NR_ITEMS(bh) - 1)
|
||||
// end of directory has been reached
|
||||
goto end;
|
||||
|
||||
/* item we went through is last item of node. Using right
|
||||
delimiting key check is it directory end */
|
||||
/*
|
||||
* item we went through is last item of node. Using right
|
||||
* delimiting key check is it directory end
|
||||
*/
|
||||
rkey = get_rkey(&path_to_entry, inode->i_sb);
|
||||
if (!comp_le_keys(rkey, &MIN_KEY)) {
|
||||
/* set pos_key to key, that is the smallest and greater
|
||||
that key of the last entry in the item */
|
||||
/*
|
||||
* set pos_key to key, that is the smallest and greater
|
||||
* that key of the last entry in the item
|
||||
*/
|
||||
set_cpu_key_k_offset(&pos_key, next_pos);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* end of directory has been reached */
|
||||
if (COMP_SHORT_KEYS(rkey, &pos_key)) {
|
||||
// end of directory has been reached
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -248,71 +274,73 @@ static int reiserfs_readdir(struct file *file, struct dir_context *ctx)
|
|||
return reiserfs_readdir_inode(file_inode(file), ctx);
|
||||
}
|
||||
|
||||
/* compose directory item containing "." and ".." entries (entries are
|
||||
not aligned to 4 byte boundary) */
|
||||
/* the last four params are LE */
|
||||
/*
|
||||
* compose directory item containing "." and ".." entries (entries are
|
||||
* not aligned to 4 byte boundary)
|
||||
*/
|
||||
void make_empty_dir_item_v1(char *body, __le32 dirid, __le32 objid,
|
||||
__le32 par_dirid, __le32 par_objid)
|
||||
{
|
||||
struct reiserfs_de_head *deh;
|
||||
struct reiserfs_de_head *dot, *dotdot;
|
||||
|
||||
memset(body, 0, EMPTY_DIR_SIZE_V1);
|
||||
deh = (struct reiserfs_de_head *)body;
|
||||
dot = (struct reiserfs_de_head *)body;
|
||||
dotdot = dot + 1;
|
||||
|
||||
/* direntry header of "." */
|
||||
put_deh_offset(&(deh[0]), DOT_OFFSET);
|
||||
put_deh_offset(dot, DOT_OFFSET);
|
||||
/* these two are from make_le_item_head, and are are LE */
|
||||
deh[0].deh_dir_id = dirid;
|
||||
deh[0].deh_objectid = objid;
|
||||
deh[0].deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(&(deh[0]), EMPTY_DIR_SIZE_V1 - strlen("."));
|
||||
mark_de_visible(&(deh[0]));
|
||||
dot->deh_dir_id = dirid;
|
||||
dot->deh_objectid = objid;
|
||||
dot->deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(dot, EMPTY_DIR_SIZE_V1 - strlen("."));
|
||||
mark_de_visible(dot);
|
||||
|
||||
/* direntry header of ".." */
|
||||
put_deh_offset(&(deh[1]), DOT_DOT_OFFSET);
|
||||
put_deh_offset(dotdot, DOT_DOT_OFFSET);
|
||||
/* key of ".." for the root directory */
|
||||
/* these two are from the inode, and are are LE */
|
||||
deh[1].deh_dir_id = par_dirid;
|
||||
deh[1].deh_objectid = par_objid;
|
||||
deh[1].deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(&(deh[1]), deh_location(&(deh[0])) - strlen(".."));
|
||||
mark_de_visible(&(deh[1]));
|
||||
dotdot->deh_dir_id = par_dirid;
|
||||
dotdot->deh_objectid = par_objid;
|
||||
dotdot->deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(dotdot, deh_location(dot) - strlen(".."));
|
||||
mark_de_visible(dotdot);
|
||||
|
||||
/* copy ".." and "." */
|
||||
memcpy(body + deh_location(&(deh[0])), ".", 1);
|
||||
memcpy(body + deh_location(&(deh[1])), "..", 2);
|
||||
memcpy(body + deh_location(dot), ".", 1);
|
||||
memcpy(body + deh_location(dotdot), "..", 2);
|
||||
}
|
||||
|
||||
/* compose directory item containing "." and ".." entries */
|
||||
void make_empty_dir_item(char *body, __le32 dirid, __le32 objid,
|
||||
__le32 par_dirid, __le32 par_objid)
|
||||
{
|
||||
struct reiserfs_de_head *deh;
|
||||
struct reiserfs_de_head *dot, *dotdot;
|
||||
|
||||
memset(body, 0, EMPTY_DIR_SIZE);
|
||||
deh = (struct reiserfs_de_head *)body;
|
||||
dot = (struct reiserfs_de_head *)body;
|
||||
dotdot = dot + 1;
|
||||
|
||||
/* direntry header of "." */
|
||||
put_deh_offset(&(deh[0]), DOT_OFFSET);
|
||||
put_deh_offset(dot, DOT_OFFSET);
|
||||
/* these two are from make_le_item_head, and are are LE */
|
||||
deh[0].deh_dir_id = dirid;
|
||||
deh[0].deh_objectid = objid;
|
||||
deh[0].deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(&(deh[0]), EMPTY_DIR_SIZE - ROUND_UP(strlen(".")));
|
||||
mark_de_visible(&(deh[0]));
|
||||
dot->deh_dir_id = dirid;
|
||||
dot->deh_objectid = objid;
|
||||
dot->deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(dot, EMPTY_DIR_SIZE - ROUND_UP(strlen(".")));
|
||||
mark_de_visible(dot);
|
||||
|
||||
/* direntry header of ".." */
|
||||
put_deh_offset(&(deh[1]), DOT_DOT_OFFSET);
|
||||
put_deh_offset(dotdot, DOT_DOT_OFFSET);
|
||||
/* key of ".." for the root directory */
|
||||
/* these two are from the inode, and are are LE */
|
||||
deh[1].deh_dir_id = par_dirid;
|
||||
deh[1].deh_objectid = par_objid;
|
||||
deh[1].deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(&(deh[1]),
|
||||
deh_location(&(deh[0])) - ROUND_UP(strlen("..")));
|
||||
mark_de_visible(&(deh[1]));
|
||||
dotdot->deh_dir_id = par_dirid;
|
||||
dotdot->deh_objectid = par_objid;
|
||||
dotdot->deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(dotdot, deh_location(dot) - ROUND_UP(strlen("..")));
|
||||
mark_de_visible(dotdot);
|
||||
|
||||
/* copy ".." and "." */
|
||||
memcpy(body + deh_location(&(deh[0])), ".", 1);
|
||||
memcpy(body + deh_location(&(deh[1])), "..", 2);
|
||||
memcpy(body + deh_location(dot), ".", 1);
|
||||
memcpy(body + deh_location(dotdot), "..", 2);
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -15,20 +15,20 @@
|
|||
#include <linux/quotaops.h>
|
||||
|
||||
/*
|
||||
** We pack the tails of files on file close, not at the time they are written.
|
||||
** This implies an unnecessary copy of the tail and an unnecessary indirect item
|
||||
** insertion/balancing, for files that are written in one write.
|
||||
** It avoids unnecessary tail packings (balances) for files that are written in
|
||||
** multiple writes and are small enough to have tails.
|
||||
**
|
||||
** file_release is called by the VFS layer when the file is closed. If
|
||||
** this is the last open file descriptor, and the file
|
||||
** small enough to have a tail, and the tail is currently in an
|
||||
** unformatted node, the tail is converted back into a direct item.
|
||||
**
|
||||
** We use reiserfs_truncate_file to pack the tail, since it already has
|
||||
** all the conditions coded.
|
||||
*/
|
||||
* We pack the tails of files on file close, not at the time they are written.
|
||||
* This implies an unnecessary copy of the tail and an unnecessary indirect item
|
||||
* insertion/balancing, for files that are written in one write.
|
||||
* It avoids unnecessary tail packings (balances) for files that are written in
|
||||
* multiple writes and are small enough to have tails.
|
||||
*
|
||||
* file_release is called by the VFS layer when the file is closed. If
|
||||
* this is the last open file descriptor, and the file
|
||||
* small enough to have a tail, and the tail is currently in an
|
||||
* unformatted node, the tail is converted back into a direct item.
|
||||
*
|
||||
* We use reiserfs_truncate_file to pack the tail, since it already has
|
||||
* all the conditions coded.
|
||||
*/
|
||||
static int reiserfs_file_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
|
||||
|
@ -41,10 +41,10 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
|
|||
if (atomic_add_unless(&REISERFS_I(inode)->openers, -1, 1))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&(REISERFS_I(inode)->tailpack));
|
||||
mutex_lock(&REISERFS_I(inode)->tailpack);
|
||||
|
||||
if (!atomic_dec_and_test(&REISERFS_I(inode)->openers)) {
|
||||
mutex_unlock(&(REISERFS_I(inode)->tailpack));
|
||||
mutex_unlock(&REISERFS_I(inode)->tailpack);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -52,31 +52,35 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
|
|||
if ((!(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) ||
|
||||
!tail_has_to_be_packed(inode)) &&
|
||||
REISERFS_I(inode)->i_prealloc_count <= 0) {
|
||||
mutex_unlock(&(REISERFS_I(inode)->tailpack));
|
||||
mutex_unlock(&REISERFS_I(inode)->tailpack);
|
||||
return 0;
|
||||
}
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
/* freeing preallocation only involves relogging blocks that
|
||||
/*
|
||||
* freeing preallocation only involves relogging blocks that
|
||||
* are already in the current transaction. preallocation gets
|
||||
* freed at the end of each transaction, so it is impossible for
|
||||
* us to log any additional blocks (including quota blocks)
|
||||
*/
|
||||
err = journal_begin(&th, inode->i_sb, 1);
|
||||
if (err) {
|
||||
/* uh oh, we can't allow the inode to go away while there
|
||||
/*
|
||||
* uh oh, we can't allow the inode to go away while there
|
||||
* is still preallocation blocks pending. Try to join the
|
||||
* aborted transaction
|
||||
*/
|
||||
jbegin_failure = err;
|
||||
err = journal_join_abort(&th, inode->i_sb, 1);
|
||||
err = journal_join_abort(&th, inode->i_sb);
|
||||
|
||||
if (err) {
|
||||
/* hmpf, our choices here aren't good. We can pin the inode
|
||||
* which will disallow unmount from every happening, we can
|
||||
* do nothing, which will corrupt random memory on unmount,
|
||||
* or we can forcibly remove the file from the preallocation
|
||||
* list, which will leak blocks on disk. Lets pin the inode
|
||||
/*
|
||||
* hmpf, our choices here aren't good. We can pin
|
||||
* the inode which will disallow unmount from ever
|
||||
* happening, we can do nothing, which will corrupt
|
||||
* random memory on unmount, or we can forcibly
|
||||
* remove the file from the preallocation list, which
|
||||
* will leak blocks on disk. Lets pin the inode
|
||||
* and let the admin know what is going on.
|
||||
*/
|
||||
igrab(inode);
|
||||
|
@ -92,7 +96,7 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
|
|||
#ifdef REISERFS_PREALLOCATE
|
||||
reiserfs_discard_prealloc(&th, inode);
|
||||
#endif
|
||||
err = journal_end(&th, inode->i_sb, 1);
|
||||
err = journal_end(&th);
|
||||
|
||||
/* copy back the error code from journal_begin */
|
||||
if (!err)
|
||||
|
@ -102,35 +106,38 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
|
|||
(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) &&
|
||||
tail_has_to_be_packed(inode)) {
|
||||
|
||||
/* if regular file is released by last holder and it has been
|
||||
appended (we append by unformatted node only) or its direct
|
||||
item(s) had to be converted, then it may have to be
|
||||
indirect2direct converted */
|
||||
/*
|
||||
* if regular file is released by last holder and it has been
|
||||
* appended (we append by unformatted node only) or its direct
|
||||
* item(s) had to be converted, then it may have to be
|
||||
* indirect2direct converted
|
||||
*/
|
||||
err = reiserfs_truncate_file(inode, 0);
|
||||
}
|
||||
out:
|
||||
out:
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
mutex_unlock(&(REISERFS_I(inode)->tailpack));
|
||||
mutex_unlock(&REISERFS_I(inode)->tailpack);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int reiserfs_file_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int err = dquot_file_open(inode, file);
|
||||
if (!atomic_inc_not_zero(&REISERFS_I(inode)->openers)) {
|
||||
|
||||
/* somebody might be tailpacking on final close; wait for it */
|
||||
mutex_lock(&(REISERFS_I(inode)->tailpack));
|
||||
if (!atomic_inc_not_zero(&REISERFS_I(inode)->openers)) {
|
||||
mutex_lock(&REISERFS_I(inode)->tailpack);
|
||||
atomic_inc(&REISERFS_I(inode)->openers);
|
||||
mutex_unlock(&(REISERFS_I(inode)->tailpack));
|
||||
mutex_unlock(&REISERFS_I(inode)->tailpack);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void reiserfs_vfs_truncate_file(struct inode *inode)
|
||||
{
|
||||
mutex_lock(&(REISERFS_I(inode)->tailpack));
|
||||
mutex_lock(&REISERFS_I(inode)->tailpack);
|
||||
reiserfs_truncate_file(inode, 1);
|
||||
mutex_unlock(&(REISERFS_I(inode)->tailpack));
|
||||
mutex_unlock(&REISERFS_I(inode)->tailpack);
|
||||
}
|
||||
|
||||
/* Sync a reiserfs file. */
|
||||
|
@ -205,10 +212,11 @@ int reiserfs_commit_page(struct inode *inode, struct page *page,
|
|||
set_buffer_uptodate(bh);
|
||||
if (logit) {
|
||||
reiserfs_prepare_for_journal(s, bh, 1);
|
||||
journal_mark_dirty(&th, s, bh);
|
||||
journal_mark_dirty(&th, bh);
|
||||
} else if (!buffer_dirty(bh)) {
|
||||
mark_buffer_dirty(bh);
|
||||
/* do data=ordered on any page past the end
|
||||
/*
|
||||
* do data=ordered on any page past the end
|
||||
* of file and any buffer marked BH_New.
|
||||
*/
|
||||
if (reiserfs_data_ordered(inode->i_sb) &&
|
||||
|
@ -219,8 +227,8 @@ int reiserfs_commit_page(struct inode *inode, struct page *page,
|
|||
}
|
||||
}
|
||||
if (logit) {
|
||||
ret = journal_end(&th, s, bh_per_page + 1);
|
||||
drop_write_lock:
|
||||
ret = journal_end(&th);
|
||||
drop_write_lock:
|
||||
reiserfs_write_unlock(s);
|
||||
}
|
||||
/*
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -12,12 +12,6 @@
|
|||
* Yura's function is added (04/07/2000)
|
||||
*/
|
||||
|
||||
//
|
||||
// keyed_hash
|
||||
// yura_hash
|
||||
// r5_hash
|
||||
//
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include "reiserfs.h"
|
||||
#include <asm/types.h>
|
||||
|
@ -56,7 +50,7 @@ u32 keyed_hash(const signed char *msg, int len)
|
|||
u32 pad;
|
||||
int i;
|
||||
|
||||
// assert(len >= 0 && len < 256);
|
||||
/* assert(len >= 0 && len < 256); */
|
||||
|
||||
pad = (u32) len | ((u32) len << 8);
|
||||
pad |= pad << 16;
|
||||
|
@ -127,9 +121,10 @@ u32 keyed_hash(const signed char *msg, int len)
|
|||
return h0 ^ h1;
|
||||
}
|
||||
|
||||
/* What follows in this file is copyright 2000 by Hans Reiser, and the
|
||||
* licensing of what follows is governed by reiserfs/README */
|
||||
|
||||
/*
|
||||
* What follows in this file is copyright 2000 by Hans Reiser, and the
|
||||
* licensing of what follows is governed by reiserfs/README
|
||||
*/
|
||||
u32 yura_hash(const signed char *msg, int len)
|
||||
{
|
||||
int j, pow;
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
int balance_internal(struct tree_balance *,
|
||||
int, int, struct item_head *, struct buffer_head **);
|
||||
|
||||
/* modes of internal_shift_left, internal_shift_right and internal_insert_childs */
|
||||
/*
|
||||
* modes of internal_shift_left, internal_shift_right and
|
||||
* internal_insert_childs
|
||||
*/
|
||||
#define INTERNAL_SHIFT_FROM_S_TO_L 0
|
||||
#define INTERNAL_SHIFT_FROM_R_TO_S 1
|
||||
#define INTERNAL_SHIFT_FROM_L_TO_S 2
|
||||
|
@ -32,7 +35,9 @@ static void internal_define_dest_src_infos(int shift_mode,
|
|||
memset(src_bi, 0, sizeof(struct buffer_info));
|
||||
/* define dest, src, dest parent, dest position */
|
||||
switch (shift_mode) {
|
||||
case INTERNAL_SHIFT_FROM_S_TO_L: /* used in internal_shift_left */
|
||||
|
||||
/* used in internal_shift_left */
|
||||
case INTERNAL_SHIFT_FROM_S_TO_L:
|
||||
src_bi->tb = tb;
|
||||
src_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h);
|
||||
src_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h);
|
||||
|
@ -52,12 +57,14 @@ static void internal_define_dest_src_infos(int shift_mode,
|
|||
dest_bi->tb = tb;
|
||||
dest_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h);
|
||||
dest_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h);
|
||||
dest_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); /* dest position is analog of dest->b_item_order */
|
||||
/* dest position is analog of dest->b_item_order */
|
||||
dest_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1);
|
||||
*d_key = tb->lkey[h];
|
||||
*cf = tb->CFL[h];
|
||||
break;
|
||||
|
||||
case INTERNAL_SHIFT_FROM_R_TO_S: /* used in internal_shift_left */
|
||||
/* used in internal_shift_left */
|
||||
case INTERNAL_SHIFT_FROM_R_TO_S:
|
||||
src_bi->tb = tb;
|
||||
src_bi->bi_bh = tb->R[h];
|
||||
src_bi->bi_parent = tb->FR[h];
|
||||
|
@ -111,7 +118,8 @@ static void internal_define_dest_src_infos(int shift_mode,
|
|||
}
|
||||
}
|
||||
|
||||
/* Insert count node pointers into buffer cur before position to + 1.
|
||||
/*
|
||||
* Insert count node pointers into buffer cur before position to + 1.
|
||||
* Insert count items into buffer cur before position to.
|
||||
* Items and node pointers are specified by inserted and bh respectively.
|
||||
*/
|
||||
|
@ -146,14 +154,14 @@ static void internal_insert_childs(struct buffer_info *cur_bi,
|
|||
|
||||
/* copy to_be_insert disk children */
|
||||
for (i = 0; i < count; i++) {
|
||||
put_dc_size(&(new_dc[i]),
|
||||
put_dc_size(&new_dc[i],
|
||||
MAX_CHILD_SIZE(bh[i]) - B_FREE_SPACE(bh[i]));
|
||||
put_dc_block_number(&(new_dc[i]), bh[i]->b_blocknr);
|
||||
put_dc_block_number(&new_dc[i], bh[i]->b_blocknr);
|
||||
}
|
||||
memcpy(dc, new_dc, DC_SIZE * count);
|
||||
|
||||
/* prepare space for count items */
|
||||
ih = B_N_PDELIM_KEY(cur, ((to == -1) ? 0 : to));
|
||||
ih = internal_key(cur, ((to == -1) ? 0 : to));
|
||||
|
||||
memmove(ih + count, ih,
|
||||
(nr - to) * KEY_SIZE + (nr + 1 + count) * DC_SIZE);
|
||||
|
@ -190,8 +198,10 @@ static void internal_insert_childs(struct buffer_info *cur_bi,
|
|||
|
||||
}
|
||||
|
||||
/* Delete del_num items and node pointers from buffer cur starting from *
|
||||
* the first_i'th item and first_p'th pointers respectively. */
|
||||
/*
|
||||
* Delete del_num items and node pointers from buffer cur starting from
|
||||
* the first_i'th item and first_p'th pointers respectively.
|
||||
*/
|
||||
static void internal_delete_pointers_items(struct buffer_info *cur_bi,
|
||||
int first_p,
|
||||
int first_i, int del_num)
|
||||
|
@ -233,7 +243,7 @@ static void internal_delete_pointers_items(struct buffer_info *cur_bi,
|
|||
dc = B_N_CHILD(cur, first_p);
|
||||
|
||||
memmove(dc, dc + del_num, (nr + 1 - first_p - del_num) * DC_SIZE);
|
||||
key = B_N_PDELIM_KEY(cur, first_i);
|
||||
key = internal_key(cur, first_i);
|
||||
memmove(key, key + del_num,
|
||||
(nr - first_i - del_num) * KEY_SIZE + (nr + 1 -
|
||||
del_num) * DC_SIZE);
|
||||
|
@ -270,22 +280,30 @@ static void internal_delete_childs(struct buffer_info *cur_bi, int from, int n)
|
|||
|
||||
i_from = (from == 0) ? from : from - 1;
|
||||
|
||||
/* delete n pointers starting from `from' position in CUR;
|
||||
delete n keys starting from 'i_from' position in CUR;
|
||||
/*
|
||||
* delete n pointers starting from `from' position in CUR;
|
||||
* delete n keys starting from 'i_from' position in CUR;
|
||||
*/
|
||||
internal_delete_pointers_items(cur_bi, from, i_from, n);
|
||||
}
|
||||
|
||||
/* copy cpy_num node pointers and cpy_num - 1 items from buffer src to buffer dest
|
||||
* last_first == FIRST_TO_LAST means, that we copy first items from src to tail of dest
|
||||
* last_first == LAST_TO_FIRST means, that we copy last items from src to head of dest
|
||||
/*
|
||||
* copy cpy_num node pointers and cpy_num - 1 items from buffer src to buffer
|
||||
* dest
|
||||
* last_first == FIRST_TO_LAST means that we copy first items
|
||||
* from src to tail of dest
|
||||
* last_first == LAST_TO_FIRST means that we copy last items
|
||||
* from src to head of dest
|
||||
*/
|
||||
static void internal_copy_pointers_items(struct buffer_info *dest_bi,
|
||||
struct buffer_head *src,
|
||||
int last_first, int cpy_num)
|
||||
{
|
||||
/* ATTENTION! Number of node pointers in DEST is equal to number of items in DEST *
|
||||
* as delimiting key have already inserted to buffer dest.*/
|
||||
/*
|
||||
* ATTENTION! Number of node pointers in DEST is equal to number
|
||||
* of items in DEST as delimiting key have already inserted to
|
||||
* buffer dest.
|
||||
*/
|
||||
struct buffer_head *dest = dest_bi->bi_bh;
|
||||
int nr_dest, nr_src;
|
||||
int dest_order, src_order;
|
||||
|
@ -330,13 +348,13 @@ static void internal_copy_pointers_items(struct buffer_info *dest_bi,
|
|||
memcpy(dc, B_N_CHILD(src, src_order), DC_SIZE * cpy_num);
|
||||
|
||||
/* prepare space for cpy_num - 1 item headers */
|
||||
key = B_N_PDELIM_KEY(dest, dest_order);
|
||||
key = internal_key(dest, dest_order);
|
||||
memmove(key + cpy_num - 1, key,
|
||||
KEY_SIZE * (nr_dest - dest_order) + DC_SIZE * (nr_dest +
|
||||
cpy_num));
|
||||
|
||||
/* insert headers */
|
||||
memcpy(key, B_N_PDELIM_KEY(src, src_order), KEY_SIZE * (cpy_num - 1));
|
||||
memcpy(key, internal_key(src, src_order), KEY_SIZE * (cpy_num - 1));
|
||||
|
||||
/* sizes, item number */
|
||||
set_blkh_nr_item(blkh, blkh_nr_item(blkh) + (cpy_num - 1));
|
||||
|
@ -366,7 +384,9 @@ static void internal_copy_pointers_items(struct buffer_info *dest_bi,
|
|||
|
||||
}
|
||||
|
||||
/* Copy cpy_num node pointers and cpy_num - 1 items from buffer src to buffer dest.
|
||||
/*
|
||||
* Copy cpy_num node pointers and cpy_num - 1 items from buffer src to
|
||||
* buffer dest.
|
||||
* Delete cpy_num - del_par items and node pointers from buffer src.
|
||||
* last_first == FIRST_TO_LAST means, that we copy/delete first items from src.
|
||||
* last_first == LAST_TO_FIRST means, that we copy/delete last items from src.
|
||||
|
@ -385,8 +405,10 @@ static void internal_move_pointers_items(struct buffer_info *dest_bi,
|
|||
if (last_first == FIRST_TO_LAST) { /* shift_left occurs */
|
||||
first_pointer = 0;
|
||||
first_item = 0;
|
||||
/* delete cpy_num - del_par pointers and keys starting for pointers with first_pointer,
|
||||
for key - with first_item */
|
||||
/*
|
||||
* delete cpy_num - del_par pointers and keys starting for
|
||||
* pointers with first_pointer, for key - with first_item
|
||||
*/
|
||||
internal_delete_pointers_items(src_bi, first_pointer,
|
||||
first_item, cpy_num - del_par);
|
||||
} else { /* shift_right occurs */
|
||||
|
@ -404,7 +426,9 @@ static void internal_move_pointers_items(struct buffer_info *dest_bi,
|
|||
}
|
||||
|
||||
/* Insert n_src'th key of buffer src before n_dest'th key of buffer dest. */
|
||||
static void internal_insert_key(struct buffer_info *dest_bi, int dest_position_before, /* insert key before key with n_dest number */
|
||||
static void internal_insert_key(struct buffer_info *dest_bi,
|
||||
/* insert key before key with n_dest number */
|
||||
int dest_position_before,
|
||||
struct buffer_head *src, int src_position)
|
||||
{
|
||||
struct buffer_head *dest = dest_bi->bi_bh;
|
||||
|
@ -429,12 +453,12 @@ static void internal_insert_key(struct buffer_info *dest_bi, int dest_position_b
|
|||
nr = blkh_nr_item(blkh);
|
||||
|
||||
/* prepare space for inserting key */
|
||||
key = B_N_PDELIM_KEY(dest, dest_position_before);
|
||||
key = internal_key(dest, dest_position_before);
|
||||
memmove(key + 1, key,
|
||||
(nr - dest_position_before) * KEY_SIZE + (nr + 1) * DC_SIZE);
|
||||
|
||||
/* insert key */
|
||||
memcpy(key, B_N_PDELIM_KEY(src, src_position), KEY_SIZE);
|
||||
memcpy(key, internal_key(src, src_position), KEY_SIZE);
|
||||
|
||||
/* Change dirt, free space, item number fields. */
|
||||
|
||||
|
@ -453,13 +477,19 @@ static void internal_insert_key(struct buffer_info *dest_bi, int dest_position_b
|
|||
}
|
||||
}
|
||||
|
||||
/* Insert d_key'th (delimiting) key from buffer cfl to tail of dest.
|
||||
* Copy pointer_amount node pointers and pointer_amount - 1 items from buffer src to buffer dest.
|
||||
/*
|
||||
* Insert d_key'th (delimiting) key from buffer cfl to tail of dest.
|
||||
* Copy pointer_amount node pointers and pointer_amount - 1 items from
|
||||
* buffer src to buffer dest.
|
||||
* Replace d_key'th key in buffer cfl.
|
||||
* Delete pointer_amount items and node pointers from buffer src.
|
||||
*/
|
||||
/* this can be invoked both to shift from S to L and from R to S */
|
||||
static void internal_shift_left(int mode, /* INTERNAL_FROM_S_TO_L | INTERNAL_FROM_R_TO_S */
|
||||
static void internal_shift_left(
|
||||
/*
|
||||
* INTERNAL_FROM_S_TO_L | INTERNAL_FROM_R_TO_S
|
||||
*/
|
||||
int mode,
|
||||
struct tree_balance *tb,
|
||||
int h, int pointer_amount)
|
||||
{
|
||||
|
@ -473,7 +503,10 @@ static void internal_shift_left(int mode, /* INTERNAL_FROM_S_TO_L | INTERNAL_FRO
|
|||
/*printk("pointer_amount = %d\n",pointer_amount); */
|
||||
|
||||
if (pointer_amount) {
|
||||
/* insert delimiting key from common father of dest and src to node dest into position B_NR_ITEM(dest) */
|
||||
/*
|
||||
* insert delimiting key from common father of dest and
|
||||
* src to node dest into position B_NR_ITEM(dest)
|
||||
*/
|
||||
internal_insert_key(&dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf,
|
||||
d_key_position);
|
||||
|
||||
|
@ -492,7 +525,8 @@ static void internal_shift_left(int mode, /* INTERNAL_FROM_S_TO_L | INTERNAL_FRO
|
|||
|
||||
}
|
||||
|
||||
/* Insert delimiting key to L[h].
|
||||
/*
|
||||
* Insert delimiting key to L[h].
|
||||
* Copy n node pointers and n - 1 items from buffer S[h] to L[h].
|
||||
* Delete n - 1 items and node pointers from buffer S[h].
|
||||
*/
|
||||
|
@ -507,23 +541,27 @@ static void internal_shift1_left(struct tree_balance *tb,
|
|||
internal_define_dest_src_infos(INTERNAL_SHIFT_FROM_S_TO_L, tb, h,
|
||||
&dest_bi, &src_bi, &d_key_position, &cf);
|
||||
|
||||
if (pointer_amount > 0) /* insert lkey[h]-th key from CFL[h] to left neighbor L[h] */
|
||||
/* insert lkey[h]-th key from CFL[h] to left neighbor L[h] */
|
||||
if (pointer_amount > 0)
|
||||
internal_insert_key(&dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf,
|
||||
d_key_position);
|
||||
/* internal_insert_key (tb->L[h], B_NR_ITEM(tb->L[h]), tb->CFL[h], tb->lkey[h]); */
|
||||
|
||||
/* last parameter is del_parameter */
|
||||
internal_move_pointers_items(&dest_bi, &src_bi, FIRST_TO_LAST,
|
||||
pointer_amount, 1);
|
||||
/* internal_move_pointers_items (tb->L[h], tb->S[h], FIRST_TO_LAST, pointer_amount, 1); */
|
||||
}
|
||||
|
||||
/* Insert d_key'th (delimiting) key from buffer cfr to head of dest.
|
||||
/*
|
||||
* Insert d_key'th (delimiting) key from buffer cfr to head of dest.
|
||||
* Copy n node pointers and n - 1 items from buffer src to buffer dest.
|
||||
* Replace d_key'th key in buffer cfr.
|
||||
* Delete n items and node pointers from buffer src.
|
||||
*/
|
||||
static void internal_shift_right(int mode, /* INTERNAL_FROM_S_TO_R | INTERNAL_FROM_L_TO_S */
|
||||
static void internal_shift_right(
|
||||
/*
|
||||
* INTERNAL_FROM_S_TO_R | INTERNAL_FROM_L_TO_S
|
||||
*/
|
||||
int mode,
|
||||
struct tree_balance *tb,
|
||||
int h, int pointer_amount)
|
||||
{
|
||||
|
@ -538,7 +576,10 @@ static void internal_shift_right(int mode, /* INTERNAL_FROM_S_TO_R | INTERNAL_FR
|
|||
nr = B_NR_ITEMS(src_bi.bi_bh);
|
||||
|
||||
if (pointer_amount > 0) {
|
||||
/* insert delimiting key from common father of dest and src to dest node into position 0 */
|
||||
/*
|
||||
* insert delimiting key from common father of dest
|
||||
* and src to dest node into position 0
|
||||
*/
|
||||
internal_insert_key(&dest_bi, 0, cf, d_key_position);
|
||||
if (nr == pointer_amount - 1) {
|
||||
RFALSE(src_bi.bi_bh != PATH_H_PBUFFER(tb->tb_path, h) /*tb->S[h] */ ||
|
||||
|
@ -559,7 +600,8 @@ static void internal_shift_right(int mode, /* INTERNAL_FROM_S_TO_R | INTERNAL_FR
|
|||
pointer_amount, 0);
|
||||
}
|
||||
|
||||
/* Insert delimiting key to R[h].
|
||||
/*
|
||||
* Insert delimiting key to R[h].
|
||||
* Copy n node pointers and n - 1 items from buffer S[h] to R[h].
|
||||
* Delete n - 1 items and node pointers from buffer S[h].
|
||||
*/
|
||||
|
@ -574,18 +616,19 @@ static void internal_shift1_right(struct tree_balance *tb,
|
|||
internal_define_dest_src_infos(INTERNAL_SHIFT_FROM_S_TO_R, tb, h,
|
||||
&dest_bi, &src_bi, &d_key_position, &cf);
|
||||
|
||||
if (pointer_amount > 0) /* insert rkey from CFR[h] to right neighbor R[h] */
|
||||
/* insert rkey from CFR[h] to right neighbor R[h] */
|
||||
if (pointer_amount > 0)
|
||||
internal_insert_key(&dest_bi, 0, cf, d_key_position);
|
||||
/* internal_insert_key (tb->R[h], 0, tb->CFR[h], tb->rkey[h]); */
|
||||
|
||||
/* last parameter is del_parameter */
|
||||
internal_move_pointers_items(&dest_bi, &src_bi, LAST_TO_FIRST,
|
||||
pointer_amount, 1);
|
||||
/* internal_move_pointers_items (tb->R[h], tb->S[h], LAST_TO_FIRST, pointer_amount, 1); */
|
||||
}
|
||||
|
||||
/* Delete insert_num node pointers together with their left items
|
||||
* and balance current node.*/
|
||||
/*
|
||||
* Delete insert_num node pointers together with their left items
|
||||
* and balance current node.
|
||||
*/
|
||||
static void balance_internal_when_delete(struct tree_balance *tb,
|
||||
int h, int child_pos)
|
||||
{
|
||||
|
@ -626,9 +669,11 @@ static void balance_internal_when_delete(struct tree_balance *tb,
|
|||
new_root = tb->R[h - 1];
|
||||
else
|
||||
new_root = tb->L[h - 1];
|
||||
/* switch super block's tree root block number to the new value */
|
||||
/*
|
||||
* switch super block's tree root block
|
||||
* number to the new value */
|
||||
PUT_SB_ROOT_BLOCK(tb->tb_sb, new_root->b_blocknr);
|
||||
//REISERFS_SB(tb->tb_sb)->s_rs->s_tree_height --;
|
||||
/*REISERFS_SB(tb->tb_sb)->s_rs->s_tree_height --; */
|
||||
PUT_SB_TREE_HEIGHT(tb->tb_sb,
|
||||
SB_TREE_HEIGHT(tb->tb_sb) - 1);
|
||||
|
||||
|
@ -636,8 +681,8 @@ static void balance_internal_when_delete(struct tree_balance *tb,
|
|||
REISERFS_SB(tb->tb_sb)->s_sbh,
|
||||
1);
|
||||
/*&&&&&&&&&&&&&&&&&&&&&& */
|
||||
if (h > 1)
|
||||
/* use check_internal if new root is an internal node */
|
||||
if (h > 1)
|
||||
check_internal(new_root);
|
||||
/*&&&&&&&&&&&&&&&&&&&&&& */
|
||||
|
||||
|
@ -648,7 +693,8 @@ static void balance_internal_when_delete(struct tree_balance *tb,
|
|||
return;
|
||||
}
|
||||
|
||||
if (tb->L[h] && tb->lnum[h] == -B_NR_ITEMS(tb->L[h]) - 1) { /* join S[h] with L[h] */
|
||||
/* join S[h] with L[h] */
|
||||
if (tb->L[h] && tb->lnum[h] == -B_NR_ITEMS(tb->L[h]) - 1) {
|
||||
|
||||
RFALSE(tb->rnum[h] != 0,
|
||||
"invalid tb->rnum[%d]==%d when joining S[h] with L[h]",
|
||||
|
@ -660,7 +706,8 @@ static void balance_internal_when_delete(struct tree_balance *tb,
|
|||
return;
|
||||
}
|
||||
|
||||
if (tb->R[h] && tb->rnum[h] == -B_NR_ITEMS(tb->R[h]) - 1) { /* join S[h] with R[h] */
|
||||
/* join S[h] with R[h] */
|
||||
if (tb->R[h] && tb->rnum[h] == -B_NR_ITEMS(tb->R[h]) - 1) {
|
||||
RFALSE(tb->lnum[h] != 0,
|
||||
"invalid tb->lnum[%d]==%d when joining S[h] with R[h]",
|
||||
h, tb->lnum[h]);
|
||||
|
@ -671,17 +718,18 @@ static void balance_internal_when_delete(struct tree_balance *tb,
|
|||
return;
|
||||
}
|
||||
|
||||
if (tb->lnum[h] < 0) { /* borrow from left neighbor L[h] */
|
||||
/* borrow from left neighbor L[h] */
|
||||
if (tb->lnum[h] < 0) {
|
||||
RFALSE(tb->rnum[h] != 0,
|
||||
"wrong tb->rnum[%d]==%d when borrow from L[h]", h,
|
||||
tb->rnum[h]);
|
||||
/*internal_shift_right (tb, h, tb->L[h], tb->CFL[h], tb->lkey[h], tb->S[h], -tb->lnum[h]); */
|
||||
internal_shift_right(INTERNAL_SHIFT_FROM_L_TO_S, tb, h,
|
||||
-tb->lnum[h]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tb->rnum[h] < 0) { /* borrow from right neighbor R[h] */
|
||||
/* borrow from right neighbor R[h] */
|
||||
if (tb->rnum[h] < 0) {
|
||||
RFALSE(tb->lnum[h] != 0,
|
||||
"invalid tb->lnum[%d]==%d when borrow from R[h]",
|
||||
h, tb->lnum[h]);
|
||||
|
@ -689,7 +737,8 @@ static void balance_internal_when_delete(struct tree_balance *tb,
|
|||
return;
|
||||
}
|
||||
|
||||
if (tb->lnum[h] > 0) { /* split S[h] into two parts and put them into neighbors */
|
||||
/* split S[h] into two parts and put them into neighbors */
|
||||
if (tb->lnum[h] > 0) {
|
||||
RFALSE(tb->rnum[h] == 0 || tb->lnum[h] + tb->rnum[h] != n + 1,
|
||||
"invalid tb->lnum[%d]==%d or tb->rnum[%d]==%d when S[h](item number == %d) is split between them",
|
||||
h, tb->lnum[h], h, tb->rnum[h], n);
|
||||
|
@ -717,7 +766,7 @@ static void replace_lkey(struct tree_balance *tb, int h, struct item_head *key)
|
|||
if (B_NR_ITEMS(PATH_H_PBUFFER(tb->tb_path, h)) == 0)
|
||||
return;
|
||||
|
||||
memcpy(B_N_PDELIM_KEY(tb->CFL[h], tb->lkey[h]), key, KEY_SIZE);
|
||||
memcpy(internal_key(tb->CFL[h], tb->lkey[h]), key, KEY_SIZE);
|
||||
|
||||
do_balance_mark_internal_dirty(tb, tb->CFL[h], 0);
|
||||
}
|
||||
|
@ -732,34 +781,41 @@ static void replace_rkey(struct tree_balance *tb, int h, struct item_head *key)
|
|||
"R[h] can not be empty if it exists (item number=%d)",
|
||||
B_NR_ITEMS(tb->R[h]));
|
||||
|
||||
memcpy(B_N_PDELIM_KEY(tb->CFR[h], tb->rkey[h]), key, KEY_SIZE);
|
||||
memcpy(internal_key(tb->CFR[h], tb->rkey[h]), key, KEY_SIZE);
|
||||
|
||||
do_balance_mark_internal_dirty(tb, tb->CFR[h], 0);
|
||||
}
|
||||
|
||||
int balance_internal(struct tree_balance *tb, /* tree_balance structure */
|
||||
int h, /* level of the tree */
|
||||
int child_pos, struct item_head *insert_key, /* key for insertion on higher level */
|
||||
struct buffer_head **insert_ptr /* node for insertion on higher level */
|
||||
)
|
||||
/* if inserting/pasting
|
||||
{
|
||||
child_pos is the position of the node-pointer in S[h] that *
|
||||
pointed to S[h-1] before balancing of the h-1 level; *
|
||||
this means that new pointers and items must be inserted AFTER *
|
||||
child_pos
|
||||
}
|
||||
else
|
||||
{
|
||||
it is the position of the leftmost pointer that must be deleted (together with
|
||||
its corresponding key to the left of the pointer)
|
||||
as a result of the previous level's balancing.
|
||||
}
|
||||
|
||||
/*
|
||||
* if inserting/pasting {
|
||||
* child_pos is the position of the node-pointer in S[h] that
|
||||
* pointed to S[h-1] before balancing of the h-1 level;
|
||||
* this means that new pointers and items must be inserted AFTER
|
||||
* child_pos
|
||||
* } else {
|
||||
* it is the position of the leftmost pointer that must be deleted
|
||||
* (together with its corresponding key to the left of the pointer)
|
||||
* as a result of the previous level's balancing.
|
||||
* }
|
||||
*/
|
||||
|
||||
int balance_internal(struct tree_balance *tb,
|
||||
int h, /* level of the tree */
|
||||
int child_pos,
|
||||
/* key for insertion on higher level */
|
||||
struct item_head *insert_key,
|
||||
/* node for insertion on higher level */
|
||||
struct buffer_head **insert_ptr)
|
||||
{
|
||||
struct buffer_head *tbSh = PATH_H_PBUFFER(tb->tb_path, h);
|
||||
struct buffer_info bi;
|
||||
int order; /* we return this: it is 0 if there is no S[h], else it is tb->S[h]->b_item_order */
|
||||
|
||||
/*
|
||||
* we return this: it is 0 if there is no S[h],
|
||||
* else it is tb->S[h]->b_item_order
|
||||
*/
|
||||
int order;
|
||||
int insert_num, n, k;
|
||||
struct buffer_head *S_new;
|
||||
struct item_head new_insert_key;
|
||||
|
@ -774,8 +830,10 @@ int balance_internal(struct tree_balance *tb, /* tree_balance structure
|
|||
(tbSh) ? PATH_H_POSITION(tb->tb_path,
|
||||
h + 1) /*tb->S[h]->b_item_order */ : 0;
|
||||
|
||||
/* Using insert_size[h] calculate the number insert_num of items
|
||||
that must be inserted to or deleted from S[h]. */
|
||||
/*
|
||||
* Using insert_size[h] calculate the number insert_num of items
|
||||
* that must be inserted to or deleted from S[h].
|
||||
*/
|
||||
insert_num = tb->insert_size[h] / ((int)(KEY_SIZE + DC_SIZE));
|
||||
|
||||
/* Check whether insert_num is proper * */
|
||||
|
@ -794,23 +852,21 @@ int balance_internal(struct tree_balance *tb, /* tree_balance structure
|
|||
|
||||
k = 0;
|
||||
if (tb->lnum[h] > 0) {
|
||||
/* shift lnum[h] items from S[h] to the left neighbor L[h].
|
||||
check how many of new items fall into L[h] or CFL[h] after
|
||||
shifting */
|
||||
/*
|
||||
* shift lnum[h] items from S[h] to the left neighbor L[h].
|
||||
* check how many of new items fall into L[h] or CFL[h] after
|
||||
* shifting
|
||||
*/
|
||||
n = B_NR_ITEMS(tb->L[h]); /* number of items in L[h] */
|
||||
if (tb->lnum[h] <= child_pos) {
|
||||
/* new items don't fall into L[h] or CFL[h] */
|
||||
internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h,
|
||||
tb->lnum[h]);
|
||||
/*internal_shift_left (tb->L[h],tb->CFL[h],tb->lkey[h],tbSh,tb->lnum[h]); */
|
||||
child_pos -= tb->lnum[h];
|
||||
} else if (tb->lnum[h] > child_pos + insert_num) {
|
||||
/* all new items fall into L[h] */
|
||||
internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h,
|
||||
tb->lnum[h] - insert_num);
|
||||
/* internal_shift_left(tb->L[h],tb->CFL[h],tb->lkey[h],tbSh,
|
||||
tb->lnum[h]-insert_num);
|
||||
*/
|
||||
/* insert insert_num keys and node-pointers into L[h] */
|
||||
bi.tb = tb;
|
||||
bi.bi_bh = tb->L[h];
|
||||
|
@ -826,7 +882,10 @@ int balance_internal(struct tree_balance *tb, /* tree_balance structure
|
|||
} else {
|
||||
struct disk_child *dc;
|
||||
|
||||
/* some items fall into L[h] or CFL[h], but some don't fall */
|
||||
/*
|
||||
* some items fall into L[h] or CFL[h],
|
||||
* but some don't fall
|
||||
*/
|
||||
internal_shift1_left(tb, h, child_pos + 1);
|
||||
/* calculate number of new items that fall into L[h] */
|
||||
k = tb->lnum[h] - child_pos - 1;
|
||||
|
@ -841,7 +900,10 @@ int balance_internal(struct tree_balance *tb, /* tree_balance structure
|
|||
|
||||
replace_lkey(tb, h, insert_key + k);
|
||||
|
||||
/* replace the first node-ptr in S[h] by node-ptr to insert_ptr[k] */
|
||||
/*
|
||||
* replace the first node-ptr in S[h] by
|
||||
* node-ptr to insert_ptr[k]
|
||||
*/
|
||||
dc = B_N_CHILD(tbSh, 0);
|
||||
put_dc_size(dc,
|
||||
MAX_CHILD_SIZE(insert_ptr[k]) -
|
||||
|
@ -860,17 +922,17 @@ int balance_internal(struct tree_balance *tb, /* tree_balance structure
|
|||
/* tb->lnum[h] > 0 */
|
||||
if (tb->rnum[h] > 0) {
|
||||
/*shift rnum[h] items from S[h] to the right neighbor R[h] */
|
||||
/* check how many of new items fall into R or CFR after shifting */
|
||||
/*
|
||||
* check how many of new items fall into R or CFR
|
||||
* after shifting
|
||||
*/
|
||||
n = B_NR_ITEMS(tbSh); /* number of items in S[h] */
|
||||
if (n - tb->rnum[h] >= child_pos)
|
||||
/* new items fall into S[h] */
|
||||
/*internal_shift_right(tb,h,tbSh,tb->CFR[h],tb->rkey[h],tb->R[h],tb->rnum[h]); */
|
||||
internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h,
|
||||
tb->rnum[h]);
|
||||
else if (n + insert_num - tb->rnum[h] < child_pos) {
|
||||
/* all new items fall into R[h] */
|
||||
/*internal_shift_right(tb,h,tbSh,tb->CFR[h],tb->rkey[h],tb->R[h],
|
||||
tb->rnum[h] - insert_num); */
|
||||
internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h,
|
||||
tb->rnum[h] - insert_num);
|
||||
|
||||
|
@ -904,7 +966,10 @@ int balance_internal(struct tree_balance *tb, /* tree_balance structure
|
|||
|
||||
replace_rkey(tb, h, insert_key + insert_num - k - 1);
|
||||
|
||||
/* replace the first node-ptr in R[h] by node-ptr insert_ptr[insert_num-k-1] */
|
||||
/*
|
||||
* replace the first node-ptr in R[h] by
|
||||
* node-ptr insert_ptr[insert_num-k-1]
|
||||
*/
|
||||
dc = B_N_CHILD(tb->R[h], 0);
|
||||
put_dc_size(dc,
|
||||
MAX_CHILD_SIZE(insert_ptr
|
||||
|
@ -997,26 +1062,30 @@ int balance_internal(struct tree_balance *tb, /* tree_balance structure
|
|||
/* new items don't fall into S_new */
|
||||
/* store the delimiting key for the next level */
|
||||
/* new_insert_key = (n - snum)'th key in S[h] */
|
||||
memcpy(&new_insert_key, B_N_PDELIM_KEY(tbSh, n - snum),
|
||||
memcpy(&new_insert_key, internal_key(tbSh, n - snum),
|
||||
KEY_SIZE);
|
||||
/* last parameter is del_par */
|
||||
internal_move_pointers_items(&dest_bi, &src_bi,
|
||||
LAST_TO_FIRST, snum, 0);
|
||||
/* internal_move_pointers_items(S_new, tbSh, LAST_TO_FIRST, snum, 0); */
|
||||
} else if (n + insert_num - snum < child_pos) {
|
||||
/* all new items fall into S_new */
|
||||
/* store the delimiting key for the next level */
|
||||
/* new_insert_key = (n + insert_item - snum)'th key in S[h] */
|
||||
/*
|
||||
* new_insert_key = (n + insert_item - snum)'th
|
||||
* key in S[h]
|
||||
*/
|
||||
memcpy(&new_insert_key,
|
||||
B_N_PDELIM_KEY(tbSh, n + insert_num - snum),
|
||||
internal_key(tbSh, n + insert_num - snum),
|
||||
KEY_SIZE);
|
||||
/* last parameter is del_par */
|
||||
internal_move_pointers_items(&dest_bi, &src_bi,
|
||||
LAST_TO_FIRST,
|
||||
snum - insert_num, 0);
|
||||
/* internal_move_pointers_items(S_new,tbSh,1,snum - insert_num,0); */
|
||||
|
||||
/* insert insert_num keys and node-pointers into S_new */
|
||||
/*
|
||||
* insert insert_num keys and node-pointers
|
||||
* into S_new
|
||||
*/
|
||||
internal_insert_childs(&dest_bi,
|
||||
/*S_new,tb->S[h-1]->b_next, */
|
||||
child_pos - n - insert_num +
|
||||
|
@ -1033,7 +1102,6 @@ int balance_internal(struct tree_balance *tb, /* tree_balance structure
|
|||
internal_move_pointers_items(&dest_bi, &src_bi,
|
||||
LAST_TO_FIRST,
|
||||
n - child_pos + 1, 1);
|
||||
/* internal_move_pointers_items(S_new,tbSh,1,n - child_pos + 1,1); */
|
||||
/* calculate number of new items that fall into S_new */
|
||||
k = snum - n + child_pos - 1;
|
||||
|
||||
|
@ -1043,7 +1111,10 @@ int balance_internal(struct tree_balance *tb, /* tree_balance structure
|
|||
/* new_insert_key = insert_key[insert_num - k - 1] */
|
||||
memcpy(&new_insert_key, insert_key + insert_num - k - 1,
|
||||
KEY_SIZE);
|
||||
/* replace first node-ptr in S_new by node-ptr to insert_ptr[insert_num-k-1] */
|
||||
/*
|
||||
* replace first node-ptr in S_new by node-ptr
|
||||
* to insert_ptr[insert_num-k-1]
|
||||
*/
|
||||
|
||||
dc = B_N_CHILD(S_new, 0);
|
||||
put_dc_size(dc,
|
||||
|
@ -1066,7 +1137,7 @@ int balance_internal(struct tree_balance *tb, /* tree_balance structure
|
|||
|| buffer_dirty(S_new), "cm-00001: bad S_new (%b)",
|
||||
S_new);
|
||||
|
||||
// S_new is released in unfix_nodes
|
||||
/* S_new is released in unfix_nodes */
|
||||
}
|
||||
|
||||
n = B_NR_ITEMS(tbSh); /*number of items in S[h] */
|
||||
|
|
1204
fs/reiserfs/inode.c
1204
fs/reiserfs/inode.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -15,7 +15,8 @@
|
|||
* reiserfs_ioctl - handler for ioctl for inode
|
||||
* supported commands:
|
||||
* 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
|
||||
* and prevent packing file (argument arg has to be non-zero)
|
||||
* and prevent packing file (argument arg has t
|
||||
* be non-zero)
|
||||
* 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
|
||||
* 3) That's all for a while ...
|
||||
*/
|
||||
|
@ -132,7 +133,10 @@ setversion_out:
|
|||
long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
/* These are just misnamed, they actually get/put from/to user an int */
|
||||
/*
|
||||
* These are just misnamed, they actually
|
||||
* get/put from/to user an int
|
||||
*/
|
||||
switch (cmd) {
|
||||
case REISERFS_IOC32_UNPACK:
|
||||
cmd = REISERFS_IOC_UNPACK;
|
||||
|
@ -160,10 +164,10 @@ long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
|
|||
int reiserfs_commit_write(struct file *f, struct page *page,
|
||||
unsigned from, unsigned to);
|
||||
/*
|
||||
** reiserfs_unpack
|
||||
** Function try to convert tail from direct item into indirect.
|
||||
** It set up nopack attribute in the REISERFS_I(inode)->nopack
|
||||
*/
|
||||
* reiserfs_unpack
|
||||
* Function try to convert tail from direct item into indirect.
|
||||
* It set up nopack attribute in the REISERFS_I(inode)->nopack
|
||||
*/
|
||||
int reiserfs_unpack(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int retval = 0;
|
||||
|
@ -194,9 +198,10 @@ int reiserfs_unpack(struct inode *inode, struct file *filp)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* we unpack by finding the page with the tail, and calling
|
||||
** __reiserfs_write_begin on that page. This will force a
|
||||
** reiserfs_get_block to unpack the tail for us.
|
||||
/*
|
||||
* we unpack by finding the page with the tail, and calling
|
||||
* __reiserfs_write_begin on that page. This will force a
|
||||
* reiserfs_get_block to unpack the tail for us.
|
||||
*/
|
||||
index = inode->i_size >> PAGE_CACHE_SHIFT;
|
||||
mapping = inode->i_mapping;
|
||||
|
@ -214,11 +219,11 @@ int reiserfs_unpack(struct inode *inode, struct file *filp)
|
|||
retval = reiserfs_commit_write(NULL, page, write_from, write_from);
|
||||
REISERFS_I(inode)->i_flags |= i_nopack_mask;
|
||||
|
||||
out_unlock:
|
||||
out_unlock:
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
|
||||
out:
|
||||
out:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
return retval;
|
||||
|
|
|
@ -5,15 +5,17 @@
|
|||
#include <linux/time.h>
|
||||
#include "reiserfs.h"
|
||||
|
||||
// this contains item handlers for old item types: sd, direct,
|
||||
// indirect, directory
|
||||
/*
|
||||
* this contains item handlers for old item types: sd, direct,
|
||||
* indirect, directory
|
||||
*/
|
||||
|
||||
/* and where are the comments? how about saying where we can find an
|
||||
explanation of each item handler method? -Hans */
|
||||
/*
|
||||
* and where are the comments? how about saying where we can find an
|
||||
* explanation of each item handler method? -Hans
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// stat data functions
|
||||
//
|
||||
/* stat data functions */
|
||||
static int sd_bytes_number(struct item_head *ih, int block_size)
|
||||
{
|
||||
return 0;
|
||||
|
@ -60,7 +62,7 @@ static void sd_print_item(struct item_head *ih, char *item)
|
|||
|
||||
static void sd_check_item(struct item_head *ih, char *item)
|
||||
{
|
||||
// FIXME: type something here!
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static int sd_create_vi(struct virtual_node *vn,
|
||||
|
@ -68,7 +70,6 @@ static int sd_create_vi(struct virtual_node *vn,
|
|||
int is_affected, int insert_size)
|
||||
{
|
||||
vi->vi_index = TYPE_STAT_DATA;
|
||||
//vi->vi_type |= VI_TYPE_STAT_DATA;// not needed?
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -117,15 +118,13 @@ static struct item_operations stat_data_ops = {
|
|||
.print_vi = sd_print_vi
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// direct item functions
|
||||
//
|
||||
/* direct item functions */
|
||||
static int direct_bytes_number(struct item_head *ih, int block_size)
|
||||
{
|
||||
return ih_item_len(ih);
|
||||
}
|
||||
|
||||
// FIXME: this should probably switch to indirect as well
|
||||
/* FIXME: this should probably switch to indirect as well */
|
||||
static void direct_decrement_key(struct cpu_key *key)
|
||||
{
|
||||
cpu_key_k_offset_dec(key);
|
||||
|
@ -144,7 +143,7 @@ static void direct_print_item(struct item_head *ih, char *item)
|
|||
{
|
||||
int j = 0;
|
||||
|
||||
// return;
|
||||
/* return; */
|
||||
printk("\"");
|
||||
while (j < ih_item_len(ih))
|
||||
printk("%c", item[j++]);
|
||||
|
@ -153,7 +152,7 @@ static void direct_print_item(struct item_head *ih, char *item)
|
|||
|
||||
static void direct_check_item(struct item_head *ih, char *item)
|
||||
{
|
||||
// FIXME: type something here!
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static int direct_create_vi(struct virtual_node *vn,
|
||||
|
@ -161,7 +160,6 @@ static int direct_create_vi(struct virtual_node *vn,
|
|||
int is_affected, int insert_size)
|
||||
{
|
||||
vi->vi_index = TYPE_DIRECT;
|
||||
//vi->vi_type |= VI_TYPE_DIRECT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -211,16 +209,13 @@ static struct item_operations direct_ops = {
|
|||
.print_vi = direct_print_vi
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// indirect item functions
|
||||
//
|
||||
|
||||
/* indirect item functions */
|
||||
static int indirect_bytes_number(struct item_head *ih, int block_size)
|
||||
{
|
||||
return ih_item_len(ih) / UNFM_P_SIZE * block_size; //- get_ih_free_space (ih);
|
||||
return ih_item_len(ih) / UNFM_P_SIZE * block_size;
|
||||
}
|
||||
|
||||
// decrease offset, if it becomes 0, change type to stat data
|
||||
/* decrease offset, if it becomes 0, change type to stat data */
|
||||
static void indirect_decrement_key(struct cpu_key *key)
|
||||
{
|
||||
cpu_key_k_offset_dec(key);
|
||||
|
@ -228,7 +223,7 @@ static void indirect_decrement_key(struct cpu_key *key)
|
|||
set_cpu_key_k_type(key, TYPE_STAT_DATA);
|
||||
}
|
||||
|
||||
// if it is not first item of the body, then it is mergeable
|
||||
/* if it is not first item of the body, then it is mergeable */
|
||||
static int indirect_is_left_mergeable(struct reiserfs_key *key,
|
||||
unsigned long bsize)
|
||||
{
|
||||
|
@ -236,7 +231,7 @@ static int indirect_is_left_mergeable(struct reiserfs_key *key,
|
|||
return (le_key_k_offset(version, key) != 1);
|
||||
}
|
||||
|
||||
// printing of indirect item
|
||||
/* printing of indirect item */
|
||||
static void start_new_sequence(__u32 * start, int *len, __u32 new)
|
||||
{
|
||||
*start = new;
|
||||
|
@ -295,7 +290,7 @@ static void indirect_print_item(struct item_head *ih, char *item)
|
|||
|
||||
static void indirect_check_item(struct item_head *ih, char *item)
|
||||
{
|
||||
// FIXME: type something here!
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static int indirect_create_vi(struct virtual_node *vn,
|
||||
|
@ -303,7 +298,6 @@ static int indirect_create_vi(struct virtual_node *vn,
|
|||
int is_affected, int insert_size)
|
||||
{
|
||||
vi->vi_index = TYPE_INDIRECT;
|
||||
//vi->vi_type |= VI_TYPE_INDIRECT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -321,16 +315,19 @@ static int indirect_check_right(struct virtual_item *vi, int free)
|
|||
return indirect_check_left(vi, free, 0, 0);
|
||||
}
|
||||
|
||||
// return size in bytes of 'units' units. If first == 0 - calculate from the head (left), otherwise - from tail (right)
|
||||
/*
|
||||
* return size in bytes of 'units' units. If first == 0 - calculate
|
||||
* from the head (left), otherwise - from tail (right)
|
||||
*/
|
||||
static int indirect_part_size(struct virtual_item *vi, int first, int units)
|
||||
{
|
||||
// unit of indirect item is byte (yet)
|
||||
/* unit of indirect item is byte (yet) */
|
||||
return units;
|
||||
}
|
||||
|
||||
static int indirect_unit_num(struct virtual_item *vi)
|
||||
{
|
||||
// unit of indirect item is byte (yet)
|
||||
/* unit of indirect item is byte (yet) */
|
||||
return vi->vi_item_len - IH_SIZE;
|
||||
}
|
||||
|
||||
|
@ -356,10 +353,7 @@ static struct item_operations indirect_ops = {
|
|||
.print_vi = indirect_print_vi
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// direntry functions
|
||||
//
|
||||
|
||||
/* direntry functions */
|
||||
static int direntry_bytes_number(struct item_head *ih, int block_size)
|
||||
{
|
||||
reiserfs_warning(NULL, "vs-16090",
|
||||
|
@ -396,7 +390,7 @@ static void direntry_print_item(struct item_head *ih, char *item)
|
|||
|
||||
deh = (struct reiserfs_de_head *)item;
|
||||
|
||||
for (i = 0; i < I_ENTRY_COUNT(ih); i++, deh++) {
|
||||
for (i = 0; i < ih_entry_count(ih); i++, deh++) {
|
||||
namelen =
|
||||
(i ? (deh_location(deh - 1)) : ih_item_len(ih)) -
|
||||
deh_location(deh);
|
||||
|
@ -428,9 +422,9 @@ static void direntry_check_item(struct item_head *ih, char *item)
|
|||
int i;
|
||||
struct reiserfs_de_head *deh;
|
||||
|
||||
// FIXME: type something here!
|
||||
/* unused */
|
||||
deh = (struct reiserfs_de_head *)item;
|
||||
for (i = 0; i < I_ENTRY_COUNT(ih); i++, deh++) {
|
||||
for (i = 0; i < ih_entry_count(ih); i++, deh++) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -439,7 +433,8 @@ static void direntry_check_item(struct item_head *ih, char *item)
|
|||
|
||||
/*
|
||||
* function returns old entry number in directory item in real node
|
||||
* using new entry number in virtual item in virtual node */
|
||||
* using new entry number in virtual item in virtual node
|
||||
*/
|
||||
static inline int old_entry_num(int is_affected, int virtual_entry_num,
|
||||
int pos_in_item, int mode)
|
||||
{
|
||||
|
@ -463,9 +458,11 @@ static inline int old_entry_num(int is_affected, int virtual_entry_num,
|
|||
return virtual_entry_num - 1;
|
||||
}
|
||||
|
||||
/* Create an array of sizes of directory entries for virtual
|
||||
item. Return space used by an item. FIXME: no control over
|
||||
consuming of space used by this item handler */
|
||||
/*
|
||||
* Create an array of sizes of directory entries for virtual
|
||||
* item. Return space used by an item. FIXME: no control over
|
||||
* consuming of space used by this item handler
|
||||
*/
|
||||
static int direntry_create_vi(struct virtual_node *vn,
|
||||
struct virtual_item *vi,
|
||||
int is_affected, int insert_size)
|
||||
|
@ -494,8 +491,8 @@ static int direntry_create_vi(struct virtual_node *vn,
|
|||
j = old_entry_num(is_affected, i, vn->vn_pos_in_item,
|
||||
vn->vn_mode);
|
||||
dir_u->entry_sizes[i] =
|
||||
(j ? deh_location(&(deh[j - 1])) : ih_item_len(vi->vi_ih)) -
|
||||
deh_location(&(deh[j])) + DEH_SIZE;
|
||||
(j ? deh_location(&deh[j - 1]) : ih_item_len(vi->vi_ih)) -
|
||||
deh_location(&deh[j]) + DEH_SIZE;
|
||||
}
|
||||
|
||||
size += (dir_u->entry_count * sizeof(short));
|
||||
|
@ -529,10 +526,10 @@ static int direntry_create_vi(struct virtual_node *vn,
|
|||
|
||||
}
|
||||
|
||||
//
|
||||
// return number of entries which may fit into specified amount of
|
||||
// free space, or -1 if free space is not enough even for 1 entry
|
||||
//
|
||||
/*
|
||||
* return number of entries which may fit into specified amount of
|
||||
* free space, or -1 if free space is not enough even for 1 entry
|
||||
*/
|
||||
static int direntry_check_left(struct virtual_item *vi, int free,
|
||||
int start_skip, int end_skip)
|
||||
{
|
||||
|
@ -541,8 +538,8 @@ static int direntry_check_left(struct virtual_item *vi, int free,
|
|||
struct direntry_uarea *dir_u = vi->vi_uarea;
|
||||
|
||||
for (i = start_skip; i < dir_u->entry_count - end_skip; i++) {
|
||||
if (dir_u->entry_sizes[i] > free)
|
||||
/* i-th entry doesn't fit into the remaining free space */
|
||||
if (dir_u->entry_sizes[i] > free)
|
||||
break;
|
||||
|
||||
free -= dir_u->entry_sizes[i];
|
||||
|
@ -570,8 +567,8 @@ static int direntry_check_right(struct virtual_item *vi, int free)
|
|||
struct direntry_uarea *dir_u = vi->vi_uarea;
|
||||
|
||||
for (i = dir_u->entry_count - 1; i >= 0; i--) {
|
||||
if (dir_u->entry_sizes[i] > free)
|
||||
/* i-th entry doesn't fit into the remaining free space */
|
||||
if (dir_u->entry_sizes[i] > free)
|
||||
break;
|
||||
|
||||
free -= dir_u->entry_sizes[i];
|
||||
|
@ -643,9 +640,7 @@ static struct item_operations direntry_ops = {
|
|||
.print_vi = direntry_print_vi
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Error catching functions to catch errors caused by incorrect item types.
|
||||
//
|
||||
/* Error catching functions to catch errors caused by incorrect item types. */
|
||||
static int errcatch_bytes_number(struct item_head *ih, int block_size)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16001",
|
||||
|
@ -685,8 +680,12 @@ static int errcatch_create_vi(struct virtual_node *vn,
|
|||
{
|
||||
reiserfs_warning(NULL, "green-16006",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
return 0; // We might return -1 here as well, but it won't help as create_virtual_node() from where
|
||||
// this operation is called from is of return type void.
|
||||
/*
|
||||
* We might return -1 here as well, but it won't help as
|
||||
* create_virtual_node() from where this operation is called
|
||||
* from is of return type void.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int errcatch_check_left(struct virtual_item *vi, int free,
|
||||
|
@ -739,9 +738,6 @@ static struct item_operations errcatch_ops = {
|
|||
errcatch_print_vi
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
#if ! (TYPE_STAT_DATA == 0 && TYPE_INDIRECT == 1 && TYPE_DIRECT == 2 && TYPE_DIRENTRY == 3)
|
||||
#error Item types must use disk-format assigned values.
|
||||
#endif
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,46 +8,42 @@
|
|||
#include "reiserfs.h"
|
||||
#include <linux/buffer_head.h>
|
||||
|
||||
/* these are used in do_balance.c */
|
||||
|
||||
/* leaf_move_items
|
||||
leaf_shift_left
|
||||
leaf_shift_right
|
||||
leaf_delete_items
|
||||
leaf_insert_into_buf
|
||||
leaf_paste_in_buffer
|
||||
leaf_cut_from_buffer
|
||||
leaf_paste_entries
|
||||
/*
|
||||
* copy copy_count entries from source directory item to dest buffer
|
||||
* (creating new item if needed)
|
||||
*/
|
||||
|
||||
/* copy copy_count entries from source directory item to dest buffer (creating new item if needed) */
|
||||
static void leaf_copy_dir_entries(struct buffer_info *dest_bi,
|
||||
struct buffer_head *source, int last_first,
|
||||
int item_num, int from, int copy_count)
|
||||
{
|
||||
struct buffer_head *dest = dest_bi->bi_bh;
|
||||
int item_num_in_dest; /* either the number of target item,
|
||||
or if we must create a new item,
|
||||
the number of the item we will
|
||||
create it next to */
|
||||
/*
|
||||
* either the number of target item, or if we must create a
|
||||
* new item, the number of the item we will create it next to
|
||||
*/
|
||||
int item_num_in_dest;
|
||||
|
||||
struct item_head *ih;
|
||||
struct reiserfs_de_head *deh;
|
||||
int copy_records_len; /* length of all records in item to be copied */
|
||||
char *records;
|
||||
|
||||
ih = B_N_PITEM_HEAD(source, item_num);
|
||||
ih = item_head(source, item_num);
|
||||
|
||||
RFALSE(!is_direntry_le_ih(ih), "vs-10000: item must be directory item");
|
||||
|
||||
/* length of all record to be copied and first byte of the last of them */
|
||||
/*
|
||||
* length of all record to be copied and first byte of
|
||||
* the last of them
|
||||
*/
|
||||
deh = B_I_DEH(source, ih);
|
||||
if (copy_count) {
|
||||
copy_records_len = (from ? deh_location(&(deh[from - 1])) :
|
||||
copy_records_len = (from ? deh_location(&deh[from - 1]) :
|
||||
ih_item_len(ih)) -
|
||||
deh_location(&(deh[from + copy_count - 1]));
|
||||
deh_location(&deh[from + copy_count - 1]);
|
||||
records =
|
||||
source->b_data + ih_location(ih) +
|
||||
deh_location(&(deh[from + copy_count - 1]));
|
||||
deh_location(&deh[from + copy_count - 1]);
|
||||
} else {
|
||||
copy_records_len = 0;
|
||||
records = NULL;
|
||||
|
@ -59,12 +55,15 @@ static void leaf_copy_dir_entries(struct buffer_info *dest_bi,
|
|||
LAST_TO_FIRST) ? ((B_NR_ITEMS(dest)) ? 0 : -1) : (B_NR_ITEMS(dest)
|
||||
- 1);
|
||||
|
||||
/* if there are no items in dest or the first/last item in dest is not item of the same directory */
|
||||
/*
|
||||
* if there are no items in dest or the first/last item in
|
||||
* dest is not item of the same directory
|
||||
*/
|
||||
if ((item_num_in_dest == -1) ||
|
||||
(last_first == FIRST_TO_LAST && le_ih_k_offset(ih) == DOT_OFFSET) ||
|
||||
(last_first == LAST_TO_FIRST
|
||||
&& comp_short_le_keys /*COMP_SHORT_KEYS */ (&ih->ih_key,
|
||||
B_N_PKEY(dest,
|
||||
leaf_key(dest,
|
||||
item_num_in_dest))))
|
||||
{
|
||||
/* create new item in dest */
|
||||
|
@ -80,16 +79,22 @@ static void leaf_copy_dir_entries(struct buffer_info *dest_bi,
|
|||
|
||||
if (last_first == LAST_TO_FIRST) {
|
||||
/* form key by the following way */
|
||||
if (from < I_ENTRY_COUNT(ih)) {
|
||||
if (from < ih_entry_count(ih)) {
|
||||
set_le_ih_k_offset(&new_ih,
|
||||
deh_offset(&(deh[from])));
|
||||
/*memcpy (&new_ih.ih_key.k_offset, &deh[from].deh_offset, SHORT_KEY_SIZE); */
|
||||
deh_offset(&deh[from]));
|
||||
} else {
|
||||
/* no entries will be copied to this item in this function */
|
||||
/*
|
||||
* no entries will be copied to this
|
||||
* item in this function
|
||||
*/
|
||||
set_le_ih_k_offset(&new_ih, U32_MAX);
|
||||
/* this item is not yet valid, but we want I_IS_DIRECTORY_ITEM to return 1 for it, so we -1 */
|
||||
/*
|
||||
* this item is not yet valid, but we
|
||||
* want I_IS_DIRECTORY_ITEM to return 1
|
||||
* for it, so we -1
|
||||
*/
|
||||
}
|
||||
set_le_key_k_type(KEY_FORMAT_3_5, &(new_ih.ih_key),
|
||||
set_le_key_k_type(KEY_FORMAT_3_5, &new_ih.ih_key,
|
||||
TYPE_DIRENTRY);
|
||||
}
|
||||
|
||||
|
@ -113,36 +118,44 @@ static void leaf_copy_dir_entries(struct buffer_info *dest_bi,
|
|||
|
||||
leaf_paste_entries(dest_bi, item_num_in_dest,
|
||||
(last_first ==
|
||||
FIRST_TO_LAST) ? I_ENTRY_COUNT(B_N_PITEM_HEAD(dest,
|
||||
FIRST_TO_LAST) ? ih_entry_count(item_head(dest,
|
||||
item_num_in_dest))
|
||||
: 0, copy_count, deh + from, records,
|
||||
DEH_SIZE * copy_count + copy_records_len);
|
||||
}
|
||||
|
||||
/* Copy the first (if last_first == FIRST_TO_LAST) or last (last_first == LAST_TO_FIRST) item or
|
||||
part of it or nothing (see the return 0 below) from SOURCE to the end
|
||||
(if last_first) or beginning (!last_first) of the DEST */
|
||||
/*
|
||||
* Copy the first (if last_first == FIRST_TO_LAST) or last
|
||||
* (last_first == LAST_TO_FIRST) item or part of it or nothing
|
||||
* (see the return 0 below) from SOURCE to the end (if last_first)
|
||||
* or beginning (!last_first) of the DEST
|
||||
*/
|
||||
/* returns 1 if anything was copied, else 0 */
|
||||
static int leaf_copy_boundary_item(struct buffer_info *dest_bi,
|
||||
struct buffer_head *src, int last_first,
|
||||
int bytes_or_entries)
|
||||
{
|
||||
struct buffer_head *dest = dest_bi->bi_bh;
|
||||
int dest_nr_item, src_nr_item; /* number of items in the source and destination buffers */
|
||||
/* number of items in the source and destination buffers */
|
||||
int dest_nr_item, src_nr_item;
|
||||
struct item_head *ih;
|
||||
struct item_head *dih;
|
||||
|
||||
dest_nr_item = B_NR_ITEMS(dest);
|
||||
|
||||
/*
|
||||
* if ( DEST is empty or first item of SOURCE and last item of
|
||||
* DEST are the items of different objects or of different types )
|
||||
* then there is no need to treat this item differently from the
|
||||
* other items that we copy, so we return
|
||||
*/
|
||||
if (last_first == FIRST_TO_LAST) {
|
||||
/* if ( DEST is empty or first item of SOURCE and last item of DEST are the items of different objects
|
||||
or of different types ) then there is no need to treat this item differently from the other items
|
||||
that we copy, so we return */
|
||||
ih = B_N_PITEM_HEAD(src, 0);
|
||||
dih = B_N_PITEM_HEAD(dest, dest_nr_item - 1);
|
||||
if (!dest_nr_item
|
||||
|| (!op_is_left_mergeable(&(ih->ih_key), src->b_size)))
|
||||
ih = item_head(src, 0);
|
||||
dih = item_head(dest, dest_nr_item - 1);
|
||||
|
||||
/* there is nothing to merge */
|
||||
if (!dest_nr_item
|
||||
|| (!op_is_left_mergeable(&ih->ih_key, src->b_size)))
|
||||
return 0;
|
||||
|
||||
RFALSE(!ih_item_len(ih),
|
||||
|
@ -157,8 +170,11 @@ static int leaf_copy_boundary_item(struct buffer_info *dest_bi,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* copy part of the body of the first item of SOURCE to the end of the body of the last item of the DEST
|
||||
part defined by 'bytes_or_entries'; if bytes_or_entries == -1 copy whole body; don't create new item header
|
||||
/*
|
||||
* copy part of the body of the first item of SOURCE
|
||||
* to the end of the body of the last item of the DEST
|
||||
* part defined by 'bytes_or_entries'; if bytes_or_entries
|
||||
* == -1 copy whole body; don't create new item header
|
||||
*/
|
||||
if (bytes_or_entries == -1)
|
||||
bytes_or_entries = ih_item_len(ih);
|
||||
|
@ -176,11 +192,13 @@ static int leaf_copy_boundary_item(struct buffer_info *dest_bi,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* merge first item (or its part) of src buffer with the last
|
||||
item of dest buffer. Both are of the same file */
|
||||
/*
|
||||
* merge first item (or its part) of src buffer with the last
|
||||
* item of dest buffer. Both are of the same file
|
||||
*/
|
||||
leaf_paste_in_buffer(dest_bi,
|
||||
dest_nr_item - 1, ih_item_len(dih),
|
||||
bytes_or_entries, B_I_PITEM(src, ih), 0);
|
||||
bytes_or_entries, ih_item_body(src, ih), 0);
|
||||
|
||||
if (is_indirect_le_ih(dih)) {
|
||||
RFALSE(get_ih_free_space(dih),
|
||||
|
@ -195,19 +213,23 @@ static int leaf_copy_boundary_item(struct buffer_info *dest_bi,
|
|||
|
||||
/* copy boundary item to right (last_first == LAST_TO_FIRST) */
|
||||
|
||||
/* ( DEST is empty or last item of SOURCE and first item of DEST
|
||||
are the items of different object or of different types )
|
||||
/*
|
||||
* (DEST is empty or last item of SOURCE and first item of DEST
|
||||
* are the items of different object or of different types)
|
||||
*/
|
||||
src_nr_item = B_NR_ITEMS(src);
|
||||
ih = B_N_PITEM_HEAD(src, src_nr_item - 1);
|
||||
dih = B_N_PITEM_HEAD(dest, 0);
|
||||
ih = item_head(src, src_nr_item - 1);
|
||||
dih = item_head(dest, 0);
|
||||
|
||||
if (!dest_nr_item || !op_is_left_mergeable(&(dih->ih_key), src->b_size))
|
||||
if (!dest_nr_item || !op_is_left_mergeable(&dih->ih_key, src->b_size))
|
||||
return 0;
|
||||
|
||||
if (is_direntry_le_ih(ih)) {
|
||||
/*
|
||||
* bytes_or_entries = entries number in last
|
||||
* item body of SOURCE
|
||||
*/
|
||||
if (bytes_or_entries == -1)
|
||||
/* bytes_or_entries = entries number in last item body of SOURCE */
|
||||
bytes_or_entries = ih_entry_count(ih);
|
||||
|
||||
leaf_copy_dir_entries(dest_bi, src, LAST_TO_FIRST,
|
||||
|
@ -217,9 +239,11 @@ static int leaf_copy_boundary_item(struct buffer_info *dest_bi,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* copy part of the body of the last item of SOURCE to the begin of the body of the first item of the DEST;
|
||||
part defined by 'bytes_or_entries'; if byte_or_entriess == -1 copy whole body; change first item key of the DEST;
|
||||
don't create new item header
|
||||
/*
|
||||
* copy part of the body of the last item of SOURCE to the
|
||||
* begin of the body of the first item of the DEST; part defined
|
||||
* by 'bytes_or_entries'; if byte_or_entriess == -1 copy whole body;
|
||||
* change first item key of the DEST; don't create new item header
|
||||
*/
|
||||
|
||||
RFALSE(is_indirect_le_ih(ih) && get_ih_free_space(ih),
|
||||
|
@ -270,15 +294,18 @@ static int leaf_copy_boundary_item(struct buffer_info *dest_bi,
|
|||
}
|
||||
|
||||
leaf_paste_in_buffer(dest_bi, 0, 0, bytes_or_entries,
|
||||
B_I_PITEM(src,
|
||||
ih_item_body(src,
|
||||
ih) + ih_item_len(ih) - bytes_or_entries,
|
||||
0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* copy cpy_mun items from buffer src to buffer dest
|
||||
* last_first == FIRST_TO_LAST means, that we copy cpy_num items beginning from first-th item in src to tail of dest
|
||||
* last_first == LAST_TO_FIRST means, that we copy cpy_num items beginning from first-th item in src to head of dest
|
||||
/*
|
||||
* copy cpy_mun items from buffer src to buffer dest
|
||||
* last_first == FIRST_TO_LAST means, that we copy cpy_num items beginning
|
||||
* from first-th item in src to tail of dest
|
||||
* last_first == LAST_TO_FIRST means, that we copy cpy_num items beginning
|
||||
* from first-th item in src to head of dest
|
||||
*/
|
||||
static void leaf_copy_items_entirely(struct buffer_info *dest_bi,
|
||||
struct buffer_head *src, int last_first,
|
||||
|
@ -311,11 +338,14 @@ static void leaf_copy_items_entirely(struct buffer_info *dest_bi,
|
|||
nr = blkh_nr_item(blkh);
|
||||
free_space = blkh_free_space(blkh);
|
||||
|
||||
/* we will insert items before 0-th or nr-th item in dest buffer. It depends of last_first parameter */
|
||||
/*
|
||||
* we will insert items before 0-th or nr-th item in dest buffer.
|
||||
* It depends of last_first parameter
|
||||
*/
|
||||
dest_before = (last_first == LAST_TO_FIRST) ? 0 : nr;
|
||||
|
||||
/* location of head of first new item */
|
||||
ih = B_N_PITEM_HEAD(dest, dest_before);
|
||||
ih = item_head(dest, dest_before);
|
||||
|
||||
RFALSE(blkh_free_space(blkh) < cpy_num * IH_SIZE,
|
||||
"vs-10140: not enough free space for headers %d (needed %d)",
|
||||
|
@ -325,7 +355,7 @@ static void leaf_copy_items_entirely(struct buffer_info *dest_bi,
|
|||
memmove(ih + cpy_num, ih, (nr - dest_before) * IH_SIZE);
|
||||
|
||||
/* copy item headers */
|
||||
memcpy(ih, B_N_PITEM_HEAD(src, first), cpy_num * IH_SIZE);
|
||||
memcpy(ih, item_head(src, first), cpy_num * IH_SIZE);
|
||||
|
||||
free_space -= (IH_SIZE * cpy_num);
|
||||
set_blkh_free_space(blkh, free_space);
|
||||
|
@ -338,8 +368,8 @@ static void leaf_copy_items_entirely(struct buffer_info *dest_bi,
|
|||
}
|
||||
|
||||
/* prepare space for items */
|
||||
last_loc = ih_location(&(ih[nr + cpy_num - 1 - dest_before]));
|
||||
last_inserted_loc = ih_location(&(ih[cpy_num - 1]));
|
||||
last_loc = ih_location(&ih[nr + cpy_num - 1 - dest_before]);
|
||||
last_inserted_loc = ih_location(&ih[cpy_num - 1]);
|
||||
|
||||
/* check free space */
|
||||
RFALSE(free_space < j - last_inserted_loc,
|
||||
|
@ -352,7 +382,8 @@ static void leaf_copy_items_entirely(struct buffer_info *dest_bi,
|
|||
|
||||
/* copy items */
|
||||
memcpy(dest->b_data + last_inserted_loc,
|
||||
B_N_PITEM(src, (first + cpy_num - 1)), j - last_inserted_loc);
|
||||
item_body(src, (first + cpy_num - 1)),
|
||||
j - last_inserted_loc);
|
||||
|
||||
/* sizes, item number */
|
||||
set_blkh_nr_item(blkh, nr + cpy_num);
|
||||
|
@ -376,8 +407,10 @@ static void leaf_copy_items_entirely(struct buffer_info *dest_bi,
|
|||
}
|
||||
}
|
||||
|
||||
/* This function splits the (liquid) item into two items (useful when
|
||||
shifting part of an item into another node.) */
|
||||
/*
|
||||
* This function splits the (liquid) item into two items (useful when
|
||||
* shifting part of an item into another node.)
|
||||
*/
|
||||
static void leaf_item_bottle(struct buffer_info *dest_bi,
|
||||
struct buffer_head *src, int last_first,
|
||||
int item_num, int cpy_bytes)
|
||||
|
@ -389,17 +422,22 @@ static void leaf_item_bottle(struct buffer_info *dest_bi,
|
|||
"vs-10170: bytes == - 1 means: do not split item");
|
||||
|
||||
if (last_first == FIRST_TO_LAST) {
|
||||
/* if ( if item in position item_num in buffer SOURCE is directory item ) */
|
||||
ih = B_N_PITEM_HEAD(src, item_num);
|
||||
/*
|
||||
* if ( if item in position item_num in buffer SOURCE
|
||||
* is directory item )
|
||||
*/
|
||||
ih = item_head(src, item_num);
|
||||
if (is_direntry_le_ih(ih))
|
||||
leaf_copy_dir_entries(dest_bi, src, FIRST_TO_LAST,
|
||||
item_num, 0, cpy_bytes);
|
||||
else {
|
||||
struct item_head n_ih;
|
||||
|
||||
/* copy part of the body of the item number 'item_num' of SOURCE to the end of the DEST
|
||||
part defined by 'cpy_bytes'; create new item header; change old item_header (????);
|
||||
n_ih = new item_header;
|
||||
/*
|
||||
* copy part of the body of the item number 'item_num'
|
||||
* of SOURCE to the end of the DEST part defined by
|
||||
* 'cpy_bytes'; create new item header; change old
|
||||
* item_header (????); n_ih = new item_header;
|
||||
*/
|
||||
memcpy(&n_ih, ih, IH_SIZE);
|
||||
put_ih_item_len(&n_ih, cpy_bytes);
|
||||
|
@ -411,30 +449,36 @@ static void leaf_item_bottle(struct buffer_info *dest_bi,
|
|||
set_ih_free_space(&n_ih, 0);
|
||||
}
|
||||
|
||||
RFALSE(op_is_left_mergeable(&(ih->ih_key), src->b_size),
|
||||
RFALSE(op_is_left_mergeable(&ih->ih_key, src->b_size),
|
||||
"vs-10190: bad mergeability of item %h", ih);
|
||||
n_ih.ih_version = ih->ih_version; /* JDM Endian safe, both le */
|
||||
leaf_insert_into_buf(dest_bi, B_NR_ITEMS(dest), &n_ih,
|
||||
B_N_PITEM(src, item_num), 0);
|
||||
item_body(src, item_num), 0);
|
||||
}
|
||||
} else {
|
||||
/* if ( if item in position item_num in buffer SOURCE is directory item ) */
|
||||
ih = B_N_PITEM_HEAD(src, item_num);
|
||||
/*
|
||||
* if ( if item in position item_num in buffer
|
||||
* SOURCE is directory item )
|
||||
*/
|
||||
ih = item_head(src, item_num);
|
||||
if (is_direntry_le_ih(ih))
|
||||
leaf_copy_dir_entries(dest_bi, src, LAST_TO_FIRST,
|
||||
item_num,
|
||||
I_ENTRY_COUNT(ih) - cpy_bytes,
|
||||
ih_entry_count(ih) - cpy_bytes,
|
||||
cpy_bytes);
|
||||
else {
|
||||
struct item_head n_ih;
|
||||
|
||||
/* copy part of the body of the item number 'item_num' of SOURCE to the begin of the DEST
|
||||
part defined by 'cpy_bytes'; create new item header;
|
||||
n_ih = new item_header;
|
||||
/*
|
||||
* copy part of the body of the item number 'item_num'
|
||||
* of SOURCE to the begin of the DEST part defined by
|
||||
* 'cpy_bytes'; create new item header;
|
||||
* n_ih = new item_header;
|
||||
*/
|
||||
memcpy(&n_ih, ih, SHORT_KEY_SIZE);
|
||||
|
||||
n_ih.ih_version = ih->ih_version; /* JDM Endian safe, both le */
|
||||
/* Endian safe, both le */
|
||||
n_ih.ih_version = ih->ih_version;
|
||||
|
||||
if (is_direct_le_ih(ih)) {
|
||||
set_le_ih_k_offset(&n_ih,
|
||||
|
@ -458,20 +502,22 @@ static void leaf_item_bottle(struct buffer_info *dest_bi,
|
|||
/* set item length */
|
||||
put_ih_item_len(&n_ih, cpy_bytes);
|
||||
|
||||
n_ih.ih_version = ih->ih_version; /* JDM Endian safe, both le */
|
||||
/* Endian safe, both le */
|
||||
n_ih.ih_version = ih->ih_version;
|
||||
|
||||
leaf_insert_into_buf(dest_bi, 0, &n_ih,
|
||||
B_N_PITEM(src,
|
||||
item_num) +
|
||||
item_body(src, item_num) +
|
||||
ih_item_len(ih) - cpy_bytes, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If cpy_bytes equals minus one than copy cpy_num whole items from SOURCE to DEST.
|
||||
If cpy_bytes not equal to minus one than copy cpy_num-1 whole items from SOURCE to DEST.
|
||||
From last item copy cpy_num bytes for regular item and cpy_num directory entries for
|
||||
directory item. */
|
||||
/*
|
||||
* If cpy_bytes equals minus one than copy cpy_num whole items from SOURCE
|
||||
* to DEST. If cpy_bytes not equal to minus one than copy cpy_num-1 whole
|
||||
* items from SOURCE to DEST. From last item copy cpy_num bytes for regular
|
||||
* item and cpy_num directory entries for directory item.
|
||||
*/
|
||||
static int leaf_copy_items(struct buffer_info *dest_bi, struct buffer_head *src,
|
||||
int last_first, int cpy_num, int cpy_bytes)
|
||||
{
|
||||
|
@ -498,22 +544,34 @@ static int leaf_copy_items(struct buffer_info *dest_bi, struct buffer_head *src,
|
|||
else
|
||||
bytes = -1;
|
||||
|
||||
/* copy the first item or it part or nothing to the end of the DEST (i = leaf_copy_boundary_item(DEST,SOURCE,0,bytes)) */
|
||||
/*
|
||||
* copy the first item or it part or nothing to the end of
|
||||
* the DEST (i = leaf_copy_boundary_item(DEST,SOURCE,0,bytes))
|
||||
*/
|
||||
i = leaf_copy_boundary_item(dest_bi, src, FIRST_TO_LAST, bytes);
|
||||
cpy_num -= i;
|
||||
if (cpy_num == 0)
|
||||
return i;
|
||||
pos += i;
|
||||
if (cpy_bytes == -1)
|
||||
/* copy first cpy_num items starting from position 'pos' of SOURCE to end of DEST */
|
||||
/*
|
||||
* copy first cpy_num items starting from position
|
||||
* 'pos' of SOURCE to end of DEST
|
||||
*/
|
||||
leaf_copy_items_entirely(dest_bi, src, FIRST_TO_LAST,
|
||||
pos, cpy_num);
|
||||
else {
|
||||
/* copy first cpy_num-1 items starting from position 'pos-1' of the SOURCE to the end of the DEST */
|
||||
/*
|
||||
* copy first cpy_num-1 items starting from position
|
||||
* 'pos-1' of the SOURCE to the end of the DEST
|
||||
*/
|
||||
leaf_copy_items_entirely(dest_bi, src, FIRST_TO_LAST,
|
||||
pos, cpy_num - 1);
|
||||
|
||||
/* copy part of the item which number is cpy_num+pos-1 to the end of the DEST */
|
||||
/*
|
||||
* copy part of the item which number is
|
||||
* cpy_num+pos-1 to the end of the DEST
|
||||
*/
|
||||
leaf_item_bottle(dest_bi, src, FIRST_TO_LAST,
|
||||
cpy_num + pos - 1, cpy_bytes);
|
||||
}
|
||||
|
@ -525,7 +583,11 @@ static int leaf_copy_items(struct buffer_info *dest_bi, struct buffer_head *src,
|
|||
else
|
||||
bytes = -1;
|
||||
|
||||
/* copy the last item or it part or nothing to the begin of the DEST (i = leaf_copy_boundary_item(DEST,SOURCE,1,bytes)); */
|
||||
/*
|
||||
* copy the last item or it part or nothing to the
|
||||
* begin of the DEST
|
||||
* (i = leaf_copy_boundary_item(DEST,SOURCE,1,bytes));
|
||||
*/
|
||||
i = leaf_copy_boundary_item(dest_bi, src, LAST_TO_FIRST, bytes);
|
||||
|
||||
cpy_num -= i;
|
||||
|
@ -534,15 +596,24 @@ static int leaf_copy_items(struct buffer_info *dest_bi, struct buffer_head *src,
|
|||
|
||||
pos = src_nr_item - cpy_num - i;
|
||||
if (cpy_bytes == -1) {
|
||||
/* starting from position 'pos' copy last cpy_num items of SOURCE to begin of DEST */
|
||||
/*
|
||||
* starting from position 'pos' copy last cpy_num
|
||||
* items of SOURCE to begin of DEST
|
||||
*/
|
||||
leaf_copy_items_entirely(dest_bi, src, LAST_TO_FIRST,
|
||||
pos, cpy_num);
|
||||
} else {
|
||||
/* copy last cpy_num-1 items starting from position 'pos+1' of the SOURCE to the begin of the DEST; */
|
||||
/*
|
||||
* copy last cpy_num-1 items starting from position
|
||||
* 'pos+1' of the SOURCE to the begin of the DEST;
|
||||
*/
|
||||
leaf_copy_items_entirely(dest_bi, src, LAST_TO_FIRST,
|
||||
pos + 1, cpy_num - 1);
|
||||
|
||||
/* copy part of the item which number is pos to the begin of the DEST */
|
||||
/*
|
||||
* copy part of the item which number is pos to
|
||||
* the begin of the DEST
|
||||
*/
|
||||
leaf_item_bottle(dest_bi, src, LAST_TO_FIRST, pos,
|
||||
cpy_bytes);
|
||||
}
|
||||
|
@ -550,9 +621,11 @@ static int leaf_copy_items(struct buffer_info *dest_bi, struct buffer_head *src,
|
|||
return i;
|
||||
}
|
||||
|
||||
/* there are types of coping: from S[0] to L[0], from S[0] to R[0],
|
||||
from R[0] to L[0]. for each of these we have to define parent and
|
||||
positions of destination and source buffers */
|
||||
/*
|
||||
* there are types of coping: from S[0] to L[0], from S[0] to R[0],
|
||||
* from R[0] to L[0]. for each of these we have to define parent and
|
||||
* positions of destination and source buffers
|
||||
*/
|
||||
static void leaf_define_dest_src_infos(int shift_mode, struct tree_balance *tb,
|
||||
struct buffer_info *dest_bi,
|
||||
struct buffer_info *src_bi,
|
||||
|
@ -568,7 +641,9 @@ static void leaf_define_dest_src_infos(int shift_mode, struct tree_balance *tb,
|
|||
src_bi->tb = tb;
|
||||
src_bi->bi_bh = PATH_PLAST_BUFFER(tb->tb_path);
|
||||
src_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, 0);
|
||||
src_bi->bi_position = PATH_H_B_ITEM_ORDER(tb->tb_path, 0); /* src->b_item_order */
|
||||
|
||||
/* src->b_item_order */
|
||||
src_bi->bi_position = PATH_H_B_ITEM_ORDER(tb->tb_path, 0);
|
||||
dest_bi->tb = tb;
|
||||
dest_bi->bi_bh = tb->L[0];
|
||||
dest_bi->bi_parent = tb->FL[0];
|
||||
|
@ -633,8 +708,10 @@ static void leaf_define_dest_src_infos(int shift_mode, struct tree_balance *tb,
|
|||
shift_mode, src_bi->bi_bh, dest_bi->bi_bh);
|
||||
}
|
||||
|
||||
/* copy mov_num items and mov_bytes of the (mov_num-1)th item to
|
||||
neighbor. Delete them from source */
|
||||
/*
|
||||
* copy mov_num items and mov_bytes of the (mov_num-1)th item to
|
||||
* neighbor. Delete them from source
|
||||
*/
|
||||
int leaf_move_items(int shift_mode, struct tree_balance *tb, int mov_num,
|
||||
int mov_bytes, struct buffer_head *Snew)
|
||||
{
|
||||
|
@ -657,18 +734,24 @@ int leaf_move_items(int shift_mode, struct tree_balance *tb, int mov_num,
|
|||
return ret_value;
|
||||
}
|
||||
|
||||
/* Shift shift_num items (and shift_bytes of last shifted item if shift_bytes != -1)
|
||||
from S[0] to L[0] and replace the delimiting key */
|
||||
/*
|
||||
* Shift shift_num items (and shift_bytes of last shifted item if
|
||||
* shift_bytes != -1) from S[0] to L[0] and replace the delimiting key
|
||||
*/
|
||||
int leaf_shift_left(struct tree_balance *tb, int shift_num, int shift_bytes)
|
||||
{
|
||||
struct buffer_head *S0 = PATH_PLAST_BUFFER(tb->tb_path);
|
||||
int i;
|
||||
|
||||
/* move shift_num (and shift_bytes bytes) items from S[0] to left neighbor L[0] */
|
||||
/*
|
||||
* move shift_num (and shift_bytes bytes) items from S[0]
|
||||
* to left neighbor L[0]
|
||||
*/
|
||||
i = leaf_move_items(LEAF_FROM_S_TO_L, tb, shift_num, shift_bytes, NULL);
|
||||
|
||||
if (shift_num) {
|
||||
if (B_NR_ITEMS(S0) == 0) { /* number of items in S[0] == 0 */
|
||||
/* number of items in S[0] == 0 */
|
||||
if (B_NR_ITEMS(S0) == 0) {
|
||||
|
||||
RFALSE(shift_bytes != -1,
|
||||
"vs-10270: S0 is empty now, but shift_bytes != -1 (%d)",
|
||||
|
@ -691,10 +774,10 @@ int leaf_shift_left(struct tree_balance *tb, int shift_num, int shift_bytes)
|
|||
replace_key(tb, tb->CFL[0], tb->lkey[0], S0, 0);
|
||||
|
||||
RFALSE((shift_bytes != -1 &&
|
||||
!(is_direntry_le_ih(B_N_PITEM_HEAD(S0, 0))
|
||||
&& !I_ENTRY_COUNT(B_N_PITEM_HEAD(S0, 0)))) &&
|
||||
!(is_direntry_le_ih(item_head(S0, 0))
|
||||
&& !ih_entry_count(item_head(S0, 0)))) &&
|
||||
(!op_is_left_mergeable
|
||||
(B_N_PKEY(S0, 0), S0->b_size)),
|
||||
(leaf_key(S0, 0), S0->b_size)),
|
||||
"vs-10280: item must be mergeable");
|
||||
}
|
||||
}
|
||||
|
@ -704,13 +787,18 @@ int leaf_shift_left(struct tree_balance *tb, int shift_num, int shift_bytes)
|
|||
|
||||
/* CLEANING STOPPED HERE */
|
||||
|
||||
/* Shift shift_num (shift_bytes) items from S[0] to the right neighbor, and replace the delimiting key */
|
||||
/*
|
||||
* Shift shift_num (shift_bytes) items from S[0] to the right neighbor,
|
||||
* and replace the delimiting key
|
||||
*/
|
||||
int leaf_shift_right(struct tree_balance *tb, int shift_num, int shift_bytes)
|
||||
{
|
||||
// struct buffer_head * S0 = PATH_PLAST_BUFFER (tb->tb_path);
|
||||
int ret_value;
|
||||
|
||||
/* move shift_num (and shift_bytes) items from S[0] to right neighbor R[0] */
|
||||
/*
|
||||
* move shift_num (and shift_bytes) items from S[0] to
|
||||
* right neighbor R[0]
|
||||
*/
|
||||
ret_value =
|
||||
leaf_move_items(LEAF_FROM_S_TO_R, tb, shift_num, shift_bytes, NULL);
|
||||
|
||||
|
@ -725,12 +813,16 @@ int leaf_shift_right(struct tree_balance *tb, int shift_num, int shift_bytes)
|
|||
|
||||
static void leaf_delete_items_entirely(struct buffer_info *bi,
|
||||
int first, int del_num);
|
||||
/* If del_bytes == -1, starting from position 'first' delete del_num items in whole in buffer CUR.
|
||||
If not.
|
||||
If last_first == 0. Starting from position 'first' delete del_num-1 items in whole. Delete part of body of
|
||||
the first item. Part defined by del_bytes. Don't delete first item header
|
||||
If last_first == 1. Starting from position 'first+1' delete del_num-1 items in whole. Delete part of body of
|
||||
the last item . Part defined by del_bytes. Don't delete last item header.
|
||||
/*
|
||||
* If del_bytes == -1, starting from position 'first' delete del_num
|
||||
* items in whole in buffer CUR.
|
||||
* If not.
|
||||
* If last_first == 0. Starting from position 'first' delete del_num-1
|
||||
* items in whole. Delete part of body of the first item. Part defined by
|
||||
* del_bytes. Don't delete first item header
|
||||
* If last_first == 1. Starting from position 'first+1' delete del_num-1
|
||||
* items in whole. Delete part of body of the last item . Part defined by
|
||||
* del_bytes. Don't delete last item header.
|
||||
*/
|
||||
void leaf_delete_items(struct buffer_info *cur_bi, int last_first,
|
||||
int first, int del_num, int del_bytes)
|
||||
|
@ -761,32 +853,43 @@ void leaf_delete_items(struct buffer_info *cur_bi, int last_first,
|
|||
leaf_delete_items_entirely(cur_bi, first, del_num);
|
||||
else {
|
||||
if (last_first == FIRST_TO_LAST) {
|
||||
/* delete del_num-1 items beginning from item in position first */
|
||||
/*
|
||||
* delete del_num-1 items beginning from
|
||||
* item in position first
|
||||
*/
|
||||
leaf_delete_items_entirely(cur_bi, first, del_num - 1);
|
||||
|
||||
/* delete the part of the first item of the bh
|
||||
do not delete item header
|
||||
/*
|
||||
* delete the part of the first item of the bh
|
||||
* do not delete item header
|
||||
*/
|
||||
leaf_cut_from_buffer(cur_bi, 0, 0, del_bytes);
|
||||
} else {
|
||||
struct item_head *ih;
|
||||
int len;
|
||||
|
||||
/* delete del_num-1 items beginning from item in position first+1 */
|
||||
/*
|
||||
* delete del_num-1 items beginning from
|
||||
* item in position first+1
|
||||
*/
|
||||
leaf_delete_items_entirely(cur_bi, first + 1,
|
||||
del_num - 1);
|
||||
|
||||
ih = B_N_PITEM_HEAD(bh, B_NR_ITEMS(bh) - 1);
|
||||
ih = item_head(bh, B_NR_ITEMS(bh) - 1);
|
||||
if (is_direntry_le_ih(ih))
|
||||
/* the last item is directory */
|
||||
/* len = numbers of directory entries in this item */
|
||||
/*
|
||||
* len = numbers of directory entries
|
||||
* in this item
|
||||
*/
|
||||
len = ih_entry_count(ih);
|
||||
else
|
||||
/* len = body len of item */
|
||||
len = ih_item_len(ih);
|
||||
|
||||
/* delete the part of the last item of the bh
|
||||
do not delete item header
|
||||
/*
|
||||
* delete the part of the last item of the bh
|
||||
* do not delete item header
|
||||
*/
|
||||
leaf_cut_from_buffer(cur_bi, B_NR_ITEMS(bh) - 1,
|
||||
len - del_bytes, del_bytes);
|
||||
|
@ -820,10 +923,10 @@ void leaf_insert_into_buf(struct buffer_info *bi, int before,
|
|||
zeros_number, ih_item_len(inserted_item_ih));
|
||||
|
||||
/* get item new item must be inserted before */
|
||||
ih = B_N_PITEM_HEAD(bh, before);
|
||||
ih = item_head(bh, before);
|
||||
|
||||
/* prepare space for the body of new item */
|
||||
last_loc = nr ? ih_location(&(ih[nr - before - 1])) : bh->b_size;
|
||||
last_loc = nr ? ih_location(&ih[nr - before - 1]) : bh->b_size;
|
||||
unmoved_loc = before ? ih_location(ih - 1) : bh->b_size;
|
||||
|
||||
memmove(bh->b_data + last_loc - ih_item_len(inserted_item_ih),
|
||||
|
@ -846,8 +949,8 @@ void leaf_insert_into_buf(struct buffer_info *bi, int before,
|
|||
|
||||
/* change locations */
|
||||
for (i = before; i < nr + 1; i++) {
|
||||
unmoved_loc -= ih_item_len(&(ih[i - before]));
|
||||
put_ih_location(&(ih[i - before]), unmoved_loc);
|
||||
unmoved_loc -= ih_item_len(&ih[i - before]);
|
||||
put_ih_location(&ih[i - before], unmoved_loc);
|
||||
}
|
||||
|
||||
/* sizes, free space, item number */
|
||||
|
@ -867,8 +970,10 @@ void leaf_insert_into_buf(struct buffer_info *bi, int before,
|
|||
}
|
||||
}
|
||||
|
||||
/* paste paste_size bytes to affected_item_num-th item.
|
||||
When item is a directory, this only prepare space for new entries */
|
||||
/*
|
||||
* paste paste_size bytes to affected_item_num-th item.
|
||||
* When item is a directory, this only prepare space for new entries
|
||||
*/
|
||||
void leaf_paste_in_buffer(struct buffer_info *bi, int affected_item_num,
|
||||
int pos_in_item, int paste_size,
|
||||
const char *body, int zeros_number)
|
||||
|
@ -902,9 +1007,9 @@ void leaf_paste_in_buffer(struct buffer_info *bi, int affected_item_num,
|
|||
#endif /* CONFIG_REISERFS_CHECK */
|
||||
|
||||
/* item to be appended */
|
||||
ih = B_N_PITEM_HEAD(bh, affected_item_num);
|
||||
ih = item_head(bh, affected_item_num);
|
||||
|
||||
last_loc = ih_location(&(ih[nr - affected_item_num - 1]));
|
||||
last_loc = ih_location(&ih[nr - affected_item_num - 1]);
|
||||
unmoved_loc = affected_item_num ? ih_location(ih - 1) : bh->b_size;
|
||||
|
||||
/* prepare space */
|
||||
|
@ -913,8 +1018,8 @@ void leaf_paste_in_buffer(struct buffer_info *bi, int affected_item_num,
|
|||
|
||||
/* change locations */
|
||||
for (i = affected_item_num; i < nr; i++)
|
||||
put_ih_location(&(ih[i - affected_item_num]),
|
||||
ih_location(&(ih[i - affected_item_num])) -
|
||||
put_ih_location(&ih[i - affected_item_num],
|
||||
ih_location(&ih[i - affected_item_num]) -
|
||||
paste_size);
|
||||
|
||||
if (body) {
|
||||
|
@ -957,10 +1062,12 @@ void leaf_paste_in_buffer(struct buffer_info *bi, int affected_item_num,
|
|||
}
|
||||
}
|
||||
|
||||
/* cuts DEL_COUNT entries beginning from FROM-th entry. Directory item
|
||||
does not have free space, so it moves DEHs and remaining records as
|
||||
necessary. Return value is size of removed part of directory item
|
||||
in bytes. */
|
||||
/*
|
||||
* cuts DEL_COUNT entries beginning from FROM-th entry. Directory item
|
||||
* does not have free space, so it moves DEHs and remaining records as
|
||||
* necessary. Return value is size of removed part of directory item
|
||||
* in bytes.
|
||||
*/
|
||||
static int leaf_cut_entries(struct buffer_head *bh,
|
||||
struct item_head *ih, int from, int del_count)
|
||||
{
|
||||
|
@ -971,12 +1078,14 @@ static int leaf_cut_entries(struct buffer_head *bh,
|
|||
int cut_records_len; /* length of all removed records */
|
||||
int i;
|
||||
|
||||
/* make sure, that item is directory and there are enough entries to
|
||||
remove */
|
||||
/*
|
||||
* make sure that item is directory and there are enough entries to
|
||||
* remove
|
||||
*/
|
||||
RFALSE(!is_direntry_le_ih(ih), "10180: item is not directory item");
|
||||
RFALSE(I_ENTRY_COUNT(ih) < from + del_count,
|
||||
RFALSE(ih_entry_count(ih) < from + del_count,
|
||||
"10185: item contains not enough entries: entry_count = %d, from = %d, to delete = %d",
|
||||
I_ENTRY_COUNT(ih), from, del_count);
|
||||
ih_entry_count(ih), from, del_count);
|
||||
|
||||
if (del_count == 0)
|
||||
return 0;
|
||||
|
@ -987,22 +1096,24 @@ static int leaf_cut_entries(struct buffer_head *bh,
|
|||
/* entry head array */
|
||||
deh = B_I_DEH(bh, ih);
|
||||
|
||||
/* first byte of remaining entries, those are BEFORE cut entries
|
||||
(prev_record) and length of all removed records (cut_records_len) */
|
||||
/*
|
||||
* first byte of remaining entries, those are BEFORE cut entries
|
||||
* (prev_record) and length of all removed records (cut_records_len)
|
||||
*/
|
||||
prev_record_offset =
|
||||
(from ? deh_location(&(deh[from - 1])) : ih_item_len(ih));
|
||||
(from ? deh_location(&deh[from - 1]) : ih_item_len(ih));
|
||||
cut_records_len = prev_record_offset /*from_record */ -
|
||||
deh_location(&(deh[from + del_count - 1]));
|
||||
deh_location(&deh[from + del_count - 1]);
|
||||
prev_record = item + prev_record_offset;
|
||||
|
||||
/* adjust locations of remaining entries */
|
||||
for (i = I_ENTRY_COUNT(ih) - 1; i > from + del_count - 1; i--)
|
||||
put_deh_location(&(deh[i]),
|
||||
for (i = ih_entry_count(ih) - 1; i > from + del_count - 1; i--)
|
||||
put_deh_location(&deh[i],
|
||||
deh_location(&deh[i]) -
|
||||
(DEH_SIZE * del_count));
|
||||
|
||||
for (i = 0; i < from; i++)
|
||||
put_deh_location(&(deh[i]),
|
||||
put_deh_location(&deh[i],
|
||||
deh_location(&deh[i]) - (DEH_SIZE * del_count +
|
||||
cut_records_len));
|
||||
|
||||
|
@ -1021,13 +1132,14 @@ static int leaf_cut_entries(struct buffer_head *bh,
|
|||
return DEH_SIZE * del_count + cut_records_len;
|
||||
}
|
||||
|
||||
/* when cut item is part of regular file
|
||||
pos_in_item - first byte that must be cut
|
||||
cut_size - number of bytes to be cut beginning from pos_in_item
|
||||
|
||||
when cut item is part of directory
|
||||
pos_in_item - number of first deleted entry
|
||||
cut_size - count of deleted entries
|
||||
/*
|
||||
* when cut item is part of regular file
|
||||
* pos_in_item - first byte that must be cut
|
||||
* cut_size - number of bytes to be cut beginning from pos_in_item
|
||||
*
|
||||
* when cut item is part of directory
|
||||
* pos_in_item - number of first deleted entry
|
||||
* cut_size - count of deleted entries
|
||||
*/
|
||||
void leaf_cut_from_buffer(struct buffer_info *bi, int cut_item_num,
|
||||
int pos_in_item, int cut_size)
|
||||
|
@ -1043,7 +1155,7 @@ void leaf_cut_from_buffer(struct buffer_info *bi, int cut_item_num,
|
|||
nr = blkh_nr_item(blkh);
|
||||
|
||||
/* item head of truncated item */
|
||||
ih = B_N_PITEM_HEAD(bh, cut_item_num);
|
||||
ih = item_head(bh, cut_item_num);
|
||||
|
||||
if (is_direntry_le_ih(ih)) {
|
||||
/* first cut entry () */
|
||||
|
@ -1055,7 +1167,6 @@ void leaf_cut_from_buffer(struct buffer_info *bi, int cut_item_num,
|
|||
cut_item_num);
|
||||
/* change item key by key of first entry in the item */
|
||||
set_le_ih_k_offset(ih, deh_offset(B_I_DEH(bh, ih)));
|
||||
/*memcpy (&ih->ih_key.k_offset, &(B_I_DEH (bh, ih)->deh_offset), SHORT_KEY_SIZE); */
|
||||
}
|
||||
} else {
|
||||
/* item is direct or indirect */
|
||||
|
@ -1089,7 +1200,7 @@ void leaf_cut_from_buffer(struct buffer_info *bi, int cut_item_num,
|
|||
}
|
||||
|
||||
/* location of the last item */
|
||||
last_loc = ih_location(&(ih[nr - cut_item_num - 1]));
|
||||
last_loc = ih_location(&ih[nr - cut_item_num - 1]);
|
||||
|
||||
/* location of the item, which is remaining at the same place */
|
||||
unmoved_loc = cut_item_num ? ih_location(ih - 1) : bh->b_size;
|
||||
|
@ -1108,7 +1219,7 @@ void leaf_cut_from_buffer(struct buffer_info *bi, int cut_item_num,
|
|||
|
||||
/* change locations */
|
||||
for (i = cut_item_num; i < nr; i++)
|
||||
put_ih_location(&(ih[i - cut_item_num]),
|
||||
put_ih_location(&ih[i - cut_item_num],
|
||||
ih_location(&ih[i - cut_item_num]) + cut_size);
|
||||
|
||||
/* size, free space */
|
||||
|
@ -1156,14 +1267,14 @@ static void leaf_delete_items_entirely(struct buffer_info *bi,
|
|||
return;
|
||||
}
|
||||
|
||||
ih = B_N_PITEM_HEAD(bh, first);
|
||||
ih = item_head(bh, first);
|
||||
|
||||
/* location of unmovable item */
|
||||
j = (first == 0) ? bh->b_size : ih_location(ih - 1);
|
||||
|
||||
/* delete items */
|
||||
last_loc = ih_location(&(ih[nr - 1 - first]));
|
||||
last_removed_loc = ih_location(&(ih[del_num - 1]));
|
||||
last_loc = ih_location(&ih[nr - 1 - first]);
|
||||
last_removed_loc = ih_location(&ih[del_num - 1]);
|
||||
|
||||
memmove(bh->b_data + last_loc + j - last_removed_loc,
|
||||
bh->b_data + last_loc, last_removed_loc - last_loc);
|
||||
|
@ -1173,8 +1284,8 @@ static void leaf_delete_items_entirely(struct buffer_info *bi,
|
|||
|
||||
/* change item location */
|
||||
for (i = first; i < nr - del_num; i++)
|
||||
put_ih_location(&(ih[i - first]),
|
||||
ih_location(&(ih[i - first])) + (j -
|
||||
put_ih_location(&ih[i - first],
|
||||
ih_location(&ih[i - first]) + (j -
|
||||
last_removed_loc));
|
||||
|
||||
/* sizes, item number */
|
||||
|
@ -1195,7 +1306,10 @@ static void leaf_delete_items_entirely(struct buffer_info *bi,
|
|||
}
|
||||
}
|
||||
|
||||
/* paste new_entry_count entries (new_dehs, records) into position before to item_num-th item */
|
||||
/*
|
||||
* paste new_entry_count entries (new_dehs, records) into position
|
||||
* before to item_num-th item
|
||||
*/
|
||||
void leaf_paste_entries(struct buffer_info *bi,
|
||||
int item_num,
|
||||
int before,
|
||||
|
@ -1213,13 +1327,16 @@ void leaf_paste_entries(struct buffer_info *bi,
|
|||
if (new_entry_count == 0)
|
||||
return;
|
||||
|
||||
ih = B_N_PITEM_HEAD(bh, item_num);
|
||||
ih = item_head(bh, item_num);
|
||||
|
||||
/* make sure, that item is directory, and there are enough records in it */
|
||||
/*
|
||||
* make sure, that item is directory, and there are enough
|
||||
* records in it
|
||||
*/
|
||||
RFALSE(!is_direntry_le_ih(ih), "10225: item is not directory item");
|
||||
RFALSE(I_ENTRY_COUNT(ih) < before,
|
||||
RFALSE(ih_entry_count(ih) < before,
|
||||
"10230: there are no entry we paste entries before. entry_count = %d, before = %d",
|
||||
I_ENTRY_COUNT(ih), before);
|
||||
ih_entry_count(ih), before);
|
||||
|
||||
/* first byte of dest item */
|
||||
item = bh->b_data + ih_location(ih);
|
||||
|
@ -1230,21 +1347,21 @@ void leaf_paste_entries(struct buffer_info *bi,
|
|||
/* new records will be pasted at this point */
|
||||
insert_point =
|
||||
item +
|
||||
(before ? deh_location(&(deh[before - 1]))
|
||||
(before ? deh_location(&deh[before - 1])
|
||||
: (ih_item_len(ih) - paste_size));
|
||||
|
||||
/* adjust locations of records that will be AFTER new records */
|
||||
for (i = I_ENTRY_COUNT(ih) - 1; i >= before; i--)
|
||||
put_deh_location(&(deh[i]),
|
||||
deh_location(&(deh[i])) +
|
||||
for (i = ih_entry_count(ih) - 1; i >= before; i--)
|
||||
put_deh_location(&deh[i],
|
||||
deh_location(&deh[i]) +
|
||||
(DEH_SIZE * new_entry_count));
|
||||
|
||||
/* adjust locations of records that will be BEFORE new records */
|
||||
for (i = 0; i < before; i++)
|
||||
put_deh_location(&(deh[i]),
|
||||
deh_location(&(deh[i])) + paste_size);
|
||||
put_deh_location(&deh[i],
|
||||
deh_location(&deh[i]) + paste_size);
|
||||
|
||||
old_entry_num = I_ENTRY_COUNT(ih);
|
||||
old_entry_num = ih_entry_count(ih);
|
||||
put_ih_entry_count(ih, ih_entry_count(ih) + new_entry_count);
|
||||
|
||||
/* prepare space for pasted records */
|
||||
|
@ -1266,10 +1383,10 @@ void leaf_paste_entries(struct buffer_info *bi,
|
|||
|
||||
/* set locations of new records */
|
||||
for (i = 0; i < new_entry_count; i++) {
|
||||
put_deh_location(&(deh[i]),
|
||||
deh_location(&(deh[i])) +
|
||||
put_deh_location(&deh[i],
|
||||
deh_location(&deh[i]) +
|
||||
(-deh_location
|
||||
(&(new_dehs[new_entry_count - 1])) +
|
||||
(&new_dehs[new_entry_count - 1]) +
|
||||
insert_point + DEH_SIZE * new_entry_count -
|
||||
item));
|
||||
}
|
||||
|
@ -1277,28 +1394,26 @@ void leaf_paste_entries(struct buffer_info *bi,
|
|||
/* change item key if necessary (when we paste before 0-th entry */
|
||||
if (!before) {
|
||||
set_le_ih_k_offset(ih, deh_offset(new_dehs));
|
||||
/* memcpy (&ih->ih_key.k_offset,
|
||||
&new_dehs->deh_offset, SHORT_KEY_SIZE);*/
|
||||
}
|
||||
#ifdef CONFIG_REISERFS_CHECK
|
||||
{
|
||||
int prev, next;
|
||||
/* check record locations */
|
||||
deh = B_I_DEH(bh, ih);
|
||||
for (i = 0; i < I_ENTRY_COUNT(ih); i++) {
|
||||
for (i = 0; i < ih_entry_count(ih); i++) {
|
||||
next =
|
||||
(i <
|
||||
I_ENTRY_COUNT(ih) -
|
||||
1) ? deh_location(&(deh[i + 1])) : 0;
|
||||
prev = (i != 0) ? deh_location(&(deh[i - 1])) : 0;
|
||||
ih_entry_count(ih) -
|
||||
1) ? deh_location(&deh[i + 1]) : 0;
|
||||
prev = (i != 0) ? deh_location(&deh[i - 1]) : 0;
|
||||
|
||||
if (prev && prev <= deh_location(&(deh[i])))
|
||||
if (prev && prev <= deh_location(&deh[i]))
|
||||
reiserfs_error(sb_from_bi(bi), "vs-10240",
|
||||
"directory item (%h) "
|
||||
"corrupted (prev %a, "
|
||||
"cur(%d) %a)",
|
||||
ih, deh + i - 1, i, deh + i);
|
||||
if (next && next >= deh_location(&(deh[i])))
|
||||
if (next && next >= deh_location(&deh[i]))
|
||||
reiserfs_error(sb_from_bi(bi), "vs-10250",
|
||||
"directory item (%h) "
|
||||
"corrupted (cur(%d) %a, "
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -7,7 +7,7 @@
|
|||
#include <linux/time.h>
|
||||
#include "reiserfs.h"
|
||||
|
||||
// find where objectid map starts
|
||||
/* find where objectid map starts */
|
||||
#define objectid_map(s,rs) (old_format_only (s) ? \
|
||||
(__le32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\
|
||||
(__le32 *)((rs) + 1))
|
||||
|
@ -20,7 +20,7 @@ static void check_objectid_map(struct super_block *s, __le32 * map)
|
|||
reiserfs_panic(s, "vs-15010", "map corrupted: %lx",
|
||||
(long unsigned int)le32_to_cpu(map[0]));
|
||||
|
||||
// FIXME: add something else here
|
||||
/* FIXME: add something else here */
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -29,19 +29,21 @@ static void check_objectid_map(struct super_block *s, __le32 * map)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* When we allocate objectids we allocate the first unused objectid.
|
||||
Each sequence of objectids in use (the odd sequences) is followed
|
||||
by a sequence of objectids not in use (the even sequences). We
|
||||
only need to record the last objectid in each of these sequences
|
||||
(both the odd and even sequences) in order to fully define the
|
||||
boundaries of the sequences. A consequence of allocating the first
|
||||
objectid not in use is that under most conditions this scheme is
|
||||
extremely compact. The exception is immediately after a sequence
|
||||
of operations which deletes a large number of objects of
|
||||
non-sequential objectids, and even then it will become compact
|
||||
again as soon as more objects are created. Note that many
|
||||
interesting optimizations of layout could result from complicating
|
||||
objectid assignment, but we have deferred making them for now. */
|
||||
/*
|
||||
* When we allocate objectids we allocate the first unused objectid.
|
||||
* Each sequence of objectids in use (the odd sequences) is followed
|
||||
* by a sequence of objectids not in use (the even sequences). We
|
||||
* only need to record the last objectid in each of these sequences
|
||||
* (both the odd and even sequences) in order to fully define the
|
||||
* boundaries of the sequences. A consequence of allocating the first
|
||||
* objectid not in use is that under most conditions this scheme is
|
||||
* extremely compact. The exception is immediately after a sequence
|
||||
* of operations which deletes a large number of objects of
|
||||
* non-sequential objectids, and even then it will become compact
|
||||
* again as soon as more objects are created. Note that many
|
||||
* interesting optimizations of layout could result from complicating
|
||||
* objectid assignment, but we have deferred making them for now.
|
||||
*/
|
||||
|
||||
/* get unique object identifier */
|
||||
__u32 reiserfs_get_unused_objectid(struct reiserfs_transaction_handle *th)
|
||||
|
@ -64,26 +66,30 @@ __u32 reiserfs_get_unused_objectid(struct reiserfs_transaction_handle *th)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* This incrementation allocates the first unused objectid. That
|
||||
is to say, the first entry on the objectid map is the first
|
||||
unused objectid, and by incrementing it we use it. See below
|
||||
where we check to see if we eliminated a sequence of unused
|
||||
objectids.... */
|
||||
/*
|
||||
* This incrementation allocates the first unused objectid. That
|
||||
* is to say, the first entry on the objectid map is the first
|
||||
* unused objectid, and by incrementing it we use it. See below
|
||||
* where we check to see if we eliminated a sequence of unused
|
||||
* objectids....
|
||||
*/
|
||||
map[1] = cpu_to_le32(unused_objectid + 1);
|
||||
|
||||
/* Now we check to see if we eliminated the last remaining member of
|
||||
the first even sequence (and can eliminate the sequence by
|
||||
eliminating its last objectid from oids), and can collapse the
|
||||
first two odd sequences into one sequence. If so, then the net
|
||||
result is to eliminate a pair of objectids from oids. We do this
|
||||
by shifting the entire map to the left. */
|
||||
/*
|
||||
* Now we check to see if we eliminated the last remaining member of
|
||||
* the first even sequence (and can eliminate the sequence by
|
||||
* eliminating its last objectid from oids), and can collapse the
|
||||
* first two odd sequences into one sequence. If so, then the net
|
||||
* result is to eliminate a pair of objectids from oids. We do this
|
||||
* by shifting the entire map to the left.
|
||||
*/
|
||||
if (sb_oid_cursize(rs) > 2 && map[1] == map[2]) {
|
||||
memmove(map + 1, map + 3,
|
||||
(sb_oid_cursize(rs) - 3) * sizeof(__u32));
|
||||
set_sb_oid_cursize(rs, sb_oid_cursize(rs) - 2);
|
||||
}
|
||||
|
||||
journal_mark_dirty(th, s, SB_BUFFER_WITH_SB(s));
|
||||
journal_mark_dirty(th, SB_BUFFER_WITH_SB(s));
|
||||
return unused_objectid;
|
||||
}
|
||||
|
||||
|
@ -97,30 +103,33 @@ void reiserfs_release_objectid(struct reiserfs_transaction_handle *th,
|
|||
int i = 0;
|
||||
|
||||
BUG_ON(!th->t_trans_id);
|
||||
//return;
|
||||
/*return; */
|
||||
check_objectid_map(s, map);
|
||||
|
||||
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
||||
journal_mark_dirty(th, s, SB_BUFFER_WITH_SB(s));
|
||||
journal_mark_dirty(th, SB_BUFFER_WITH_SB(s));
|
||||
|
||||
/* start at the beginning of the objectid map (i = 0) and go to
|
||||
the end of it (i = disk_sb->s_oid_cursize). Linear search is
|
||||
what we use, though it is possible that binary search would be
|
||||
more efficient after performing lots of deletions (which is
|
||||
when oids is large.) We only check even i's. */
|
||||
/*
|
||||
* start at the beginning of the objectid map (i = 0) and go to
|
||||
* the end of it (i = disk_sb->s_oid_cursize). Linear search is
|
||||
* what we use, though it is possible that binary search would be
|
||||
* more efficient after performing lots of deletions (which is
|
||||
* when oids is large.) We only check even i's.
|
||||
*/
|
||||
while (i < sb_oid_cursize(rs)) {
|
||||
if (objectid_to_release == le32_to_cpu(map[i])) {
|
||||
/* This incrementation unallocates the objectid. */
|
||||
//map[i]++;
|
||||
le32_add_cpu(&map[i], 1);
|
||||
|
||||
/* Did we unallocate the last member of an odd sequence, and can shrink oids? */
|
||||
/*
|
||||
* Did we unallocate the last member of an
|
||||
* odd sequence, and can shrink oids?
|
||||
*/
|
||||
if (map[i] == map[i + 1]) {
|
||||
/* shrink objectid map */
|
||||
memmove(map + i, map + i + 2,
|
||||
(sb_oid_cursize(rs) - i -
|
||||
2) * sizeof(__u32));
|
||||
//disk_sb->s_oid_cursize -= 2;
|
||||
set_sb_oid_cursize(rs, sb_oid_cursize(rs) - 2);
|
||||
|
||||
RFALSE(sb_oid_cursize(rs) < 2 ||
|
||||
|
@ -135,14 +144,19 @@ void reiserfs_release_objectid(struct reiserfs_transaction_handle *th,
|
|||
objectid_to_release < le32_to_cpu(map[i + 1])) {
|
||||
/* size of objectid map is not changed */
|
||||
if (objectid_to_release + 1 == le32_to_cpu(map[i + 1])) {
|
||||
//objectid_map[i+1]--;
|
||||
le32_add_cpu(&map[i + 1], -1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* JDM comparing two little-endian values for equality -- safe */
|
||||
/*
|
||||
* JDM comparing two little-endian values for
|
||||
* equality -- safe
|
||||
*/
|
||||
/*
|
||||
* objectid map must be expanded, but
|
||||
* there is no space
|
||||
*/
|
||||
if (sb_oid_cursize(rs) == sb_oid_maxsize(rs)) {
|
||||
/* objectid map must be expanded, but there is no space */
|
||||
PROC_INFO_INC(s, leaked_oid);
|
||||
return;
|
||||
}
|
||||
|
@ -178,8 +192,9 @@ int reiserfs_convert_objectid_map_v1(struct super_block *s)
|
|||
new_objectid_map = (__le32 *) (disk_sb + 1);
|
||||
|
||||
if (cur_size > new_size) {
|
||||
/* mark everyone used that was listed as free at the end of the objectid
|
||||
** map
|
||||
/*
|
||||
* mark everyone used that was listed as free at
|
||||
* the end of the objectid map
|
||||
*/
|
||||
objectid_map[new_size - 1] = objectid_map[cur_size - 1];
|
||||
set_sb_oid_cursize(disk_sb, new_size);
|
||||
|
|
|
@ -172,18 +172,19 @@ static char *is_there_reiserfs_struct(char *fmt, int *what)
|
|||
return k;
|
||||
}
|
||||
|
||||
/* debugging reiserfs we used to print out a lot of different
|
||||
variables, like keys, item headers, buffer heads etc. Values of
|
||||
most fields matter. So it took a long time just to write
|
||||
appropriative printk. With this reiserfs_warning you can use format
|
||||
specification for complex structures like you used to do with
|
||||
printfs for integers, doubles and pointers. For instance, to print
|
||||
out key structure you have to write just:
|
||||
reiserfs_warning ("bad key %k", key);
|
||||
instead of
|
||||
printk ("bad key %lu %lu %lu %lu", key->k_dir_id, key->k_objectid,
|
||||
key->k_offset, key->k_uniqueness);
|
||||
*/
|
||||
/*
|
||||
* debugging reiserfs we used to print out a lot of different
|
||||
* variables, like keys, item headers, buffer heads etc. Values of
|
||||
* most fields matter. So it took a long time just to write
|
||||
* appropriative printk. With this reiserfs_warning you can use format
|
||||
* specification for complex structures like you used to do with
|
||||
* printfs for integers, doubles and pointers. For instance, to print
|
||||
* out key structure you have to write just:
|
||||
* reiserfs_warning ("bad key %k", key);
|
||||
* instead of
|
||||
* printk ("bad key %lu %lu %lu %lu", key->k_dir_id, key->k_objectid,
|
||||
* key->k_offset, key->k_uniqueness);
|
||||
*/
|
||||
static DEFINE_SPINLOCK(error_lock);
|
||||
static void prepare_error_buf(const char *fmt, va_list args)
|
||||
{
|
||||
|
@ -243,15 +244,16 @@ static void prepare_error_buf(const char *fmt, va_list args)
|
|||
|
||||
}
|
||||
|
||||
/* in addition to usual conversion specifiers this accepts reiserfs
|
||||
specific conversion specifiers:
|
||||
%k to print little endian key,
|
||||
%K to print cpu key,
|
||||
%h to print item_head,
|
||||
%t to print directory entry
|
||||
%z to print block head (arg must be struct buffer_head *
|
||||
%b to print buffer_head
|
||||
*/
|
||||
/*
|
||||
* in addition to usual conversion specifiers this accepts reiserfs
|
||||
* specific conversion specifiers:
|
||||
* %k to print little endian key,
|
||||
* %K to print cpu key,
|
||||
* %h to print item_head,
|
||||
* %t to print directory entry
|
||||
* %z to print block head (arg must be struct buffer_head *
|
||||
* %b to print buffer_head
|
||||
*/
|
||||
|
||||
#define do_reiserfs_warning(fmt)\
|
||||
{\
|
||||
|
@ -304,50 +306,52 @@ void reiserfs_debug(struct super_block *s, int level, const char *fmt, ...)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* The format:
|
||||
|
||||
maintainer-errorid: [function-name:] message
|
||||
|
||||
where errorid is unique to the maintainer and function-name is
|
||||
optional, is recommended, so that anyone can easily find the bug
|
||||
with a simple grep for the short to type string
|
||||
maintainer-errorid. Don't bother with reusing errorids, there are
|
||||
lots of numbers out there.
|
||||
|
||||
Example:
|
||||
|
||||
reiserfs_panic(
|
||||
p_sb, "reiser-29: reiserfs_new_blocknrs: "
|
||||
"one of search_start or rn(%d) is equal to MAX_B_NUM,"
|
||||
"which means that we are optimizing location based on the bogus location of a temp buffer (%p).",
|
||||
rn, bh
|
||||
);
|
||||
|
||||
Regular panic()s sometimes clear the screen before the message can
|
||||
be read, thus the need for the while loop.
|
||||
|
||||
Numbering scheme for panic used by Vladimir and Anatoly( Hans completely ignores this scheme, and considers it
|
||||
pointless complexity):
|
||||
|
||||
panics in reiserfs.h have numbers from 1000 to 1999
|
||||
super.c 2000 to 2999
|
||||
preserve.c (unused) 3000 to 3999
|
||||
bitmap.c 4000 to 4999
|
||||
stree.c 5000 to 5999
|
||||
prints.c 6000 to 6999
|
||||
namei.c 7000 to 7999
|
||||
fix_nodes.c 8000 to 8999
|
||||
dir.c 9000 to 9999
|
||||
lbalance.c 10000 to 10999
|
||||
ibalance.c 11000 to 11999 not ready
|
||||
do_balan.c 12000 to 12999
|
||||
inode.c 13000 to 13999
|
||||
file.c 14000 to 14999
|
||||
objectid.c 15000 - 15999
|
||||
buffer.c 16000 - 16999
|
||||
symlink.c 17000 - 17999
|
||||
|
||||
. */
|
||||
/*
|
||||
* The format:
|
||||
*
|
||||
* maintainer-errorid: [function-name:] message
|
||||
*
|
||||
* where errorid is unique to the maintainer and function-name is
|
||||
* optional, is recommended, so that anyone can easily find the bug
|
||||
* with a simple grep for the short to type string
|
||||
* maintainer-errorid. Don't bother with reusing errorids, there are
|
||||
* lots of numbers out there.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* reiserfs_panic(
|
||||
* p_sb, "reiser-29: reiserfs_new_blocknrs: "
|
||||
* "one of search_start or rn(%d) is equal to MAX_B_NUM,"
|
||||
* "which means that we are optimizing location based on the "
|
||||
* "bogus location of a temp buffer (%p).",
|
||||
* rn, bh
|
||||
* );
|
||||
*
|
||||
* Regular panic()s sometimes clear the screen before the message can
|
||||
* be read, thus the need for the while loop.
|
||||
*
|
||||
* Numbering scheme for panic used by Vladimir and Anatoly( Hans completely
|
||||
* ignores this scheme, and considers it pointless complexity):
|
||||
*
|
||||
* panics in reiserfs_fs.h have numbers from 1000 to 1999
|
||||
* super.c 2000 to 2999
|
||||
* preserve.c (unused) 3000 to 3999
|
||||
* bitmap.c 4000 to 4999
|
||||
* stree.c 5000 to 5999
|
||||
* prints.c 6000 to 6999
|
||||
* namei.c 7000 to 7999
|
||||
* fix_nodes.c 8000 to 8999
|
||||
* dir.c 9000 to 9999
|
||||
* lbalance.c 10000 to 10999
|
||||
* ibalance.c 11000 to 11999 not ready
|
||||
* do_balan.c 12000 to 12999
|
||||
* inode.c 13000 to 13999
|
||||
* file.c 14000 to 14999
|
||||
* objectid.c 15000 - 15999
|
||||
* buffer.c 16000 - 16999
|
||||
* symlink.c 17000 - 17999
|
||||
*
|
||||
* . */
|
||||
|
||||
void __reiserfs_panic(struct super_block *sb, const char *id,
|
||||
const char *function, const char *fmt, ...)
|
||||
|
@ -411,9 +415,11 @@ void reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...)
|
|||
reiserfs_abort_journal(sb, errno);
|
||||
}
|
||||
|
||||
/* this prints internal nodes (4 keys/items in line) (dc_number,
|
||||
dc_size)[k_dirid, k_objectid, k_offset, k_uniqueness](dc_number,
|
||||
dc_size)...*/
|
||||
/*
|
||||
* this prints internal nodes (4 keys/items in line) (dc_number,
|
||||
* dc_size)[k_dirid, k_objectid, k_offset, k_uniqueness](dc_number,
|
||||
* dc_size)...
|
||||
*/
|
||||
static int print_internal(struct buffer_head *bh, int first, int last)
|
||||
{
|
||||
struct reiserfs_key *key;
|
||||
|
@ -439,7 +445,7 @@ static int print_internal(struct buffer_head *bh, int first, int last)
|
|||
dc = B_N_CHILD(bh, from);
|
||||
reiserfs_printk("PTR %d: %y ", from, dc);
|
||||
|
||||
for (i = from, key = B_N_PDELIM_KEY(bh, from), dc++; i < to;
|
||||
for (i = from, key = internal_key(bh, from), dc++; i < to;
|
||||
i++, key++, dc++) {
|
||||
reiserfs_printk("KEY %d: %k PTR %d: %y ", i, key, i + 1, dc);
|
||||
if (i && i % 4 == 0)
|
||||
|
@ -463,7 +469,7 @@ static int print_leaf(struct buffer_head *bh, int print_mode, int first,
|
|||
check_leaf(bh);
|
||||
|
||||
blkh = B_BLK_HEAD(bh);
|
||||
ih = B_N_PITEM_HEAD(bh, 0);
|
||||
ih = item_head(bh, 0);
|
||||
nr = blkh_nr_item(blkh);
|
||||
|
||||
printk
|
||||
|
@ -496,7 +502,7 @@ static int print_leaf(struct buffer_head *bh, int print_mode, int first,
|
|||
("-------------------------------------------------------------------------------\n");
|
||||
reiserfs_printk("|%2d| %h |\n", i, ih);
|
||||
if (print_mode & PRINT_LEAF_ITEMS)
|
||||
op_print_item(ih, B_I_PITEM(bh, ih));
|
||||
op_print_item(ih, ih_item_body(bh, ih));
|
||||
}
|
||||
|
||||
printk
|
||||
|
@ -543,9 +549,11 @@ static int print_super_block(struct buffer_head *bh)
|
|||
printk("Block count %u\n", sb_block_count(rs));
|
||||
printk("Blocksize %d\n", sb_blocksize(rs));
|
||||
printk("Free blocks %u\n", sb_free_blocks(rs));
|
||||
// FIXME: this would be confusing if
|
||||
// someone stores reiserfs super block in some data block ;)
|
||||
/*
|
||||
* FIXME: this would be confusing if
|
||||
* someone stores reiserfs super block in some data block ;)
|
||||
// skipped = (bh->b_blocknr * bh->b_size) / sb_blocksize(rs);
|
||||
*/
|
||||
skipped = bh->b_blocknr;
|
||||
data_blocks = sb_block_count(rs) - skipped - 1 - sb_bmap_nr(rs) -
|
||||
(!is_reiserfs_jr(rs) ? sb_jp_journal_size(rs) +
|
||||
|
@ -581,8 +589,8 @@ static int print_desc_block(struct buffer_head *bh)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_block(struct buffer_head *bh, ...) //int print_mode, int first, int last)
|
||||
/* ..., int print_mode, int first, int last) */
|
||||
void print_block(struct buffer_head *bh, ...)
|
||||
{
|
||||
va_list args;
|
||||
int mode, first, last;
|
||||
|
@ -644,11 +652,11 @@ void store_print_tb(struct tree_balance *tb)
|
|||
"* %d * %3lld(%2d) * %3lld(%2d) * %3lld(%2d) * %5lld * %5lld * %5lld * %5lld * %5lld *\n",
|
||||
h,
|
||||
(tbSh) ? (long long)(tbSh->b_blocknr) : (-1LL),
|
||||
(tbSh) ? atomic_read(&(tbSh->b_count)) : -1,
|
||||
(tbSh) ? atomic_read(&tbSh->b_count) : -1,
|
||||
(tb->L[h]) ? (long long)(tb->L[h]->b_blocknr) : (-1LL),
|
||||
(tb->L[h]) ? atomic_read(&(tb->L[h]->b_count)) : -1,
|
||||
(tb->L[h]) ? atomic_read(&tb->L[h]->b_count) : -1,
|
||||
(tb->R[h]) ? (long long)(tb->R[h]->b_blocknr) : (-1LL),
|
||||
(tb->R[h]) ? atomic_read(&(tb->R[h]->b_count)) : -1,
|
||||
(tb->R[h]) ? atomic_read(&tb->R[h]->b_count) : -1,
|
||||
(tbFh) ? (long long)(tbFh->b_blocknr) : (-1LL),
|
||||
(tb->FL[h]) ? (long long)(tb->FL[h]->
|
||||
b_blocknr) : (-1LL),
|
||||
|
@ -665,9 +673,9 @@ void store_print_tb(struct tree_balance *tb)
|
|||
"* h * size * ln * lb * rn * rb * blkn * s0 * s1 * s1b * s2 * s2b * curb * lk * rk *\n"
|
||||
"* 0 * %4d * %2d * %2d * %2d * %2d * %4d * %2d * %2d * %3d * %2d * %3d * %4d * %2d * %2d *\n",
|
||||
tb->insert_size[0], tb->lnum[0], tb->lbytes, tb->rnum[0],
|
||||
tb->rbytes, tb->blknum[0], tb->s0num, tb->s1num, tb->s1bytes,
|
||||
tb->s2num, tb->s2bytes, tb->cur_blknum, tb->lkey[0],
|
||||
tb->rkey[0]);
|
||||
tb->rbytes, tb->blknum[0], tb->s0num, tb->snum[0],
|
||||
tb->sbytes[0], tb->snum[1], tb->sbytes[1],
|
||||
tb->cur_blknum, tb->lkey[0], tb->rkey[0]);
|
||||
|
||||
/* this prints balance parameters for non-leaf levels */
|
||||
h = 0;
|
||||
|
@ -690,7 +698,7 @@ void store_print_tb(struct tree_balance *tb)
|
|||
"%p (%llu %d)%s", tb->FEB[i],
|
||||
tb->FEB[i] ? (unsigned long long)tb->FEB[i]->
|
||||
b_blocknr : 0ULL,
|
||||
tb->FEB[i] ? atomic_read(&(tb->FEB[i]->b_count)) : 0,
|
||||
tb->FEB[i] ? atomic_read(&tb->FEB[i]->b_count) : 0,
|
||||
(i == ARRAY_SIZE(tb->FEB) - 1) ? "\n" : ", ");
|
||||
|
||||
sprintf(print_tb_buf + strlen(print_tb_buf),
|
||||
|
@ -744,8 +752,8 @@ void check_leaf(struct buffer_head *bh)
|
|||
if (!bh)
|
||||
return;
|
||||
check_leaf_block_head(bh);
|
||||
for (i = 0, ih = B_N_PITEM_HEAD(bh, 0); i < B_NR_ITEMS(bh); i++, ih++)
|
||||
op_check_item(ih, B_I_PITEM(bh, ih));
|
||||
for (i = 0, ih = item_head(bh, 0); i < B_NR_ITEMS(bh); i++, ih++)
|
||||
op_check_item(ih, ih_item_body(bh, ih));
|
||||
}
|
||||
|
||||
void check_internal(struct buffer_head *bh)
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -53,8 +53,10 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
|
|||
}
|
||||
bforget(bh);
|
||||
|
||||
/* old disk layout detection; those partitions can be mounted, but
|
||||
* cannot be resized */
|
||||
/*
|
||||
* old disk layout detection; those partitions can be mounted, but
|
||||
* cannot be resized
|
||||
*/
|
||||
if (SB_BUFFER_WITH_SB(s)->b_blocknr * SB_BUFFER_WITH_SB(s)->b_size
|
||||
!= REISERFS_DISK_OFFSET_IN_BYTES) {
|
||||
printk
|
||||
|
@ -86,12 +88,14 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
|
|||
("reiserfs_resize: unable to allocate memory for journal bitmaps\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* the new journal bitmaps are zero filled, now we copy in the bitmap
|
||||
** node pointers from the old journal bitmap structs, and then
|
||||
** transfer the new data structures into the journal struct.
|
||||
**
|
||||
** using the copy_size var below allows this code to work for
|
||||
** both shrinking and expanding the FS.
|
||||
/*
|
||||
* the new journal bitmaps are zero filled, now we copy i
|
||||
* the bitmap node pointers from the old journal bitmap
|
||||
* structs, and then transfer the new data structures
|
||||
* into the journal struct.
|
||||
*
|
||||
* using the copy_size var below allows this code to work for
|
||||
* both shrinking and expanding the FS.
|
||||
*/
|
||||
copy_size = bmap_nr_new < bmap_nr ? bmap_nr_new : bmap_nr;
|
||||
copy_size =
|
||||
|
@ -101,36 +105,45 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
|
|||
jb = SB_JOURNAL(s)->j_list_bitmap + i;
|
||||
memcpy(jbitmap[i].bitmaps, jb->bitmaps, copy_size);
|
||||
|
||||
/* just in case vfree schedules on us, copy the new
|
||||
** pointer into the journal struct before freeing the
|
||||
** old one
|
||||
/*
|
||||
* just in case vfree schedules on us, copy the new
|
||||
* pointer into the journal struct before freeing the
|
||||
* old one
|
||||
*/
|
||||
node_tmp = jb->bitmaps;
|
||||
jb->bitmaps = jbitmap[i].bitmaps;
|
||||
vfree(node_tmp);
|
||||
}
|
||||
|
||||
/* allocate additional bitmap blocks, reallocate array of bitmap
|
||||
* block pointers */
|
||||
/*
|
||||
* allocate additional bitmap blocks, reallocate
|
||||
* array of bitmap block pointers
|
||||
*/
|
||||
bitmap =
|
||||
vzalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new);
|
||||
if (!bitmap) {
|
||||
/* Journal bitmaps are still supersized, but the memory isn't
|
||||
* leaked, so I guess it's ok */
|
||||
/*
|
||||
* Journal bitmaps are still supersized, but the
|
||||
* memory isn't leaked, so I guess it's ok
|
||||
*/
|
||||
printk("reiserfs_resize: unable to allocate memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (i = 0; i < bmap_nr; i++)
|
||||
bitmap[i] = old_bitmap[i];
|
||||
|
||||
/* This doesn't go through the journal, but it doesn't have to.
|
||||
* The changes are still atomic: We're synced up when the journal
|
||||
* transaction begins, and the new bitmaps don't matter if the
|
||||
* transaction fails. */
|
||||
/*
|
||||
* This doesn't go through the journal, but it doesn't have to.
|
||||
* The changes are still atomic: We're synced up when the
|
||||
* journal transaction begins, and the new bitmaps don't
|
||||
* matter if the transaction fails.
|
||||
*/
|
||||
for (i = bmap_nr; i < bmap_nr_new; i++) {
|
||||
int depth;
|
||||
/* don't use read_bitmap_block since it will cache
|
||||
* the uninitialized bitmap */
|
||||
/*
|
||||
* don't use read_bitmap_block since it will cache
|
||||
* the uninitialized bitmap
|
||||
*/
|
||||
depth = reiserfs_write_unlock_nested(s);
|
||||
bh = sb_bread(s, i * s->s_blocksize * 8);
|
||||
reiserfs_write_lock_nested(s, depth);
|
||||
|
@ -147,7 +160,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
|
|||
depth = reiserfs_write_unlock_nested(s);
|
||||
sync_dirty_buffer(bh);
|
||||
reiserfs_write_lock_nested(s, depth);
|
||||
// update bitmap_info stuff
|
||||
/* update bitmap_info stuff */
|
||||
bitmap[i].free_count = sb_blocksize(sb) * 8 - 1;
|
||||
brelse(bh);
|
||||
}
|
||||
|
@ -156,9 +169,11 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
|
|||
vfree(old_bitmap);
|
||||
}
|
||||
|
||||
/* begin transaction, if there was an error, it's fine. Yes, we have
|
||||
/*
|
||||
* begin transaction, if there was an error, it's fine. Yes, we have
|
||||
* incorrect bitmaps now, but none of it is ever going to touch the
|
||||
* disk anyway. */
|
||||
* disk anyway.
|
||||
*/
|
||||
err = journal_begin(&th, s, 10);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -167,7 +182,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
|
|||
info = SB_AP_BITMAP(s) + bmap_nr - 1;
|
||||
bh = reiserfs_read_bitmap_block(s, bmap_nr - 1);
|
||||
if (!bh) {
|
||||
int jerr = journal_end(&th, s, 10);
|
||||
int jerr = journal_end(&th);
|
||||
if (jerr)
|
||||
return jerr;
|
||||
return -EIO;
|
||||
|
@ -178,14 +193,14 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
|
|||
reiserfs_clear_le_bit(i, bh->b_data);
|
||||
info->free_count += s->s_blocksize * 8 - block_r;
|
||||
|
||||
journal_mark_dirty(&th, s, bh);
|
||||
journal_mark_dirty(&th, bh);
|
||||
brelse(bh);
|
||||
|
||||
/* Correct new last bitmap block - It may not be full */
|
||||
info = SB_AP_BITMAP(s) + bmap_nr_new - 1;
|
||||
bh = reiserfs_read_bitmap_block(s, bmap_nr_new - 1);
|
||||
if (!bh) {
|
||||
int jerr = journal_end(&th, s, 10);
|
||||
int jerr = journal_end(&th);
|
||||
if (jerr)
|
||||
return jerr;
|
||||
return -EIO;
|
||||
|
@ -194,7 +209,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
|
|||
reiserfs_prepare_for_journal(s, bh, 1);
|
||||
for (i = block_r_new; i < s->s_blocksize * 8; i++)
|
||||
reiserfs_set_le_bit(i, bh->b_data);
|
||||
journal_mark_dirty(&th, s, bh);
|
||||
journal_mark_dirty(&th, bh);
|
||||
brelse(bh);
|
||||
|
||||
info->free_count -= s->s_blocksize * 8 - block_r_new;
|
||||
|
@ -207,8 +222,8 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
|
|||
PUT_SB_BLOCK_COUNT(s, block_count_new);
|
||||
PUT_SB_BMAP_NR(s, bmap_would_wrap(bmap_nr_new) ? : bmap_nr_new);
|
||||
|
||||
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
|
||||
journal_mark_dirty(&th, SB_BUFFER_WITH_SB(s));
|
||||
|
||||
SB_JOURNAL(s)->j_must_wait = 1;
|
||||
return journal_end(&th, s, 10);
|
||||
return journal_end(&th);
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -74,7 +74,7 @@ static int reiserfs_sync_fs(struct super_block *s, int wait)
|
|||
dquot_writeback_dquots(s, -1);
|
||||
reiserfs_write_lock(s);
|
||||
if (!journal_begin(&th, s, 1))
|
||||
if (!journal_end_sync(&th, s, 1))
|
||||
if (!journal_end_sync(&th))
|
||||
reiserfs_flush_old_commits(s);
|
||||
reiserfs_write_unlock(s);
|
||||
return 0;
|
||||
|
@ -136,9 +136,9 @@ static int reiserfs_freeze(struct super_block *s)
|
|||
} else {
|
||||
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s),
|
||||
1);
|
||||
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
|
||||
journal_mark_dirty(&th, SB_BUFFER_WITH_SB(s));
|
||||
reiserfs_block_writes(&th);
|
||||
journal_end_sync(&th, s, 1);
|
||||
journal_end_sync(&th);
|
||||
}
|
||||
}
|
||||
reiserfs_write_unlock(s);
|
||||
|
@ -153,13 +153,15 @@ static int reiserfs_unfreeze(struct super_block *s)
|
|||
|
||||
extern const struct in_core_key MAX_IN_CORE_KEY;
|
||||
|
||||
/* this is used to delete "save link" when there are no items of a
|
||||
file it points to. It can either happen if unlink is completed but
|
||||
"save unlink" removal, or if file has both unlink and truncate
|
||||
pending and as unlink completes first (because key of "save link"
|
||||
protecting unlink is bigger that a key lf "save link" which
|
||||
protects truncate), so there left no items to make truncate
|
||||
completion on */
|
||||
/*
|
||||
* this is used to delete "save link" when there are no items of a
|
||||
* file it points to. It can either happen if unlink is completed but
|
||||
* "save unlink" removal, or if file has both unlink and truncate
|
||||
* pending and as unlink completes first (because key of "save link"
|
||||
* protecting unlink is bigger that a key lf "save link" which
|
||||
* protects truncate), so there left no items to make truncate
|
||||
* completion on
|
||||
*/
|
||||
static int remove_save_link_only(struct super_block *s,
|
||||
struct reiserfs_key *key, int oid_free)
|
||||
{
|
||||
|
@ -176,7 +178,7 @@ static int remove_save_link_only(struct super_block *s,
|
|||
/* removals are protected by direct items */
|
||||
reiserfs_release_objectid(&th, le32_to_cpu(key->k_objectid));
|
||||
|
||||
return journal_end(&th, s, JOURNAL_PER_BALANCE_CNT);
|
||||
return journal_end(&th);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_QUOTA
|
||||
|
@ -258,7 +260,7 @@ static int finish_unfinished(struct super_block *s)
|
|||
break;
|
||||
}
|
||||
item_pos--;
|
||||
ih = B_N_PITEM_HEAD(bh, item_pos);
|
||||
ih = item_head(bh, item_pos);
|
||||
|
||||
if (le32_to_cpu(ih->ih_key.k_dir_id) != MAX_KEY_OBJECTID)
|
||||
/* there are no "save" links anymore */
|
||||
|
@ -271,7 +273,7 @@ static int finish_unfinished(struct super_block *s)
|
|||
truncate = 0;
|
||||
|
||||
/* reiserfs_iget needs k_dirid and k_objectid only */
|
||||
item = B_I_PITEM(bh, ih);
|
||||
item = ih_item_body(bh, ih);
|
||||
obj_key.on_disk_key.k_dir_id = le32_to_cpu(*(__le32 *) item);
|
||||
obj_key.on_disk_key.k_objectid =
|
||||
le32_to_cpu(ih->ih_key.k_objectid);
|
||||
|
@ -282,8 +284,10 @@ static int finish_unfinished(struct super_block *s)
|
|||
|
||||
inode = reiserfs_iget(s, &obj_key);
|
||||
if (!inode) {
|
||||
/* the unlink almost completed, it just did not manage to remove
|
||||
"save" link and release objectid */
|
||||
/*
|
||||
* the unlink almost completed, it just did not
|
||||
* manage to remove "save" link and release objectid
|
||||
*/
|
||||
reiserfs_warning(s, "vs-2180", "iget failed for %K",
|
||||
&obj_key);
|
||||
retval = remove_save_link_only(s, &save_link_key, 1);
|
||||
|
@ -303,10 +307,13 @@ static int finish_unfinished(struct super_block *s)
|
|||
reiserfs_write_lock_nested(inode->i_sb, depth);
|
||||
|
||||
if (truncate && S_ISDIR(inode->i_mode)) {
|
||||
/* We got a truncate request for a dir which is impossible.
|
||||
The only imaginable way is to execute unfinished truncate request
|
||||
then boot into old kernel, remove the file and create dir with
|
||||
the same key. */
|
||||
/*
|
||||
* We got a truncate request for a dir which
|
||||
* is impossible. The only imaginable way is to
|
||||
* execute unfinished truncate request then boot
|
||||
* into old kernel, remove the file and create dir
|
||||
* with the same key.
|
||||
*/
|
||||
reiserfs_warning(s, "green-2101",
|
||||
"impossible truncate on a "
|
||||
"directory %k. Please report",
|
||||
|
@ -320,14 +327,16 @@ static int finish_unfinished(struct super_block *s)
|
|||
if (truncate) {
|
||||
REISERFS_I(inode)->i_flags |=
|
||||
i_link_saved_truncate_mask;
|
||||
/* not completed truncate found. New size was committed together
|
||||
with "save" link */
|
||||
/*
|
||||
* not completed truncate found. New size was
|
||||
* committed together with "save" link
|
||||
*/
|
||||
reiserfs_info(s, "Truncating %k to %Ld ..",
|
||||
INODE_PKEY(inode), inode->i_size);
|
||||
reiserfs_truncate_file(inode,
|
||||
0
|
||||
/*don't update modification time */
|
||||
);
|
||||
|
||||
/* don't update modification time */
|
||||
reiserfs_truncate_file(inode, 0);
|
||||
|
||||
retval = remove_save_link(inode, truncate);
|
||||
} else {
|
||||
REISERFS_I(inode)->i_flags |= i_link_saved_unlink_mask;
|
||||
|
@ -373,10 +382,12 @@ static int finish_unfinished(struct super_block *s)
|
|||
return retval;
|
||||
}
|
||||
|
||||
/* to protect file being unlinked from getting lost we "safe" link files
|
||||
being unlinked. This link will be deleted in the same transaction with last
|
||||
item of file. mounting the filesystem we scan all these links and remove
|
||||
files which almost got lost */
|
||||
/*
|
||||
* to protect file being unlinked from getting lost we "safe" link files
|
||||
* being unlinked. This link will be deleted in the same transaction with last
|
||||
* item of file. mounting the filesystem we scan all these links and remove
|
||||
* files which almost got lost
|
||||
*/
|
||||
void add_save_link(struct reiserfs_transaction_handle *th,
|
||||
struct inode *inode, int truncate)
|
||||
{
|
||||
|
@ -495,7 +506,7 @@ int remove_save_link(struct inode *inode, int truncate)
|
|||
} else
|
||||
REISERFS_I(inode)->i_flags &= ~i_link_saved_truncate_mask;
|
||||
|
||||
return journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT);
|
||||
return journal_end(&th);
|
||||
}
|
||||
|
||||
static void reiserfs_kill_sb(struct super_block *s)
|
||||
|
@ -530,19 +541,23 @@ static void reiserfs_put_super(struct super_block *s)
|
|||
|
||||
reiserfs_write_lock(s);
|
||||
|
||||
/* change file system state to current state if it was mounted with read-write permissions */
|
||||
/*
|
||||
* change file system state to current state if it was mounted
|
||||
* with read-write permissions
|
||||
*/
|
||||
if (!(s->s_flags & MS_RDONLY)) {
|
||||
if (!journal_begin(&th, s, 10)) {
|
||||
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s),
|
||||
1);
|
||||
set_sb_umount_state(SB_DISK_SUPER_BLOCK(s),
|
||||
REISERFS_SB(s)->s_mount_state);
|
||||
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
|
||||
journal_mark_dirty(&th, SB_BUFFER_WITH_SB(s));
|
||||
}
|
||||
}
|
||||
|
||||
/* note, journal_release checks for readonly mount, and can decide not
|
||||
** to do a journal_end
|
||||
/*
|
||||
* note, journal_release checks for readonly mount, and can
|
||||
* decide not to do a journal_end
|
||||
*/
|
||||
journal_release(&th, s);
|
||||
|
||||
|
@ -559,6 +574,7 @@ static void reiserfs_put_super(struct super_block *s)
|
|||
|
||||
reiserfs_write_unlock(s);
|
||||
mutex_destroy(&REISERFS_SB(s)->lock);
|
||||
destroy_workqueue(REISERFS_SB(s)->commit_wq);
|
||||
kfree(s->s_fs_info);
|
||||
s->s_fs_info = NULL;
|
||||
}
|
||||
|
@ -634,15 +650,16 @@ static void reiserfs_dirty_inode(struct inode *inode, int flags)
|
|||
}
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
|
||||
/* this is really only used for atime updates, so they don't have
|
||||
** to be included in O_SYNC or fsync
|
||||
/*
|
||||
* this is really only used for atime updates, so they don't have
|
||||
* to be included in O_SYNC or fsync
|
||||
*/
|
||||
err = journal_begin(&th, inode->i_sb, 1);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
reiserfs_update_sd(&th, inode);
|
||||
journal_end(&th, inode->i_sb, 1);
|
||||
journal_end(&th);
|
||||
|
||||
out:
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
|
@ -788,31 +805,53 @@ static const struct export_operations reiserfs_export_ops = {
|
|||
.get_parent = reiserfs_get_parent,
|
||||
};
|
||||
|
||||
/* this struct is used in reiserfs_getopt () for containing the value for those
|
||||
mount options that have values rather than being toggles. */
|
||||
/*
|
||||
* this struct is used in reiserfs_getopt () for containing the value for
|
||||
* those mount options that have values rather than being toggles.
|
||||
*/
|
||||
typedef struct {
|
||||
char *value;
|
||||
int setmask; /* bitmask which is to set on mount_options bitmask when this
|
||||
value is found, 0 is no bits are to be changed. */
|
||||
int clrmask; /* bitmask which is to clear on mount_options bitmask when this
|
||||
value is found, 0 is no bits are to be changed. This is
|
||||
applied BEFORE setmask */
|
||||
/*
|
||||
* bitmask which is to set on mount_options bitmask
|
||||
* when this value is found, 0 is no bits are to be changed.
|
||||
*/
|
||||
int setmask;
|
||||
/*
|
||||
* bitmask which is to clear on mount_options bitmask
|
||||
* when this value is found, 0 is no bits are to be changed.
|
||||
* This is applied BEFORE setmask
|
||||
*/
|
||||
int clrmask;
|
||||
} arg_desc_t;
|
||||
|
||||
/* Set this bit in arg_required to allow empty arguments */
|
||||
#define REISERFS_OPT_ALLOWEMPTY 31
|
||||
|
||||
/* this struct is used in reiserfs_getopt() for describing the set of reiserfs
|
||||
mount options */
|
||||
/*
|
||||
* this struct is used in reiserfs_getopt() for describing the
|
||||
* set of reiserfs mount options
|
||||
*/
|
||||
typedef struct {
|
||||
char *option_name;
|
||||
int arg_required; /* 0 if argument is not required, not 0 otherwise */
|
||||
const arg_desc_t *values; /* list of values accepted by an option */
|
||||
int setmask; /* bitmask which is to set on mount_options bitmask when this
|
||||
value is found, 0 is no bits are to be changed. */
|
||||
int clrmask; /* bitmask which is to clear on mount_options bitmask when this
|
||||
value is found, 0 is no bits are to be changed. This is
|
||||
applied BEFORE setmask */
|
||||
|
||||
/* 0 if argument is not required, not 0 otherwise */
|
||||
int arg_required;
|
||||
|
||||
/* list of values accepted by an option */
|
||||
const arg_desc_t *values;
|
||||
|
||||
/*
|
||||
* bitmask which is to set on mount_options bitmask
|
||||
* when this value is found, 0 is no bits are to be changed.
|
||||
*/
|
||||
int setmask;
|
||||
|
||||
/*
|
||||
* bitmask which is to clear on mount_options bitmask
|
||||
* when this value is found, 0 is no bits are to be changed.
|
||||
* This is applied BEFORE setmask
|
||||
*/
|
||||
int clrmask;
|
||||
} opt_desc_t;
|
||||
|
||||
/* possible values for -o data= */
|
||||
|
@ -833,8 +872,10 @@ static const arg_desc_t barrier_mode[] = {
|
|||
{.value = NULL}
|
||||
};
|
||||
|
||||
/* possible values for "-o block-allocator=" and bits which are to be set in
|
||||
s_mount_opt of reiserfs specific part of in-core super block */
|
||||
/*
|
||||
* possible values for "-o block-allocator=" and bits which are to be set in
|
||||
* s_mount_opt of reiserfs specific part of in-core super block
|
||||
*/
|
||||
static const arg_desc_t balloc[] = {
|
||||
{"noborder", 1 << REISERFS_NO_BORDER, 0},
|
||||
{"border", 0, 1 << REISERFS_NO_BORDER},
|
||||
|
@ -864,21 +905,25 @@ static const arg_desc_t error_actions[] = {
|
|||
{NULL, 0, 0},
|
||||
};
|
||||
|
||||
/* proceed only one option from a list *cur - string containing of mount options
|
||||
opts - array of options which are accepted
|
||||
opt_arg - if option is found and requires an argument and if it is specifed
|
||||
in the input - pointer to the argument is stored here
|
||||
bit_flags - if option requires to set a certain bit - it is set here
|
||||
return -1 if unknown option is found, opt->arg_required otherwise */
|
||||
/*
|
||||
* proceed only one option from a list *cur - string containing of mount
|
||||
* options
|
||||
* opts - array of options which are accepted
|
||||
* opt_arg - if option is found and requires an argument and if it is specifed
|
||||
* in the input - pointer to the argument is stored here
|
||||
* bit_flags - if option requires to set a certain bit - it is set here
|
||||
* return -1 if unknown option is found, opt->arg_required otherwise
|
||||
*/
|
||||
static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
|
||||
char **opt_arg, unsigned long *bit_flags)
|
||||
{
|
||||
char *p;
|
||||
/* foo=bar,
|
||||
^ ^ ^
|
||||
| | +-- option_end
|
||||
| +-- arg_start
|
||||
+-- option_start
|
||||
/*
|
||||
* foo=bar,
|
||||
* ^ ^ ^
|
||||
* | | +-- option_end
|
||||
* | +-- arg_start
|
||||
* +-- option_start
|
||||
*/
|
||||
const opt_desc_t *opt;
|
||||
const arg_desc_t *arg;
|
||||
|
@ -893,9 +938,12 @@ static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
|
|||
}
|
||||
|
||||
if (!strncmp(p, "alloc=", 6)) {
|
||||
/* Ugly special case, probably we should redo options parser so that
|
||||
it can understand several arguments for some options, also so that
|
||||
it can fill several bitfields with option values. */
|
||||
/*
|
||||
* Ugly special case, probably we should redo options
|
||||
* parser so that it can understand several arguments for
|
||||
* some options, also so that it can fill several bitfields
|
||||
* with option values.
|
||||
*/
|
||||
if (reiserfs_parse_alloc_options(s, p + 6)) {
|
||||
return -1;
|
||||
} else {
|
||||
|
@ -958,7 +1006,10 @@ static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* move to the argument, or to next option if argument is not required */
|
||||
/*
|
||||
* move to the argument, or to next option if argument is not
|
||||
* required
|
||||
*/
|
||||
p++;
|
||||
|
||||
if (opt->arg_required
|
||||
|
@ -995,12 +1046,20 @@ static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
|
|||
}
|
||||
|
||||
/* returns 0 if something is wrong in option string, 1 - otherwise */
|
||||
static int reiserfs_parse_options(struct super_block *s, char *options, /* string given via mount's -o */
|
||||
static int reiserfs_parse_options(struct super_block *s,
|
||||
|
||||
/* string given via mount's -o */
|
||||
char *options,
|
||||
|
||||
/*
|
||||
* after the parsing phase, contains the
|
||||
* collection of bitflags defining what
|
||||
* mount options were selected.
|
||||
*/
|
||||
unsigned long *mount_options,
|
||||
/* after the parsing phase, contains the
|
||||
collection of bitflags defining what
|
||||
mount options were selected. */
|
||||
unsigned long *blocks, /* strtol-ed from NNN of resize=NNN */
|
||||
|
||||
/* strtol-ed from NNN of resize=NNN */
|
||||
unsigned long *blocks,
|
||||
char **jdev_name,
|
||||
unsigned int *commit_max_age,
|
||||
char **qf_names,
|
||||
|
@ -1010,7 +1069,10 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
|
|||
char *arg = NULL;
|
||||
char *pos;
|
||||
opt_desc_t opts[] = {
|
||||
/* Compatibility stuff, so that -o notail for old setups still work */
|
||||
/*
|
||||
* Compatibility stuff, so that -o notail for old
|
||||
* setups still work
|
||||
*/
|
||||
{"tails",.arg_required = 't',.values = tails},
|
||||
{"notail",.clrmask =
|
||||
(1 << REISERFS_LARGETAIL) | (1 << REISERFS_SMALLTAIL)},
|
||||
|
@ -1055,8 +1117,10 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
|
|||
|
||||
*blocks = 0;
|
||||
if (!options || !*options)
|
||||
/* use default configuration: create tails, journaling on, no
|
||||
conversion to newest format */
|
||||
/*
|
||||
* use default configuration: create tails, journaling on, no
|
||||
* conversion to newest format
|
||||
*/
|
||||
return 1;
|
||||
|
||||
for (pos = options; pos;) {
|
||||
|
@ -1109,7 +1173,8 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
|
|||
|
||||
if (c == 'j') {
|
||||
if (arg && *arg && jdev_name) {
|
||||
if (*jdev_name) { //Hm, already assigned?
|
||||
/* Hm, already assigned? */
|
||||
if (*jdev_name) {
|
||||
reiserfs_warning(s, "super-6510",
|
||||
"journal device was "
|
||||
"already specified to "
|
||||
|
@ -1362,8 +1427,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||
safe_mask |= 1 << REISERFS_USRQUOTA;
|
||||
safe_mask |= 1 << REISERFS_GRPQUOTA;
|
||||
|
||||
/* Update the bitmask, taking care to keep
|
||||
* the bits we're not allowed to change here */
|
||||
/*
|
||||
* Update the bitmask, taking care to keep
|
||||
* the bits we're not allowed to change here
|
||||
*/
|
||||
REISERFS_SB(s)->s_mount_opt =
|
||||
(REISERFS_SB(s)->
|
||||
s_mount_opt & ~safe_mask) | (mount_options & safe_mask);
|
||||
|
@ -1410,7 +1477,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||
/* Mounting a rw partition read-only. */
|
||||
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
||||
set_sb_umount_state(rs, REISERFS_SB(s)->s_mount_state);
|
||||
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
|
||||
journal_mark_dirty(&th, SB_BUFFER_WITH_SB(s));
|
||||
} else {
|
||||
/* remount read-write */
|
||||
if (!(s->s_flags & MS_RDONLY)) {
|
||||
|
@ -1427,7 +1494,9 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||
handle_data_mode(s, mount_options);
|
||||
handle_barrier_mode(s, mount_options);
|
||||
REISERFS_SB(s)->s_mount_state = sb_umount_state(rs);
|
||||
s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */
|
||||
|
||||
/* now it is safe to call journal_begin */
|
||||
s->s_flags &= ~MS_RDONLY;
|
||||
err = journal_begin(&th, s, 10);
|
||||
if (err)
|
||||
goto out_err_unlock;
|
||||
|
@ -1440,12 +1509,12 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||
if (!old_format_only(s))
|
||||
set_sb_mnt_count(rs, sb_mnt_count(rs) + 1);
|
||||
/* mark_buffer_dirty (SB_BUFFER_WITH_SB (s), 1); */
|
||||
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
|
||||
journal_mark_dirty(&th, SB_BUFFER_WITH_SB(s));
|
||||
REISERFS_SB(s)->s_mount_state = REISERFS_VALID_FS;
|
||||
}
|
||||
/* this will force a full flush of all journal lists */
|
||||
SB_JOURNAL(s)->j_must_wait = 1;
|
||||
err = journal_end(&th, s, 10);
|
||||
err = journal_end(&th);
|
||||
if (err)
|
||||
goto out_err_unlock;
|
||||
|
||||
|
@ -1489,9 +1558,9 @@ static int read_super_block(struct super_block *s, int offset)
|
|||
brelse(bh);
|
||||
return 1;
|
||||
}
|
||||
//
|
||||
// ok, reiserfs signature (old or new) found in at the given offset
|
||||
//
|
||||
/*
|
||||
* ok, reiserfs signature (old or new) found in at the given offset
|
||||
*/
|
||||
fs_blocksize = sb_blocksize(rs);
|
||||
brelse(bh);
|
||||
sb_set_blocksize(s, fs_blocksize);
|
||||
|
@ -1529,9 +1598,11 @@ static int read_super_block(struct super_block *s, int offset)
|
|||
SB_BUFFER_WITH_SB(s) = bh;
|
||||
SB_DISK_SUPER_BLOCK(s) = rs;
|
||||
|
||||
/*
|
||||
* magic is of non-standard journal filesystem, look at s_version to
|
||||
* find which format is in use
|
||||
*/
|
||||
if (is_reiserfs_jr(rs)) {
|
||||
/* magic is of non-standard journal filesystem, look at s_version to
|
||||
find which format is in use */
|
||||
if (sb_version(rs) == REISERFS_VERSION_2)
|
||||
reiserfs_info(s, "found reiserfs format \"3.6\""
|
||||
" with non-standard journal\n");
|
||||
|
@ -1545,8 +1616,10 @@ static int read_super_block(struct super_block *s, int offset)
|
|||
return 1;
|
||||
}
|
||||
} else
|
||||
/* s_version of standard format may contain incorrect information,
|
||||
so we just look at the magic string */
|
||||
/*
|
||||
* s_version of standard format may contain incorrect
|
||||
* information, so we just look at the magic string
|
||||
*/
|
||||
reiserfs_info(s,
|
||||
"found reiserfs format \"%s\" with standard journal\n",
|
||||
is_reiserfs_3_5(rs) ? "3.5" : "3.6");
|
||||
|
@ -1558,8 +1631,9 @@ static int read_super_block(struct super_block *s, int offset)
|
|||
s->dq_op = &reiserfs_quota_operations;
|
||||
#endif
|
||||
|
||||
/* new format is limited by the 32 bit wide i_blocks field, want to
|
||||
** be one full block below that.
|
||||
/*
|
||||
* new format is limited by the 32 bit wide i_blocks field, want to
|
||||
* be one full block below that.
|
||||
*/
|
||||
s->s_maxbytes = (512LL << 32) - s->s_blocksize;
|
||||
return 0;
|
||||
|
@ -1568,7 +1642,7 @@ static int read_super_block(struct super_block *s, int offset)
|
|||
/* after journal replay, reread all bitmap and super blocks */
|
||||
static int reread_meta_blocks(struct super_block *s)
|
||||
{
|
||||
ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s)));
|
||||
ll_rw_block(READ, 1, &SB_BUFFER_WITH_SB(s));
|
||||
wait_on_buffer(SB_BUFFER_WITH_SB(s));
|
||||
if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
|
||||
reiserfs_warning(s, "reiserfs-2504", "error reading the super");
|
||||
|
@ -1578,14 +1652,15 @@ static int reread_meta_blocks(struct super_block *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// hash detection stuff
|
||||
/* hash detection stuff */
|
||||
|
||||
// if root directory is empty - we set default - Yura's - hash and
|
||||
// warn about it
|
||||
// FIXME: we look for only one name in a directory. If tea and yura
|
||||
// bith have the same value - we ask user to send report to the
|
||||
// mailing list
|
||||
/*
|
||||
* if root directory is empty - we set default - Yura's - hash and
|
||||
* warn about it
|
||||
* FIXME: we look for only one name in a directory. If tea and yura
|
||||
* both have the same value - we ask user to send report to the
|
||||
* mailing list
|
||||
*/
|
||||
static __u32 find_hash_out(struct super_block *s)
|
||||
{
|
||||
int retval;
|
||||
|
@ -1593,13 +1668,12 @@ static __u32 find_hash_out(struct super_block *s)
|
|||
struct cpu_key key;
|
||||
INITIALIZE_PATH(path);
|
||||
struct reiserfs_dir_entry de;
|
||||
struct reiserfs_de_head *deh;
|
||||
__u32 hash = DEFAULT_HASH;
|
||||
__u32 deh_hashval, teahash, r5hash, yurahash;
|
||||
|
||||
inode = s->s_root->d_inode;
|
||||
|
||||
do { // Some serious "goto"-hater was there ;)
|
||||
u32 teahash, r5hash, yurahash;
|
||||
|
||||
make_cpu_key(&key, inode, ~0, TYPE_DIRENTRY, 3);
|
||||
retval = search_by_entry_key(s, &key, &path, &de);
|
||||
if (retval == IO_ERROR) {
|
||||
|
@ -1608,77 +1682,69 @@ static __u32 find_hash_out(struct super_block *s)
|
|||
}
|
||||
if (retval == NAME_NOT_FOUND)
|
||||
de.de_entry_num--;
|
||||
|
||||
set_de_name_and_namelen(&de);
|
||||
if (deh_offset(&(de.de_deh[de.de_entry_num])) == DOT_DOT_OFFSET) {
|
||||
deh = de.de_deh + de.de_entry_num;
|
||||
|
||||
if (deh_offset(deh) == DOT_DOT_OFFSET) {
|
||||
/* allow override in this case */
|
||||
if (reiserfs_rupasov_hash(s)) {
|
||||
if (reiserfs_rupasov_hash(s))
|
||||
hash = YURA_HASH;
|
||||
reiserfs_info(s, "FS seems to be empty, autodetect is using the default hash\n");
|
||||
goto out;
|
||||
}
|
||||
reiserfs_info(s, "FS seems to be empty, autodetect "
|
||||
"is using the default hash\n");
|
||||
break;
|
||||
}
|
||||
|
||||
deh_hashval = GET_HASH_VALUE(deh_offset(deh));
|
||||
r5hash = GET_HASH_VALUE(r5_hash(de.de_name, de.de_namelen));
|
||||
teahash = GET_HASH_VALUE(keyed_hash(de.de_name, de.de_namelen));
|
||||
yurahash = GET_HASH_VALUE(yura_hash(de.de_name, de.de_namelen));
|
||||
if (((teahash == r5hash)
|
||||
&&
|
||||
(GET_HASH_VALUE(deh_offset(&(de.de_deh[de.de_entry_num])))
|
||||
== r5hash)) || ((teahash == yurahash)
|
||||
&& (yurahash ==
|
||||
GET_HASH_VALUE(deh_offset
|
||||
(&
|
||||
(de.
|
||||
de_deh[de.
|
||||
de_entry_num])))))
|
||||
|| ((r5hash == yurahash)
|
||||
&& (yurahash ==
|
||||
GET_HASH_VALUE(deh_offset
|
||||
(&(de.de_deh[de.de_entry_num])))))) {
|
||||
reiserfs_warning(s, "reiserfs-2506", "Unable to "
|
||||
"automatically detect hash function. "
|
||||
"Please mount with -o "
|
||||
|
||||
if ((teahash == r5hash && deh_hashval == r5hash) ||
|
||||
(teahash == yurahash && deh_hashval == yurahash) ||
|
||||
(r5hash == yurahash && deh_hashval == yurahash)) {
|
||||
reiserfs_warning(s, "reiserfs-2506",
|
||||
"Unable to automatically detect hash "
|
||||
"function. Please mount with -o "
|
||||
"hash={tea,rupasov,r5}");
|
||||
hash = UNSET_HASH;
|
||||
break;
|
||||
goto out;
|
||||
}
|
||||
if (GET_HASH_VALUE(deh_offset(&(de.de_deh[de.de_entry_num]))) ==
|
||||
yurahash)
|
||||
|
||||
if (deh_hashval == yurahash)
|
||||
hash = YURA_HASH;
|
||||
else if (GET_HASH_VALUE
|
||||
(deh_offset(&(de.de_deh[de.de_entry_num]))) == teahash)
|
||||
else if (deh_hashval == teahash)
|
||||
hash = TEA_HASH;
|
||||
else if (GET_HASH_VALUE
|
||||
(deh_offset(&(de.de_deh[de.de_entry_num]))) == r5hash)
|
||||
else if (deh_hashval == r5hash)
|
||||
hash = R5_HASH;
|
||||
else {
|
||||
reiserfs_warning(s, "reiserfs-2506",
|
||||
"Unrecognised hash function");
|
||||
hash = UNSET_HASH;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
out:
|
||||
pathrelse(&path);
|
||||
return hash;
|
||||
}
|
||||
|
||||
// finds out which hash names are sorted with
|
||||
/* finds out which hash names are sorted with */
|
||||
static int what_hash(struct super_block *s)
|
||||
{
|
||||
__u32 code;
|
||||
|
||||
code = sb_hash_function_code(SB_DISK_SUPER_BLOCK(s));
|
||||
|
||||
/* reiserfs_hash_detect() == true if any of the hash mount options
|
||||
** were used. We must check them to make sure the user isn't
|
||||
** using a bad hash value
|
||||
/*
|
||||
* reiserfs_hash_detect() == true if any of the hash mount options
|
||||
* were used. We must check them to make sure the user isn't
|
||||
* using a bad hash value
|
||||
*/
|
||||
if (code == UNSET_HASH || reiserfs_hash_detect(s))
|
||||
code = find_hash_out(s);
|
||||
|
||||
if (code != UNSET_HASH && reiserfs_hash_detect(s)) {
|
||||
/* detection has found the hash, and we must check against the
|
||||
** mount options
|
||||
/*
|
||||
* detection has found the hash, and we must check against the
|
||||
* mount options
|
||||
*/
|
||||
if (reiserfs_rupasov_hash(s) && code != YURA_HASH) {
|
||||
reiserfs_warning(s, "reiserfs-2507",
|
||||
|
@ -1700,7 +1766,10 @@ static int what_hash(struct super_block *s)
|
|||
code = UNSET_HASH;
|
||||
}
|
||||
} else {
|
||||
/* find_hash_out was not called or could not determine the hash */
|
||||
/*
|
||||
* find_hash_out was not called or
|
||||
* could not determine the hash
|
||||
*/
|
||||
if (reiserfs_rupasov_hash(s)) {
|
||||
code = YURA_HASH;
|
||||
} else if (reiserfs_tea_hash(s)) {
|
||||
|
@ -1710,8 +1779,9 @@ static int what_hash(struct super_block *s)
|
|||
}
|
||||
}
|
||||
|
||||
/* if we are mounted RW, and we have a new valid hash code, update
|
||||
** the super
|
||||
/*
|
||||
* if we are mounted RW, and we have a new valid hash code, update
|
||||
* the super
|
||||
*/
|
||||
if (code != UNSET_HASH &&
|
||||
!(s->s_flags & MS_RDONLY) &&
|
||||
|
@ -1721,7 +1791,7 @@ static int what_hash(struct super_block *s)
|
|||
return code;
|
||||
}
|
||||
|
||||
// return pointer to appropriate function
|
||||
/* return pointer to appropriate function */
|
||||
static hashf_t hash_function(struct super_block *s)
|
||||
{
|
||||
switch (what_hash(s)) {
|
||||
|
@ -1738,7 +1808,7 @@ static hashf_t hash_function(struct super_block *s)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// this is used to set up correct value for old partitions
|
||||
/* this is used to set up correct value for old partitions */
|
||||
static int function2code(hashf_t func)
|
||||
{
|
||||
if (func == keyed_hash)
|
||||
|
@ -1748,7 +1818,7 @@ static int function2code(hashf_t func)
|
|||
if (func == r5_hash)
|
||||
return R5_HASH;
|
||||
|
||||
BUG(); // should never happen
|
||||
BUG(); /* should never happen */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1783,8 +1853,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
sbi->s_mount_opt |= (1 << REISERFS_SMALLTAIL);
|
||||
sbi->s_mount_opt |= (1 << REISERFS_ERROR_RO);
|
||||
sbi->s_mount_opt |= (1 << REISERFS_BARRIER_FLUSH);
|
||||
/* no preallocation minimum, be smart in
|
||||
reiserfs_file_write instead */
|
||||
/* no preallocation minimum, be smart in reiserfs_file_write instead */
|
||||
sbi->s_alloc_options.preallocmin = 0;
|
||||
/* Preallocate by 16 blocks (17-1) at once */
|
||||
sbi->s_alloc_options.preallocsize = 17;
|
||||
|
@ -1796,9 +1865,17 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
mutex_init(&sbi->lock);
|
||||
sbi->lock_depth = -1;
|
||||
|
||||
sbi->commit_wq = alloc_workqueue("reiserfs/%s", WQ_MEM_RECLAIM, 0,
|
||||
s->s_id);
|
||||
if (!sbi->commit_wq) {
|
||||
SWARN(silent, s, "", "Cannot allocate commit workqueue");
|
||||
errval = -ENOMEM;
|
||||
goto error_unlocked;
|
||||
}
|
||||
|
||||
jdev_name = NULL;
|
||||
if (reiserfs_parse_options
|
||||
(s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name,
|
||||
(s, (char *)data, &sbi->s_mount_opt, &blocks, &jdev_name,
|
||||
&commit_max_age, qf_names, &qfmt) == 0) {
|
||||
goto error_unlocked;
|
||||
}
|
||||
|
@ -1819,10 +1896,17 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
goto error_unlocked;
|
||||
}
|
||||
|
||||
/* try old format (undistributed bitmap, super block in 8-th 1k block of a device) */
|
||||
/*
|
||||
* try old format (undistributed bitmap, super block in 8-th 1k
|
||||
* block of a device)
|
||||
*/
|
||||
if (!read_super_block(s, REISERFS_OLD_DISK_OFFSET_IN_BYTES))
|
||||
old_format = 1;
|
||||
/* try new format (64-th 1k block), which can contain reiserfs super block */
|
||||
|
||||
/*
|
||||
* try new format (64-th 1k block), which can contain reiserfs
|
||||
* super block
|
||||
*/
|
||||
else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) {
|
||||
SWARN(silent, s, "sh-2021", "can not find reiserfs on %s",
|
||||
s->s_id);
|
||||
|
@ -1830,9 +1914,11 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
}
|
||||
|
||||
rs = SB_DISK_SUPER_BLOCK(s);
|
||||
/* Let's do basic sanity check to verify that underlying device is not
|
||||
smaller than the filesystem. If the check fails then abort and scream,
|
||||
because bad stuff will happen otherwise. */
|
||||
/*
|
||||
* Let's do basic sanity check to verify that underlying device is not
|
||||
* smaller than the filesystem. If the check fails then abort and
|
||||
* scream, because bad stuff will happen otherwise.
|
||||
*/
|
||||
if (s->s_bdev && s->s_bdev->bd_inode
|
||||
&& i_size_read(s->s_bdev->bd_inode) <
|
||||
sb_block_count(rs) * sb_blocksize(rs)) {
|
||||
|
@ -1876,15 +1962,16 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
printk("reiserfs: using flush barriers\n");
|
||||
}
|
||||
|
||||
// set_device_ro(s->s_dev, 1) ;
|
||||
if (journal_init(s, jdev_name, old_format, commit_max_age)) {
|
||||
SWARN(silent, s, "sh-2022",
|
||||
"unable to initialize journal space");
|
||||
goto error_unlocked;
|
||||
} else {
|
||||
jinit_done = 1; /* once this is set, journal_release must be called
|
||||
** if we error out of the mount
|
||||
/*
|
||||
* once this is set, journal_release must be called
|
||||
* if we error out of the mount
|
||||
*/
|
||||
jinit_done = 1;
|
||||
}
|
||||
|
||||
if (reread_meta_blocks(s)) {
|
||||
|
@ -1905,7 +1992,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
args.dirid = REISERFS_ROOT_PARENT_OBJECTID;
|
||||
root_inode =
|
||||
iget5_locked(s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor,
|
||||
reiserfs_init_locked_inode, (void *)(&args));
|
||||
reiserfs_init_locked_inode, (void *)&args);
|
||||
if (!root_inode) {
|
||||
SWARN(silent, s, "jmacd-10", "get root inode failed");
|
||||
goto error_unlocked;
|
||||
|
@ -1929,7 +2016,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
s->s_root = d_make_root(root_inode);
|
||||
if (!s->s_root)
|
||||
goto error;
|
||||
// define and initialize hash function
|
||||
/* define and initialize hash function */
|
||||
sbi->s_hash_function = hash_function(s);
|
||||
if (sbi->s_hash_function == NULL) {
|
||||
dput(s->s_root);
|
||||
|
@ -1939,11 +2026,11 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
|
||||
if (is_reiserfs_3_5(rs)
|
||||
|| (is_reiserfs_jr(rs) && SB_VERSION(s) == REISERFS_VERSION_1))
|
||||
set_bit(REISERFS_3_5, &(sbi->s_properties));
|
||||
set_bit(REISERFS_3_5, &sbi->s_properties);
|
||||
else if (old_format)
|
||||
set_bit(REISERFS_OLD_FORMAT, &(sbi->s_properties));
|
||||
set_bit(REISERFS_OLD_FORMAT, &sbi->s_properties);
|
||||
else
|
||||
set_bit(REISERFS_3_6, &(sbi->s_properties));
|
||||
set_bit(REISERFS_3_6, &sbi->s_properties);
|
||||
|
||||
if (!(s->s_flags & MS_RDONLY)) {
|
||||
|
||||
|
@ -1958,10 +2045,12 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
set_sb_umount_state(rs, REISERFS_ERROR_FS);
|
||||
set_sb_fs_state(rs, 0);
|
||||
|
||||
/* Clear out s_bmap_nr if it would wrap. We can handle this
|
||||
/*
|
||||
* Clear out s_bmap_nr if it would wrap. We can handle this
|
||||
* case, but older revisions can't. This will cause the
|
||||
* file system to fail mount on those older implementations,
|
||||
* avoiding corruption. -jeffm */
|
||||
* avoiding corruption. -jeffm
|
||||
*/
|
||||
if (bmap_would_wrap(reiserfs_bmap_count(s)) &&
|
||||
sb_bmap_nr(rs) != 0) {
|
||||
reiserfs_warning(s, "super-2030", "This file system "
|
||||
|
@ -1974,8 +2063,10 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
}
|
||||
|
||||
if (old_format_only(s)) {
|
||||
/* filesystem of format 3.5 either with standard or non-standard
|
||||
journal */
|
||||
/*
|
||||
* filesystem of format 3.5 either with standard
|
||||
* or non-standard journal
|
||||
*/
|
||||
if (convert_reiserfs(s)) {
|
||||
/* and -o conv is given */
|
||||
if (!silent)
|
||||
|
@ -1983,8 +2074,11 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
"converting 3.5 filesystem to the 3.6 format");
|
||||
|
||||
if (is_reiserfs_3_5(rs))
|
||||
/* put magic string of 3.6 format. 2.2 will not be able to
|
||||
mount this filesystem anymore */
|
||||
/*
|
||||
* put magic string of 3.6 format.
|
||||
* 2.2 will not be able to
|
||||
* mount this filesystem anymore
|
||||
*/
|
||||
memcpy(rs->s_v1.s_magic,
|
||||
reiserfs_3_6_magic_string,
|
||||
sizeof
|
||||
|
@ -1992,8 +2086,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
|
||||
set_sb_version(rs, REISERFS_VERSION_2);
|
||||
reiserfs_convert_objectid_map_v1(s);
|
||||
set_bit(REISERFS_3_6, &(sbi->s_properties));
|
||||
clear_bit(REISERFS_3_5, &(sbi->s_properties));
|
||||
set_bit(REISERFS_3_6, &sbi->s_properties);
|
||||
clear_bit(REISERFS_3_5, &sbi->s_properties);
|
||||
} else if (!silent) {
|
||||
reiserfs_info(s, "using 3.5.x disk format\n");
|
||||
}
|
||||
|
@ -2001,8 +2095,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
set_sb_mnt_count(rs, sb_mnt_count(rs) + 1);
|
||||
|
||||
|
||||
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
|
||||
errval = journal_end(&th, s, 1);
|
||||
journal_mark_dirty(&th, SB_BUFFER_WITH_SB(s));
|
||||
errval = journal_end(&th);
|
||||
if (errval) {
|
||||
dput(s->s_root);
|
||||
s->s_root = NULL;
|
||||
|
@ -2018,7 +2112,9 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
}
|
||||
reiserfs_write_lock(s);
|
||||
|
||||
/* look for files which were to be removed in previous session */
|
||||
/*
|
||||
* look for files which were to be removed in previous session
|
||||
*/
|
||||
finish_unfinished(s);
|
||||
} else {
|
||||
if (old_format_only(s) && !silent) {
|
||||
|
@ -2034,7 +2130,9 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
|||
}
|
||||
reiserfs_write_lock(s);
|
||||
}
|
||||
// mark hash in super block: it could be unset. overwrite should be ok
|
||||
/*
|
||||
* mark hash in super block: it could be unset. overwrite should be ok
|
||||
*/
|
||||
set_sb_hash_function_code(rs, function2code(sbi->s_hash_function));
|
||||
|
||||
handle_attrs(s);
|
||||
|
@ -2111,9 +2209,7 @@ static int reiserfs_write_dquot(struct dquot *dquot)
|
|||
depth = reiserfs_write_unlock_nested(dquot->dq_sb);
|
||||
ret = dquot_commit(dquot);
|
||||
reiserfs_write_lock_nested(dquot->dq_sb, depth);
|
||||
err =
|
||||
journal_end(&th, dquot->dq_sb,
|
||||
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
|
||||
err = journal_end(&th);
|
||||
if (!ret && err)
|
||||
ret = err;
|
||||
out:
|
||||
|
@ -2136,9 +2232,7 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
|
|||
depth = reiserfs_write_unlock_nested(dquot->dq_sb);
|
||||
ret = dquot_acquire(dquot);
|
||||
reiserfs_write_lock_nested(dquot->dq_sb, depth);
|
||||
err =
|
||||
journal_end(&th, dquot->dq_sb,
|
||||
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
|
||||
err = journal_end(&th);
|
||||
if (!ret && err)
|
||||
ret = err;
|
||||
out:
|
||||
|
@ -2163,9 +2257,7 @@ static int reiserfs_release_dquot(struct dquot *dquot)
|
|||
}
|
||||
ret = dquot_release(dquot);
|
||||
reiserfs_write_lock(dquot->dq_sb);
|
||||
err =
|
||||
journal_end(&th, dquot->dq_sb,
|
||||
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
||||
err = journal_end(&th);
|
||||
if (!ret && err)
|
||||
ret = err;
|
||||
reiserfs_write_unlock(dquot->dq_sb);
|
||||
|
@ -2198,7 +2290,7 @@ static int reiserfs_write_info(struct super_block *sb, int type)
|
|||
depth = reiserfs_write_unlock_nested(sb);
|
||||
ret = dquot_commit_info(sb, type);
|
||||
reiserfs_write_lock_nested(sb, depth);
|
||||
err = journal_end(&th, sb, 2);
|
||||
err = journal_end(&th);
|
||||
if (!ret && err)
|
||||
ret = err;
|
||||
out:
|
||||
|
@ -2238,7 +2330,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
|
|||
goto out;
|
||||
}
|
||||
inode = path->dentry->d_inode;
|
||||
/* We must not pack tails for quota files on reiserfs for quota IO to work */
|
||||
/*
|
||||
* We must not pack tails for quota files on reiserfs for quota
|
||||
* IO to work
|
||||
*/
|
||||
if (!(REISERFS_I(inode)->i_flags & i_nopack_mask)) {
|
||||
err = reiserfs_unpack(inode, NULL);
|
||||
if (err) {
|
||||
|
@ -2268,7 +2363,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
|
|||
err = journal_begin(&th, sb, 1);
|
||||
if (err)
|
||||
goto out;
|
||||
err = journal_end_sync(&th, sb, 1);
|
||||
err = journal_end_sync(&th);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
@ -2279,10 +2374,12 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Read data from quotafile - avoid pagecache and such because we cannot afford
|
||||
/*
|
||||
* Read data from quotafile - avoid pagecache and such because we cannot afford
|
||||
* acquiring the locks... As quota files are never truncated and quota code
|
||||
* itself serializes the operations (and no one else should touch the files)
|
||||
* we don't have to be afraid of races */
|
||||
* we don't have to be afraid of races
|
||||
*/
|
||||
static ssize_t reiserfs_quota_read(struct super_block *sb, int type, char *data,
|
||||
size_t len, loff_t off)
|
||||
{
|
||||
|
@ -2303,7 +2400,10 @@ static ssize_t reiserfs_quota_read(struct super_block *sb, int type, char *data,
|
|||
sb->s_blocksize - offset <
|
||||
toread ? sb->s_blocksize - offset : toread;
|
||||
tmp_bh.b_state = 0;
|
||||
/* Quota files are without tails so we can safely use this function */
|
||||
/*
|
||||
* Quota files are without tails so we can safely
|
||||
* use this function
|
||||
*/
|
||||
reiserfs_write_lock(sb);
|
||||
err = reiserfs_get_block(inode, blk, &tmp_bh, 0);
|
||||
reiserfs_write_unlock(sb);
|
||||
|
@ -2326,8 +2426,10 @@ static ssize_t reiserfs_quota_read(struct super_block *sb, int type, char *data,
|
|||
return len;
|
||||
}
|
||||
|
||||
/* Write to quotafile (we know the transaction is already started and has
|
||||
* enough credits) */
|
||||
/*
|
||||
* Write to quotafile (we know the transaction is already started and has
|
||||
* enough credits)
|
||||
*/
|
||||
static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
|
||||
const char *data, size_t len, loff_t off)
|
||||
{
|
||||
|
@ -2368,7 +2470,7 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
|
|||
unlock_buffer(bh);
|
||||
reiserfs_write_lock(sb);
|
||||
reiserfs_prepare_for_journal(sb, bh, 1);
|
||||
journal_mark_dirty(current->journal_info, sb, bh);
|
||||
journal_mark_dirty(current->journal_info, bh);
|
||||
if (!journal_quota)
|
||||
reiserfs_add_ordered_list(inode, bh);
|
||||
reiserfs_write_unlock(sb);
|
||||
|
@ -2402,18 +2504,18 @@ static int __init init_reiserfs_fs(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = init_inodecache())) {
|
||||
ret = init_inodecache();
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
reiserfs_proc_info_global_init();
|
||||
|
||||
ret = register_filesystem(&reiserfs_fs_type);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
out:
|
||||
reiserfs_proc_info_global_done();
|
||||
destroy_inodecache();
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright 1999 Hans Reiser, see reiserfs/README for licensing and copyright details
|
||||
* Copyright 1999 Hans Reiser, see reiserfs/README for licensing and copyright
|
||||
* details
|
||||
*/
|
||||
|
||||
#include <linux/time.h>
|
||||
|
@ -7,29 +8,41 @@
|
|||
#include <linux/buffer_head.h>
|
||||
#include "reiserfs.h"
|
||||
|
||||
/* access to tail : when one is going to read tail it must make sure, that is not running.
|
||||
direct2indirect and indirect2direct can not run concurrently */
|
||||
/*
|
||||
* access to tail : when one is going to read tail it must make sure, that is
|
||||
* not running. direct2indirect and indirect2direct can not run concurrently
|
||||
*/
|
||||
|
||||
/* Converts direct items to an unformatted node. Panics if file has no
|
||||
tail. -ENOSPC if no disk space for conversion */
|
||||
/* path points to first direct item of the file regarless of how many of
|
||||
them are there */
|
||||
/*
|
||||
* Converts direct items to an unformatted node. Panics if file has no
|
||||
* tail. -ENOSPC if no disk space for conversion
|
||||
*/
|
||||
/*
|
||||
* path points to first direct item of the file regardless of how many of
|
||||
* them are there
|
||||
*/
|
||||
int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
|
||||
struct treepath *path, struct buffer_head *unbh,
|
||||
loff_t tail_offset)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct buffer_head *up_to_date_bh;
|
||||
struct item_head *p_le_ih = PATH_PITEM_HEAD(path);
|
||||
struct item_head *p_le_ih = tp_item_head(path);
|
||||
unsigned long total_tail = 0;
|
||||
struct cpu_key end_key; /* Key to search for the last byte of the
|
||||
converted item. */
|
||||
struct item_head ind_ih; /* new indirect item to be inserted or
|
||||
key of unfm pointer to be pasted */
|
||||
int blk_size, retval; /* returned value for reiserfs_insert_item and clones */
|
||||
unp_t unfm_ptr; /* Handle on an unformatted node
|
||||
that will be inserted in the
|
||||
tree. */
|
||||
|
||||
/* Key to search for the last byte of the converted item. */
|
||||
struct cpu_key end_key;
|
||||
|
||||
/*
|
||||
* new indirect item to be inserted or key
|
||||
* of unfm pointer to be pasted
|
||||
*/
|
||||
struct item_head ind_ih;
|
||||
int blk_size;
|
||||
/* returned value for reiserfs_insert_item and clones */
|
||||
int retval;
|
||||
/* Handle on an unformatted node that will be inserted in the tree. */
|
||||
unp_t unfm_ptr;
|
||||
|
||||
BUG_ON(!th->t_trans_id);
|
||||
|
||||
|
@ -37,8 +50,10 @@ int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
|
|||
|
||||
blk_size = sb->s_blocksize;
|
||||
|
||||
/* and key to search for append or insert pointer to the new
|
||||
unformatted node. */
|
||||
/*
|
||||
* and key to search for append or insert pointer to the new
|
||||
* unformatted node.
|
||||
*/
|
||||
copy_item_head(&ind_ih, p_le_ih);
|
||||
set_le_ih_k_offset(&ind_ih, tail_offset);
|
||||
set_le_ih_k_type(&ind_ih, TYPE_INDIRECT);
|
||||
|
@ -55,7 +70,7 @@ int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
p_le_ih = PATH_PITEM_HEAD(path);
|
||||
p_le_ih = tp_item_head(path);
|
||||
|
||||
unfm_ptr = cpu_to_le32(unbh->b_blocknr);
|
||||
|
||||
|
@ -76,36 +91,43 @@ int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
|
|||
if (retval) {
|
||||
return retval;
|
||||
}
|
||||
// note: from here there are two keys which have matching first
|
||||
// three key components. They only differ by the fourth one.
|
||||
/*
|
||||
* note: from here there are two keys which have matching first
|
||||
* three key components. They only differ by the fourth one.
|
||||
*/
|
||||
|
||||
/* Set the key to search for the direct items of the file */
|
||||
make_cpu_key(&end_key, inode, max_reiserfs_offset(inode), TYPE_DIRECT,
|
||||
4);
|
||||
|
||||
/* Move bytes from the direct items to the new unformatted node
|
||||
and delete them. */
|
||||
/*
|
||||
* Move bytes from the direct items to the new unformatted node
|
||||
* and delete them.
|
||||
*/
|
||||
while (1) {
|
||||
int tail_size;
|
||||
|
||||
/* end_key.k_offset is set so, that we will always have found
|
||||
last item of the file */
|
||||
/*
|
||||
* end_key.k_offset is set so, that we will always have found
|
||||
* last item of the file
|
||||
*/
|
||||
if (search_for_position_by_key(sb, &end_key, path) ==
|
||||
POSITION_FOUND)
|
||||
reiserfs_panic(sb, "PAP-14050",
|
||||
"direct item (%K) not found", &end_key);
|
||||
p_le_ih = PATH_PITEM_HEAD(path);
|
||||
p_le_ih = tp_item_head(path);
|
||||
RFALSE(!is_direct_le_ih(p_le_ih),
|
||||
"vs-14055: direct item expected(%K), found %h",
|
||||
&end_key, p_le_ih);
|
||||
tail_size = (le_ih_k_offset(p_le_ih) & (blk_size - 1))
|
||||
+ ih_item_len(p_le_ih) - 1;
|
||||
|
||||
/* we only send the unbh pointer if the buffer is not up to date.
|
||||
** this avoids overwriting good data from writepage() with old data
|
||||
** from the disk or buffer cache
|
||||
** Special case: unbh->b_page will be NULL if we are coming through
|
||||
** DIRECT_IO handler here.
|
||||
/*
|
||||
* we only send the unbh pointer if the buffer is not
|
||||
* up to date. this avoids overwriting good data from
|
||||
* writepage() with old data from the disk or buffer cache
|
||||
* Special case: unbh->b_page will be NULL if we are coming
|
||||
* through DIRECT_IO handler here.
|
||||
*/
|
||||
if (!unbh->b_page || buffer_uptodate(unbh)
|
||||
|| PageUptodate(unbh->b_page)) {
|
||||
|
@ -117,13 +139,15 @@ int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
|
|||
up_to_date_bh);
|
||||
|
||||
total_tail += retval;
|
||||
|
||||
/* done: file does not have direct items anymore */
|
||||
if (tail_size == retval)
|
||||
// done: file does not have direct items anymore
|
||||
break;
|
||||
|
||||
}
|
||||
/* if we've copied bytes from disk into the page, we need to zero
|
||||
** out the unused part of the block (it was not up to date before)
|
||||
/*
|
||||
* if we've copied bytes from disk into the page, we need to zero
|
||||
* out the unused part of the block (it was not up to date before)
|
||||
*/
|
||||
if (up_to_date_bh) {
|
||||
unsigned pgoff =
|
||||
|
@ -146,9 +170,11 @@ void reiserfs_unmap_buffer(struct buffer_head *bh)
|
|||
BUG();
|
||||
}
|
||||
clear_buffer_dirty(bh);
|
||||
/* Remove the buffer from whatever list it belongs to. We are mostly
|
||||
interested in removing it from per-sb j_dirty_buffers list, to avoid
|
||||
BUG() on attempt to write not mapped buffer */
|
||||
/*
|
||||
* Remove the buffer from whatever list it belongs to. We are mostly
|
||||
* interested in removing it from per-sb j_dirty_buffers list, to avoid
|
||||
* BUG() on attempt to write not mapped buffer
|
||||
*/
|
||||
if ((!list_empty(&bh->b_assoc_buffers) || bh->b_private) && bh->b_page) {
|
||||
struct inode *inode = bh->b_page->mapping->host;
|
||||
struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb);
|
||||
|
@ -164,12 +190,14 @@ void reiserfs_unmap_buffer(struct buffer_head *bh)
|
|||
unlock_buffer(bh);
|
||||
}
|
||||
|
||||
/* this first locks inode (neither reads nor sync are permitted),
|
||||
reads tail through page cache, insert direct item. When direct item
|
||||
inserted successfully inode is left locked. Return value is always
|
||||
what we expect from it (number of cut bytes). But when tail remains
|
||||
in the unformatted node, we set mode to SKIP_BALANCING and unlock
|
||||
inode */
|
||||
/*
|
||||
* this first locks inode (neither reads nor sync are permitted),
|
||||
* reads tail through page cache, insert direct item. When direct item
|
||||
* inserted successfully inode is left locked. Return value is always
|
||||
* what we expect from it (number of cut bytes). But when tail remains
|
||||
* in the unformatted node, we set mode to SKIP_BALANCING and unlock
|
||||
* inode
|
||||
*/
|
||||
int indirect2direct(struct reiserfs_transaction_handle *th,
|
||||
struct inode *inode, struct page *page,
|
||||
struct treepath *path, /* path to the indirect item. */
|
||||
|
@ -194,7 +222,7 @@ int indirect2direct(struct reiserfs_transaction_handle *th,
|
|||
*mode = M_SKIP_BALANCING;
|
||||
|
||||
/* store item head path points to. */
|
||||
copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
|
||||
copy_item_head(&s_ih, tp_item_head(path));
|
||||
|
||||
tail_len = (n_new_file_size & (block_size - 1));
|
||||
if (get_inode_sd_version(inode) == STAT_DATA_V2)
|
||||
|
@ -207,9 +235,11 @@ int indirect2direct(struct reiserfs_transaction_handle *th,
|
|||
1) * sb->s_blocksize;
|
||||
pos1 = pos;
|
||||
|
||||
// we are protected by i_mutex. The tail can not disapper, not
|
||||
// append can be done either
|
||||
// we are in truncate or packing tail in file_release
|
||||
/*
|
||||
* we are protected by i_mutex. The tail can not disapper, not
|
||||
* append can be done either
|
||||
* we are in truncate or packing tail in file_release
|
||||
*/
|
||||
|
||||
tail = (char *)kmap(page); /* this can schedule */
|
||||
|
||||
|
@ -220,7 +250,7 @@ int indirect2direct(struct reiserfs_transaction_handle *th,
|
|||
reiserfs_panic(sb, "PAP-5520",
|
||||
"item to be converted %K does not exist",
|
||||
item_key);
|
||||
copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
|
||||
copy_item_head(&s_ih, tp_item_head(path));
|
||||
#ifdef CONFIG_REISERFS_CHECK
|
||||
pos = le_ih_k_offset(&s_ih) - 1 +
|
||||
(ih_item_len(&s_ih) / UNFM_P_SIZE -
|
||||
|
@ -236,9 +266,10 @@ int indirect2direct(struct reiserfs_transaction_handle *th,
|
|||
pos1 + 1, TYPE_DIRECT, round_tail_len,
|
||||
0xffff /*ih_free_space */ );
|
||||
|
||||
/* we want a pointer to the first byte of the tail in the page.
|
||||
** the page was locked and this part of the page was up to date when
|
||||
** indirect2direct was called, so we know the bytes are still valid
|
||||
/*
|
||||
* we want a pointer to the first byte of the tail in the page.
|
||||
* the page was locked and this part of the page was up to date when
|
||||
* indirect2direct was called, so we know the bytes are still valid
|
||||
*/
|
||||
tail = tail + (pos & (PAGE_CACHE_SIZE - 1));
|
||||
|
||||
|
@ -250,12 +281,14 @@ int indirect2direct(struct reiserfs_transaction_handle *th,
|
|||
/* Insert tail as new direct item in the tree */
|
||||
if (reiserfs_insert_item(th, path, &key, &s_ih, 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
|
||||
indirect items's ih_free_space. Now ih_free_space is not
|
||||
used, it would be ideal to write zeros to corresponding
|
||||
unformatted node. For now i_size is considered as guard for
|
||||
going out of file size */
|
||||
/*
|
||||
* No disk memory. So we can not convert last unformatted node
|
||||
* to the direct item. In this case we used to adjust
|
||||
* indirect items's ih_free_space. Now ih_free_space is not
|
||||
* used, it would be ideal to write zeros to corresponding
|
||||
* unformatted node. For now i_size is considered as guard for
|
||||
* going out of file size
|
||||
*/
|
||||
kunmap(page);
|
||||
return block_size - round_tail_len;
|
||||
}
|
||||
|
@ -264,12 +297,16 @@ int indirect2direct(struct reiserfs_transaction_handle *th,
|
|||
/* make sure to get the i_blocks changes from reiserfs_insert_item */
|
||||
reiserfs_update_sd(th, 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.
|
||||
/*
|
||||
* 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 fourth one.
|
||||
*/
|
||||
|
||||
/* We have inserted new direct item and must remove last
|
||||
unformatted node. */
|
||||
/*
|
||||
* We have inserted new direct item and must remove last
|
||||
* unformatted node.
|
||||
*/
|
||||
*mode = M_CUT;
|
||||
|
||||
/* we store position of first direct item in the in-core inode */
|
||||
|
|
|
@ -56,9 +56,11 @@
|
|||
#define XAROOT_NAME "xattrs"
|
||||
|
||||
|
||||
/* Helpers for inode ops. We do this so that we don't have all the VFS
|
||||
/*
|
||||
* Helpers for inode ops. We do this so that we don't have all the VFS
|
||||
* overhead and also for proper i_mutex annotation.
|
||||
* dir->i_mutex must be held for all of them. */
|
||||
* dir->i_mutex must be held for all of them.
|
||||
*/
|
||||
#ifdef CONFIG_REISERFS_FS_XATTR
|
||||
static int xattr_create(struct inode *dir, struct dentry *dentry, int mode)
|
||||
{
|
||||
|
@ -73,10 +75,12 @@ static int xattr_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|||
return dir->i_op->mkdir(dir, dentry, mode);
|
||||
}
|
||||
|
||||
/* We use I_MUTEX_CHILD here to silence lockdep. It's safe because xattr
|
||||
/*
|
||||
* We use I_MUTEX_CHILD here to silence lockdep. It's safe because xattr
|
||||
* mutation ops aren't called during rename or splace, which are the
|
||||
* only other users of I_MUTEX_CHILD. It violates the ordering, but that's
|
||||
* better than allocating another subclass just for this code. */
|
||||
* better than allocating another subclass just for this code.
|
||||
*/
|
||||
static int xattr_unlink(struct inode *dir, struct dentry *dentry)
|
||||
{
|
||||
int error;
|
||||
|
@ -166,9 +170,11 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags)
|
|||
return xadir;
|
||||
}
|
||||
|
||||
/* The following are side effects of other operations that aren't explicitly
|
||||
/*
|
||||
* The following are side effects of other operations that aren't explicitly
|
||||
* modifying extended attributes. This includes operations such as permissions
|
||||
* or ownership changes, object deletions, etc. */
|
||||
* or ownership changes, object deletions, etc.
|
||||
*/
|
||||
struct reiserfs_dentry_buf {
|
||||
struct dir_context ctx;
|
||||
struct dentry *xadir;
|
||||
|
@ -267,11 +273,13 @@ static int reiserfs_for_each_xattr(struct inode *inode,
|
|||
cleanup_dentry_buf(&buf);
|
||||
|
||||
if (!err) {
|
||||
/* We start a transaction here to avoid a ABBA situation
|
||||
/*
|
||||
* We start a transaction here to avoid a ABBA situation
|
||||
* between the xattr root's i_mutex and the journal lock.
|
||||
* This doesn't incur much additional overhead since the
|
||||
* new transaction will just nest inside the
|
||||
* outer transaction. */
|
||||
* outer transaction.
|
||||
*/
|
||||
int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 +
|
||||
4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);
|
||||
struct reiserfs_transaction_handle th;
|
||||
|
@ -284,7 +292,7 @@ static int reiserfs_for_each_xattr(struct inode *inode,
|
|||
I_MUTEX_XATTR);
|
||||
err = action(dir, data);
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
jerror = journal_end(&th, inode->i_sb, blocks);
|
||||
jerror = journal_end(&th);
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
mutex_unlock(&dir->d_parent->d_inode->i_mutex);
|
||||
err = jerror ?: err;
|
||||
|
@ -349,9 +357,11 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_REISERFS_FS_XATTR
|
||||
/* Returns a dentry corresponding to a specific extended attribute file
|
||||
/*
|
||||
* Returns a dentry corresponding to a specific extended attribute file
|
||||
* for the inode. If flags allow, the file is created. Otherwise, a
|
||||
* valid or negative dentry, or an error is returned. */
|
||||
* valid or negative dentry, or an error is returned.
|
||||
*/
|
||||
static struct dentry *xattr_lookup(struct inode *inode, const char *name,
|
||||
int flags)
|
||||
{
|
||||
|
@ -400,8 +410,10 @@ static struct page *reiserfs_get_page(struct inode *dir, size_t n)
|
|||
{
|
||||
struct address_space *mapping = dir->i_mapping;
|
||||
struct page *page;
|
||||
/* We can deadlock if we try to free dentries,
|
||||
and an unlink/rmdir has just occurred - GFP_NOFS avoids this */
|
||||
/*
|
||||
* We can deadlock if we try to free dentries,
|
||||
* and an unlink/rmdir has just occurred - GFP_NOFS avoids this
|
||||
*/
|
||||
mapping_set_gfp_mask(mapping, GFP_NOFS);
|
||||
page = read_mapping_page(mapping, n >> PAGE_CACHE_SHIFT, NULL);
|
||||
if (!IS_ERR(page)) {
|
||||
|
@ -411,7 +423,7 @@ static struct page *reiserfs_get_page(struct inode *dir, size_t n)
|
|||
}
|
||||
return page;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
reiserfs_put_page(page);
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
@ -589,7 +601,7 @@ int reiserfs_xattr_set(struct inode *inode, const char *name,
|
|||
buffer, buffer_size, flags);
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
error2 = journal_end(&th, inode->i_sb, jbegin_count);
|
||||
error2 = journal_end(&th);
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
if (error == 0)
|
||||
error = error2;
|
||||
|
@ -615,8 +627,10 @@ reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer,
|
|||
if (name == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* We can't have xattrs attached to v1 items since they don't have
|
||||
* generation numbers */
|
||||
/*
|
||||
* We can't have xattrs attached to v1 items since they don't have
|
||||
* generation numbers
|
||||
*/
|
||||
if (get_inode_sd_version(inode) == STAT_DATA_V1)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
@ -913,12 +927,16 @@ static const struct xattr_handler *reiserfs_xattr_handlers[] = {
|
|||
|
||||
static int xattr_mount_check(struct super_block *s)
|
||||
{
|
||||
/* We need generation numbers to ensure that the oid mapping is correct
|
||||
* v3.5 filesystems don't have them. */
|
||||
/*
|
||||
* We need generation numbers to ensure that the oid mapping is correct
|
||||
* v3.5 filesystems don't have them.
|
||||
*/
|
||||
if (old_format_only(s)) {
|
||||
if (reiserfs_xattrs_optional(s)) {
|
||||
/* Old format filesystem, but optional xattrs have
|
||||
* been enabled. Error out. */
|
||||
/*
|
||||
* Old format filesystem, but optional xattrs have
|
||||
* been enabled. Error out.
|
||||
*/
|
||||
reiserfs_warning(s, "jdm-2005",
|
||||
"xattrs/ACLs not supported "
|
||||
"on pre-v3.6 format filesystems. "
|
||||
|
@ -972,9 +990,11 @@ int reiserfs_lookup_privroot(struct super_block *s)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* We need to take a copy of the mount flags since things like
|
||||
/*
|
||||
* We need to take a copy of the mount flags since things like
|
||||
* MS_RDONLY don't get set until *after* we're called.
|
||||
* mount_flags != mount_options */
|
||||
* mount_flags != mount_options
|
||||
*/
|
||||
int reiserfs_xattr_init(struct super_block *s, int mount_flags)
|
||||
{
|
||||
int err = 0;
|
||||
|
@ -1007,8 +1027,8 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
|
|||
|
||||
error:
|
||||
if (err) {
|
||||
clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt));
|
||||
clear_bit(REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt));
|
||||
clear_bit(REISERFS_XATTRS_USER, &REISERFS_SB(s)->s_mount_opt);
|
||||
clear_bit(REISERFS_POSIXACL, &REISERFS_SB(s)->s_mount_opt);
|
||||
}
|
||||
|
||||
/* The super_block MS_POSIXACL must mirror the (no)acl mount option. */
|
||||
|
|
|
@ -61,7 +61,8 @@ static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* We may have to create up to 3 objects: xattr root, xattr dir, xattr file.
|
||||
/*
|
||||
* We may have to create up to 3 objects: xattr root, xattr dir, xattr file.
|
||||
* Let's try to be smart about it.
|
||||
* xattr root: We cache it. If it's not cached, we may need to create it.
|
||||
* xattr dir: If anything has been loaded for this inode, we can set a flag
|
||||
|
|
|
@ -25,8 +25,10 @@ reiserfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
|
|||
int size = acl ? posix_acl_xattr_size(acl->a_count) : 0;
|
||||
|
||||
|
||||
/* Pessimism: We can't assume that anything from the xattr root up
|
||||
* has been created. */
|
||||
/*
|
||||
* Pessimism: We can't assume that anything from the xattr root up
|
||||
* has been created.
|
||||
*/
|
||||
|
||||
jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
|
||||
reiserfs_xattr_nblocks(inode, size) * 2;
|
||||
|
@ -37,7 +39,7 @@ reiserfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
|
|||
if (error == 0) {
|
||||
error = __reiserfs_set_acl(&th, inode, type, acl);
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
error2 = journal_end(&th, inode->i_sb, jcreate_blocks);
|
||||
error2 = journal_end(&th);
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
if (error2)
|
||||
error = error2;
|
||||
|
@ -111,7 +113,7 @@ static struct posix_acl *reiserfs_posix_acl_from_disk(const void *value, size_t
|
|||
goto fail;
|
||||
return acl;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
posix_acl_release(acl);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
@ -164,7 +166,7 @@ static void *reiserfs_posix_acl_to_disk(const struct posix_acl *acl, size_t * si
|
|||
}
|
||||
return (char *)ext_acl;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
kfree(ext_acl);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
@ -208,8 +210,10 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
|
|||
|
||||
retval = reiserfs_xattr_get(inode, name, value, size);
|
||||
if (retval == -ENODATA || retval == -ENOSYS) {
|
||||
/* This shouldn't actually happen as it should have
|
||||
been caught above.. but just in case */
|
||||
/*
|
||||
* This shouldn't actually happen as it should have
|
||||
* been caught above.. but just in case
|
||||
*/
|
||||
acl = NULL;
|
||||
} else if (retval < 0) {
|
||||
acl = ERR_PTR(retval);
|
||||
|
@ -290,8 +294,10 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
|
|||
return error;
|
||||
}
|
||||
|
||||
/* dir->i_mutex: locked,
|
||||
* inode is new and not released into the wild yet */
|
||||
/*
|
||||
* dir->i_mutex: locked,
|
||||
* inode is new and not released into the wild yet
|
||||
*/
|
||||
int
|
||||
reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
|
@ -304,14 +310,18 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
|
|||
if (S_ISLNK(inode->i_mode))
|
||||
return 0;
|
||||
|
||||
/* ACLs can only be used on "new" objects, so if it's an old object
|
||||
* there is nothing to inherit from */
|
||||
/*
|
||||
* ACLs can only be used on "new" objects, so if it's an old object
|
||||
* there is nothing to inherit from
|
||||
*/
|
||||
if (get_inode_sd_version(dir) == STAT_DATA_V1)
|
||||
goto apply_umask;
|
||||
|
||||
/* Don't apply ACLs to objects in the .reiserfs_priv tree.. This
|
||||
/*
|
||||
* Don't apply ACLs to objects in the .reiserfs_priv tree.. This
|
||||
* would be useless since permissions are ignored, and a pain because
|
||||
* it introduces locking cycles */
|
||||
* it introduces locking cycles
|
||||
*/
|
||||
if (IS_PRIVATE(dir)) {
|
||||
inode->i_flags |= S_PRIVATE;
|
||||
goto apply_umask;
|
||||
|
@ -335,7 +345,7 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
|
|||
|
||||
return err;
|
||||
|
||||
apply_umask:
|
||||
apply_umask:
|
||||
/* no ACL, apply umask */
|
||||
inode->i_mode &= ~current_umask();
|
||||
return err;
|
||||
|
|
Загрузка…
Ссылка в новой задаче