2005-04-17 02:20:36 +04:00
/*
2014-04-23 18:00:36 +04:00
* Copyright 1999 Hans Reiser , see reiserfs / README for licensing and copyright
* details
2005-04-17 02:20:36 +04:00
*/
# include <linux/time.h>
# include <linux/pagemap.h>
# include <linux/buffer_head.h>
2012-03-17 09:16:43 +04:00
# include "reiserfs.h"
2005-04-17 02:20:36 +04:00
2014-04-23 18:00:36 +04:00
/*
* 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
*/
2005-04-17 02:20:36 +04:00
2014-04-23 18:00:36 +04:00
/*
* 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
*/
2005-07-13 07:21:28 +04:00
int direct2indirect ( struct reiserfs_transaction_handle * th , struct inode * inode ,
2006-12-08 13:36:32 +03:00
struct treepath * path , struct buffer_head * unbh ,
2005-07-13 07:21:28 +04:00
loff_t tail_offset )
2005-04-17 02:20:36 +04:00
{
2005-07-13 07:21:28 +04:00
struct super_block * sb = inode - > i_sb ;
struct buffer_head * up_to_date_bh ;
2014-04-23 18:00:35 +04:00
struct item_head * p_le_ih = tp_item_head ( path ) ;
2005-07-13 07:21:28 +04:00
unsigned long total_tail = 0 ;
2014-04-23 18:00:36 +04:00
/* 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 ;
2005-07-13 07:21:28 +04:00
BUG_ON ( ! th - > t_trans_id ) ;
REISERFS_SB ( sb ) - > s_direct2indirect + + ;
2009-03-30 22:02:50 +04:00
blk_size = sb - > s_blocksize ;
2005-07-13 07:21:28 +04:00
2014-04-23 18:00:36 +04:00
/*
* and key to search for append or insert pointer to the new
* unformatted node .
*/
2005-07-13 07:21:28 +04:00
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 ) ;
/* Set the key to search for the place for new unfm pointer */
make_cpu_key ( & end_key , inode , tail_offset , TYPE_INDIRECT , 4 ) ;
2009-03-30 22:02:44 +04:00
/* FIXME: we could avoid this */
2005-07-13 07:21:28 +04:00
if ( search_for_position_by_key ( sb , & end_key , path ) = = POSITION_FOUND ) {
2009-03-30 22:02:28 +04:00
reiserfs_error ( sb , " PAP-14030 " ,
" pasted or inserted byte exists in "
" the tree %K. Use fsck to repair. " , & end_key ) ;
2005-07-13 07:21:28 +04:00
pathrelse ( path ) ;
return - EIO ;
}
2014-04-23 18:00:35 +04:00
p_le_ih = tp_item_head ( path ) ;
2005-07-13 07:21:28 +04:00
unfm_ptr = cpu_to_le32 ( unbh - > b_blocknr ) ;
if ( is_statdata_le_ih ( p_le_ih ) ) {
/* Insert new indirect item. */
set_ih_free_space ( & ind_ih , 0 ) ; /* delete at nearest future */
put_ih_item_len ( & ind_ih , UNFM_P_SIZE ) ;
PATH_LAST_POSITION ( path ) + + ;
2009-03-30 22:02:50 +04:00
retval =
2005-07-13 07:21:28 +04:00
reiserfs_insert_item ( th , path , & end_key , & ind_ih , inode ,
2005-04-17 02:20:36 +04:00
( char * ) & unfm_ptr ) ;
} else {
2005-07-13 07:21:28 +04:00
/* Paste into last indirect item of an object. */
2009-03-30 22:02:50 +04:00
retval = reiserfs_paste_into_item ( th , path , & end_key , inode ,
2005-07-13 07:21:28 +04:00
( char * ) & unfm_ptr ,
UNFM_P_SIZE ) ;
2005-04-17 02:20:36 +04:00
}
2009-03-30 22:02:50 +04:00
if ( retval ) {
return retval ;
2005-07-13 07:21:28 +04:00
}
2014-04-23 18:00:36 +04:00
/*
* note : from here there are two keys which have matching first
* three key components . They only differ by the fourth one .
*/
2005-07-13 07:21:28 +04:00
/* 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 ) ;
2014-04-23 18:00:36 +04:00
/*
* Move bytes from the direct items to the new unformatted node
* and delete them .
*/
2005-07-13 07:21:28 +04:00
while ( 1 ) {
int tail_size ;
2014-04-23 18:00:36 +04:00
/*
* end_key . k_offset is set so , that we will always have found
* last item of the file
*/
2005-07-13 07:21:28 +04:00
if ( search_for_position_by_key ( sb , & end_key , path ) = =
POSITION_FOUND )
2009-03-30 22:02:25 +04:00
reiserfs_panic ( sb , " PAP-14050 " ,
2005-07-13 07:21:28 +04:00
" direct item (%K) not found " , & end_key ) ;
2014-04-23 18:00:35 +04:00
p_le_ih = tp_item_head ( path ) ;
2005-07-13 07:21:28 +04:00
RFALSE ( ! is_direct_le_ih ( p_le_ih ) ,
" vs-14055: direct item expected(%K), found %h " ,
& end_key , p_le_ih ) ;
2009-03-30 22:02:50 +04:00
tail_size = ( le_ih_k_offset ( p_le_ih ) & ( blk_size - 1 ) )
2005-07-13 07:21:28 +04:00
+ ih_item_len ( p_le_ih ) - 1 ;
2014-04-23 18:00:36 +04:00
/*
* 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 .
2005-07-13 07:21:28 +04:00
*/
if ( ! unbh - > b_page | | buffer_uptodate ( unbh )
| | PageUptodate ( unbh - > b_page ) ) {
up_to_date_bh = NULL ;
} else {
up_to_date_bh = unbh ;
}
2009-03-30 22:02:50 +04:00
retval = reiserfs_delete_item ( th , path , & end_key , inode ,
2005-07-13 07:21:28 +04:00
up_to_date_bh ) ;
2009-03-30 22:02:50 +04:00
total_tail + = retval ;
2014-04-23 18:00:36 +04:00
/* done: file does not have direct items anymore */
2009-03-30 22:02:50 +04:00
if ( tail_size = = retval )
2005-07-13 07:21:28 +04:00
break ;
2005-04-17 02:20:36 +04:00
2005-07-13 07:21:28 +04:00
}
2014-04-23 18:00:36 +04:00
/*
* 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 )
2005-07-13 07:21:28 +04:00
*/
if ( up_to_date_bh ) {
unsigned pgoff =
( tail_offset + total_tail - 1 ) & ( PAGE_CACHE_SIZE - 1 ) ;
2011-11-25 19:14:35 +04:00
char * kaddr = kmap_atomic ( up_to_date_bh - > b_page ) ;
2009-03-30 22:02:50 +04:00
memset ( kaddr + pgoff , 0 , blk_size - total_tail ) ;
2011-11-25 19:14:35 +04:00
kunmap_atomic ( kaddr ) ;
2005-07-13 07:21:28 +04:00
}
REISERFS_I ( inode ) - > i_first_direct_byte = U32_MAX ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
/* stolen from fs/buffer.c */
2005-07-13 07:21:28 +04:00
void reiserfs_unmap_buffer ( struct buffer_head * bh )
{
lock_buffer ( bh ) ;
if ( buffer_journaled ( bh ) | | buffer_journal_dirty ( bh ) ) {
BUG ( ) ;
}
clear_buffer_dirty ( bh ) ;
2014-04-23 18:00:36 +04:00
/*
* 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
*/
2005-07-13 07:21:28 +04:00
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 ) ;
spin_lock ( & j - > j_dirty_buffers_lock ) ;
list_del_init ( & bh - > b_assoc_buffers ) ;
reiserfs_free_jh ( bh ) ;
spin_unlock ( & j - > j_dirty_buffers_lock ) ;
}
clear_buffer_mapped ( bh ) ;
clear_buffer_req ( bh ) ;
clear_buffer_new ( bh ) ;
bh - > b_bdev = NULL ;
unlock_buffer ( bh ) ;
2005-04-17 02:20:36 +04:00
}
2014-04-23 18:00:36 +04:00
/*
* 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
*/
2009-03-30 22:02:47 +04:00
int indirect2direct ( struct reiserfs_transaction_handle * th ,
struct inode * inode , struct page * page ,
2009-03-30 22:02:49 +04:00
struct treepath * path , /* path to the indirect item. */
const struct cpu_key * item_key , /* Key to look for
* unformatted node
* pointer to be cut . */
2005-07-13 07:21:28 +04:00
loff_t n_new_file_size , /* New file size. */
2009-03-30 22:02:49 +04:00
char * mode )
2005-04-17 02:20:36 +04:00
{
2009-03-30 22:02:47 +04:00
struct super_block * sb = inode - > i_sb ;
2005-07-13 07:21:28 +04:00
struct item_head s_ih ;
2009-03-30 22:02:50 +04:00
unsigned long block_size = sb - > s_blocksize ;
2005-07-13 07:21:28 +04:00
char * tail ;
int tail_len , round_tail_len ;
loff_t pos , pos1 ; /* position of first byte of the tail */
struct cpu_key key ;
2005-04-17 02:20:36 +04:00
2005-07-13 07:21:28 +04:00
BUG_ON ( ! th - > t_trans_id ) ;
2005-04-17 02:20:36 +04:00
2009-03-30 22:02:45 +04:00
REISERFS_SB ( sb ) - > s_indirect2direct + + ;
2005-04-17 02:20:36 +04:00
2009-03-30 22:02:49 +04:00
* mode = M_SKIP_BALANCING ;
2005-04-17 02:20:36 +04:00
2005-07-13 07:21:28 +04:00
/* store item head path points to. */
2014-04-23 18:00:35 +04:00
copy_item_head ( & s_ih , tp_item_head ( path ) ) ;
2005-07-13 07:21:28 +04:00
2009-03-30 22:02:50 +04:00
tail_len = ( n_new_file_size & ( block_size - 1 ) ) ;
2009-03-30 22:02:47 +04:00
if ( get_inode_sd_version ( inode ) = = STAT_DATA_V2 )
2005-07-13 07:21:28 +04:00
round_tail_len = ROUND_UP ( tail_len ) ;
else
round_tail_len = tail_len ;
pos =
le_ih_k_offset ( & s_ih ) - 1 + ( ih_item_len ( & s_ih ) / UNFM_P_SIZE -
2009-03-30 22:02:45 +04:00
1 ) * sb - > s_blocksize ;
2005-07-13 07:21:28 +04:00
pos1 = pos ;
2014-04-23 18:00:36 +04:00
/*
* 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
*/
2005-07-13 07:21:28 +04:00
tail = ( char * ) kmap ( page ) ; /* this can schedule */
2009-03-30 22:02:49 +04:00
if ( path_changed ( & s_ih , path ) ) {
2005-07-13 07:21:28 +04:00
/* re-search indirect item */
2009-03-30 22:02:49 +04:00
if ( search_for_position_by_key ( sb , item_key , path )
2005-07-13 07:21:28 +04:00
= = POSITION_NOT_FOUND )
2009-03-30 22:02:45 +04:00
reiserfs_panic ( sb , " PAP-5520 " ,
2005-07-13 07:21:28 +04:00
" item to be converted %K does not exist " ,
2009-03-30 22:02:49 +04:00
item_key ) ;
2014-04-23 18:00:35 +04:00
copy_item_head ( & s_ih , tp_item_head ( path ) ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_REISERFS_CHECK
2005-07-13 07:21:28 +04:00
pos = le_ih_k_offset ( & s_ih ) - 1 +
( ih_item_len ( & s_ih ) / UNFM_P_SIZE -
2009-03-30 22:02:45 +04:00
1 ) * sb - > s_blocksize ;
2005-07-13 07:21:28 +04:00
if ( pos ! = pos1 )
2009-03-30 22:02:45 +04:00
reiserfs_panic ( sb , " vs-5530 " , " tail position "
2009-03-30 22:02:25 +04:00
" changed while we were reading it " ) ;
2005-04-17 02:20:36 +04:00
# endif
2005-07-13 07:21:28 +04:00
}
2005-04-17 02:20:36 +04:00
2005-07-13 07:21:28 +04:00
/* Set direct item header to insert. */
2009-03-30 22:02:47 +04:00
make_le_item_head ( & s_ih , NULL , get_inode_item_key_version ( inode ) ,
2005-07-13 07:21:28 +04:00
pos1 + 1 , TYPE_DIRECT , round_tail_len ,
0xffff /*ih_free_space */ ) ;
2014-04-23 18:00:36 +04:00
/*
* 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
2005-07-13 07:21:28 +04:00
*/
tail = tail + ( pos & ( PAGE_CACHE_SIZE - 1 ) ) ;
2009-03-30 22:02:49 +04:00
PATH_LAST_POSITION ( path ) + + ;
2005-07-13 07:21:28 +04:00
2009-03-30 22:02:49 +04:00
key = * item_key ;
2005-07-13 07:21:28 +04:00
set_cpu_key_k_type ( & key , TYPE_DIRECT ) ;
key . key_length = 4 ;
/* Insert tail as new direct item in the tree */
2009-03-30 22:02:49 +04:00
if ( reiserfs_insert_item ( th , path , & key , & s_ih , inode ,
2005-07-13 07:21:28 +04:00
tail ? tail : NULL ) < 0 ) {
2014-04-23 18:00:36 +04:00
/*
* 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
*/
2005-07-13 07:21:28 +04:00
kunmap ( page ) ;
2009-03-30 22:02:50 +04:00
return block_size - round_tail_len ;
2005-07-13 07:21:28 +04:00
}
kunmap ( page ) ;
2005-04-17 02:20:36 +04:00
2005-07-13 07:21:28 +04:00
/* make sure to get the i_blocks changes from reiserfs_insert_item */
2009-03-30 22:02:47 +04:00
reiserfs_update_sd ( th , inode ) ;
2005-04-17 02:20:36 +04:00
2014-04-23 18:00:36 +04:00
/*
* 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 .
*/
2005-04-17 02:20:36 +04:00
2014-04-23 18:00:36 +04:00
/*
* We have inserted new direct item and must remove last
* unformatted node .
*/
2009-03-30 22:02:49 +04:00
* mode = M_CUT ;
2005-04-17 02:20:36 +04:00
2005-07-13 07:21:28 +04:00
/* we store position of first direct item in the in-core inode */
2009-03-30 22:02:47 +04:00
/* mark_file_with_tail (inode, pos1 + 1); */
REISERFS_I ( inode ) - > i_first_direct_byte = pos1 + 1 ;
2005-04-17 02:20:36 +04:00
2009-03-30 22:02:50 +04:00
return block_size - round_tail_len ;
2005-07-13 07:21:28 +04:00
}