aboutsummaryrefslogtreecommitdiff
path: root/fs/reiserfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/reiserfs/inode.c')
-rw-r--r--fs/reiserfs/inode.c4915
1 files changed, 2521 insertions, 2394 deletions
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 289d864fe73..1aaf2c7d44e 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -18,107 +18,109 @@
#include <linux/writeback.h>
#include <linux/quotaops.h>
-extern int reiserfs_default_io_size; /* default io size devuned in super.c */
+extern int reiserfs_default_io_size; /* default io size devuned in super.c */
static int reiserfs_commit_write(struct file *f, struct page *page,
- unsigned from, unsigned to);
+ unsigned from, unsigned to);
static int reiserfs_prepare_write(struct file *f, struct page *page,
unsigned from, unsigned to);
-void reiserfs_delete_inode (struct inode * inode)
+void reiserfs_delete_inode(struct inode *inode)
{
- /* We need blocks for transaction + (user+group) quota update (possibly delete) */
- int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
- struct reiserfs_transaction_handle th ;
-
- reiserfs_write_lock(inode->i_sb);
+ /* We need blocks for transaction + (user+group) quota update (possibly delete) */
+ int jbegin_count =
+ JOURNAL_PER_BALANCE_CNT * 2 +
+ 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
+ struct reiserfs_transaction_handle th;
- /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
- if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
- down (&inode->i_sem);
+ reiserfs_write_lock(inode->i_sb);
- reiserfs_delete_xattrs (inode);
+ /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
+ if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
+ down(&inode->i_sem);
- if (journal_begin(&th, inode->i_sb, jbegin_count)) {
- up (&inode->i_sem);
- goto out;
- }
- reiserfs_update_inode_transaction(inode) ;
+ reiserfs_delete_xattrs(inode);
- if (reiserfs_delete_object (&th, inode)) {
- up (&inode->i_sem);
- goto out;
- }
+ if (journal_begin(&th, inode->i_sb, jbegin_count)) {
+ up(&inode->i_sem);
+ goto out;
+ }
+ reiserfs_update_inode_transaction(inode);
- /* Do quota update inside a transaction for journaled quotas. We must do that
- * after delete_object so that quota updates go into the same transaction as
- * stat data deletion */
- DQUOT_FREE_INODE(inode);
+ if (reiserfs_delete_object(&th, inode)) {
+ up(&inode->i_sem);
+ goto out;
+ }
- if (journal_end(&th, inode->i_sb, jbegin_count)) {
- up (&inode->i_sem);
- goto out;
- }
+ /* Do quota update inside a transaction for journaled quotas. We must do that
+ * after delete_object so that quota updates go into the same transaction as
+ * stat data deletion */
+ DQUOT_FREE_INODE(inode);
+
+ if (journal_end(&th, inode->i_sb, jbegin_count)) {
+ up(&inode->i_sem);
+ goto out;
+ }
- up (&inode->i_sem);
+ up(&inode->i_sem);
- /* all items of file are deleted, so we can remove "save" link */
- remove_save_link (inode, 0/* not truncate */); /* we can't do anything
- * about an error here */
- } else {
- /* no object items are in the tree */
- ;
- }
-out:
- clear_inode (inode); /* note this must go after the journal_end to prevent deadlock */
- inode->i_blocks = 0;
- reiserfs_write_unlock(inode->i_sb);
+ /* all items of file are deleted, so we can remove "save" link */
+ remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything
+ * about an error here */
+ } else {
+ /* no object items are in the tree */
+ ;
+ }
+ out:
+ clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */
+ inode->i_blocks = 0;
+ reiserfs_write_unlock(inode->i_sb);
}
-static void _make_cpu_key (struct cpu_key * key, int version, __u32 dirid, __u32 objectid,
- loff_t offset, int type, int length )
+static void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid,
+ __u32 objectid, loff_t offset, int type, int length)
{
- key->version = version;
+ key->version = version;
- key->on_disk_key.k_dir_id = dirid;
- key->on_disk_key.k_objectid = objectid;
- set_cpu_key_k_offset (key, offset);
- set_cpu_key_k_type (key, type);
- key->key_length = length;
+ key->on_disk_key.k_dir_id = dirid;
+ key->on_disk_key.k_objectid = objectid;
+ set_cpu_key_k_offset(key, offset);
+ set_cpu_key_k_type(key, type);
+ key->key_length = length;
}
-
/* take base of inode_key (it comes from inode always) (dirid, objectid) and version from an inode, set
offset and type of key */
-void make_cpu_key (struct cpu_key * key, struct inode * inode, loff_t offset,
- int type, int length )
+void make_cpu_key(struct cpu_key *key, struct inode *inode, loff_t offset,
+ int type, int length)
{
- _make_cpu_key (key, get_inode_item_key_version (inode), le32_to_cpu (INODE_PKEY (inode)->k_dir_id),
- le32_to_cpu (INODE_PKEY (inode)->k_objectid),
- offset, type, length);
+ _make_cpu_key(key, get_inode_item_key_version(inode),
+ le32_to_cpu(INODE_PKEY(inode)->k_dir_id),
+ le32_to_cpu(INODE_PKEY(inode)->k_objectid), offset, type,
+ length);
}
-
//
// when key is 0, do not set version and short key
//
-inline void make_le_item_head (struct item_head * ih, const struct cpu_key * key,
- int version,
- loff_t offset, int type, int length,
- int entry_count/*or ih_free_space*/)
+inline void make_le_item_head(struct item_head *ih, const struct cpu_key *key,
+ int version,
+ loff_t offset, int type, int length,
+ int entry_count /*or ih_free_space */ )
{
- if (key) {
- ih->ih_key.k_dir_id = cpu_to_le32 (key->on_disk_key.k_dir_id);
- ih->ih_key.k_objectid = cpu_to_le32 (key->on_disk_key.k_objectid);
- }
- put_ih_version( ih, version );
- set_le_ih_k_offset (ih, offset);
- set_le_ih_k_type (ih, type);
- put_ih_item_len( ih, length );
- /* set_ih_free_space (ih, 0);*/
- // for directory items it is entry count, for directs and stat
- // datas - 0xffff, for indirects - 0
- put_ih_entry_count( ih, entry_count );
+ if (key) {
+ ih->ih_key.k_dir_id = cpu_to_le32(key->on_disk_key.k_dir_id);
+ ih->ih_key.k_objectid =
+ cpu_to_le32(key->on_disk_key.k_objectid);
+ }
+ put_ih_version(ih, version);
+ set_le_ih_k_offset(ih, offset);
+ set_le_ih_k_type(ih, type);
+ put_ih_item_len(ih, length);
+ /* set_ih_free_space (ih, 0); */
+ // for directory items it is entry count, for directs and stat
+ // datas - 0xffff, for indirects - 0
+ put_ih_entry_count(ih, entry_count);
}
//
@@ -153,84 +155,84 @@ inline void make_le_item_head (struct item_head * ih, const struct cpu_key * key
** to be unmapped, so that block_prepare_write will correctly call
** reiserfs_get_block to convert the tail into an unformatted node
*/
-static inline void fix_tail_page_for_writing(struct page *page) {
- struct buffer_head *head, *next, *bh ;
-
- if (page && page_has_buffers(page)) {
- head = page_buffers(page) ;
- bh = head ;
- do {
- next = bh->b_this_page ;
- if (buffer_mapped(bh) && bh->b_blocknr == 0) {
- reiserfs_unmap_buffer(bh) ;
- }
- bh = next ;
- } while (bh != head) ;
- }
+static inline void fix_tail_page_for_writing(struct page *page)
+{
+ struct buffer_head *head, *next, *bh;
+
+ if (page && page_has_buffers(page)) {
+ head = page_buffers(page);
+ bh = head;
+ do {
+ next = bh->b_this_page;
+ if (buffer_mapped(bh) && bh->b_blocknr == 0) {
+ reiserfs_unmap_buffer(bh);
+ }
+ bh = next;
+ } while (bh != head);
+ }
}
/* reiserfs_get_block does not need to allocate a block only if it has been
done already or non-hole position has been found in the indirect item */
-static inline int allocation_needed (int retval, b_blocknr_t allocated,
- struct item_head * ih,
- __le32 * item, int pos_in_item)
+static inline int allocation_needed(int retval, b_blocknr_t allocated,
+ struct item_head *ih,
+ __le32 * item, int pos_in_item)
{
- if (allocated)
- return 0;
- if (retval == POSITION_FOUND && is_indirect_le_ih (ih) &&
- get_block_num(item, pos_in_item))
- return 0;
- return 1;
+ if (allocated)
+ return 0;
+ if (retval == POSITION_FOUND && is_indirect_le_ih(ih) &&
+ get_block_num(item, pos_in_item))
+ return 0;
+ return 1;
}
-static inline int indirect_item_found (int retval, struct item_head * ih)
+static inline int indirect_item_found(int retval, struct item_head *ih)
{
- return (retval == POSITION_FOUND) && is_indirect_le_ih (ih);
+ return (retval == POSITION_FOUND) && is_indirect_le_ih(ih);
}
-
-static inline void set_block_dev_mapped (struct buffer_head * bh,
- b_blocknr_t block, struct inode * inode)
+static inline void set_block_dev_mapped(struct buffer_head *bh,
+ b_blocknr_t block, struct inode *inode)
{
map_bh(bh, inode->i_sb, block);
}
-
//
// files which were created in the earlier version can not be longer,
// than 2 gb
//
-static int file_capable (struct inode * inode, long block)
+static int file_capable(struct inode *inode, long block)
{
- if (get_inode_item_key_version (inode) != KEY_FORMAT_3_5 || // it is new file.
- block < (1 << (31 - inode->i_sb->s_blocksize_bits))) // old file, but 'block' is inside of 2gb
- return 1;
+ if (get_inode_item_key_version(inode) != KEY_FORMAT_3_5 || // it is new file.
+ block < (1 << (31 - inode->i_sb->s_blocksize_bits))) // old file, but 'block' is inside of 2gb
+ return 1;
- return 0;
+ return 0;
}
/*static*/ int restart_transaction(struct reiserfs_transaction_handle *th,
- struct inode *inode, struct path *path) {
- struct super_block *s = th->t_super ;
- int len = th->t_blocks_allocated ;
- int err;
-
- BUG_ON (!th->t_trans_id);
- BUG_ON (!th->t_refcount);
-
- /* we cannot restart while nested */
- if (th->t_refcount > 1) {
- return 0 ;
- }
- pathrelse(path) ;
- reiserfs_update_sd(th, inode) ;
- err = journal_end(th, s, len) ;
- if (!err) {
- err = journal_begin(th, s, JOURNAL_PER_BALANCE_CNT * 6) ;
- if (!err)
- reiserfs_update_inode_transaction(inode) ;
- }
- return err;
+ struct inode *inode, struct path *path)
+{
+ struct super_block *s = th->t_super;
+ int len = th->t_blocks_allocated;
+ int err;
+
+ BUG_ON(!th->t_trans_id);
+ BUG_ON(!th->t_refcount);
+
+ /* we cannot restart while nested */
+ if (th->t_refcount > 1) {
+ return 0;
+ }
+ pathrelse(path);
+ reiserfs_update_sd(th, inode);
+ err = journal_end(th, s, len);
+ if (!err) {
+ err = journal_begin(th, s, JOURNAL_PER_BALANCE_CNT * 6);
+ if (!err)
+ reiserfs_update_inode_transaction(inode);
+ }
+ return err;
}
// it is called by get_block when create == 0. Returns block number
@@ -241,190 +243,192 @@ static int file_capable (struct inode * inode, long block)
// Please improve the english/clarity in the comment above, as it is
// hard to understand.
-static int _get_block_create_0 (struct inode * inode, long block,
- struct buffer_head * bh_result,
- int args)
+static int _get_block_create_0(struct inode *inode, long block,
+ struct buffer_head *bh_result, int args)
{
- INITIALIZE_PATH (path);
- struct cpu_key key;
- struct buffer_head * bh;
- struct item_head * ih, tmp_ih;
- int fs_gen ;
- int blocknr;
- char * p = NULL;
- int chars;
- int ret ;
- int result ;
- int done = 0 ;
- unsigned long offset ;
-
- // prepare the key to look for the 'block'-th block of file
- make_cpu_key (&key, inode,
- (loff_t)block * inode->i_sb->s_blocksize + 1, TYPE_ANY, 3);
-
-research:
- result = search_for_position_by_key (inode->i_sb, &key, &path) ;
- if (result != POSITION_FOUND) {
- pathrelse (&path);
- if (p)
- kunmap(bh_result->b_page) ;
- if (result == IO_ERROR)
- return -EIO;
- // We do not return -ENOENT if there is a hole but page is uptodate, because it means
- // That there is some MMAPED data associated with it that is yet to be written to disk.
- if ((args & GET_BLOCK_NO_HOLE) && !PageUptodate(bh_result->b_page) ) {
- return -ENOENT ;
- }
- return 0 ;
- }
-
- //
- bh = get_last_bh (&path);
- ih = get_ih (&path);
- if (is_indirect_le_ih (ih)) {
- __le32 * ind_item = (__le32 *)B_I_PITEM (bh, ih);
-
- /* FIXME: here we could cache indirect item or part of it in
- the inode to avoid search_by_key in case of subsequent
- access to file */
- blocknr = get_block_num(ind_item, path.pos_in_item) ;
- ret = 0 ;
- if (blocknr) {
- map_bh(bh_result, inode->i_sb, blocknr);
- if (path.pos_in_item == ((ih_item_len(ih) / UNFM_P_SIZE) - 1)) {
- set_buffer_boundary(bh_result);
- }
- } else
- // We do not return -ENOENT if there is a hole but page is uptodate, because it means
- // That there is some MMAPED data associated with it that is yet to be written to disk.
- if ((args & GET_BLOCK_NO_HOLE) && !PageUptodate(bh_result->b_page) ) {
- ret = -ENOENT ;
- }
-
- pathrelse (&path);
- if (p)
- kunmap(bh_result->b_page) ;
- return ret ;
- }
-
- // requested data are in direct item(s)
- if (!(args & GET_BLOCK_READ_DIRECT)) {
- // we are called by bmap. FIXME: we can not map block of file
- // when it is stored in direct item(s)
- pathrelse (&path);
- if (p)
- kunmap(bh_result->b_page) ;
- return -ENOENT;
- }
-
- /* if we've got a direct item, and the buffer or page was uptodate,
- ** we don't want to pull data off disk again. skip to the
- ** end, where we map the buffer and return
- */
- if (buffer_uptodate(bh_result)) {
- goto finished ;
- } else
- /*
- ** grab_tail_page can trigger calls to reiserfs_get_block on up to date
- ** pages without any buffers. If the page is up to date, we don't want
- ** read old data off disk. Set the up to date bit on the buffer instead
- ** and jump to the end
- */
- if (!bh_result->b_page || PageUptodate(bh_result->b_page)) {
+ INITIALIZE_PATH(path);
+ struct cpu_key key;
+ struct buffer_head *bh;
+ struct item_head *ih, tmp_ih;
+ int fs_gen;
+ int blocknr;
+ char *p = NULL;
+ int chars;
+ int ret;
+ int result;
+ int done = 0;
+ unsigned long offset;
+
+ // prepare the key to look for the 'block'-th block of file
+ make_cpu_key(&key, inode,
+ (loff_t) block * inode->i_sb->s_blocksize + 1, TYPE_ANY,
+ 3);
+
+ research:
+ result = search_for_position_by_key(inode->i_sb, &key, &path);
+ if (result != POSITION_FOUND) {
+ pathrelse(&path);
+ if (p)
+ kunmap(bh_result->b_page);
+ if (result == IO_ERROR)
+ return -EIO;
+ // We do not return -ENOENT if there is a hole but page is uptodate, because it means
+ // That there is some MMAPED data associated with it that is yet to be written to disk.
+ if ((args & GET_BLOCK_NO_HOLE)
+ && !PageUptodate(bh_result->b_page)) {
+ return -ENOENT;
+ }
+ return 0;
+ }
+ //
+ bh = get_last_bh(&path);
+ ih = get_ih(&path);
+ if (is_indirect_le_ih(ih)) {
+ __le32 *ind_item = (__le32 *) B_I_PITEM(bh, ih);
+
+ /* FIXME: here we could cache indirect item or part of it in
+ the inode to avoid search_by_key in case of subsequent
+ access to file */
+ blocknr = get_block_num(ind_item, path.pos_in_item);
+ ret = 0;
+ if (blocknr) {
+ map_bh(bh_result, inode->i_sb, blocknr);
+ if (path.pos_in_item ==
+ ((ih_item_len(ih) / UNFM_P_SIZE) - 1)) {
+ set_buffer_boundary(bh_result);
+ }
+ } else
+ // We do not return -ENOENT if there is a hole but page is uptodate, because it means
+ // That there is some MMAPED data associated with it that is yet to be written to disk.
+ if ((args & GET_BLOCK_NO_HOLE)
+ && !PageUptodate(bh_result->b_page)) {
+ ret = -ENOENT;
+ }
+
+ pathrelse(&path);
+ if (p)
+ kunmap(bh_result->b_page);
+ return ret;
+ }
+ // requested data are in direct item(s)
+ if (!(args & GET_BLOCK_READ_DIRECT)) {
+ // we are called by bmap. FIXME: we can not map block of file
+ // when it is stored in direct item(s)
+ pathrelse(&path);
+ if (p)
+ kunmap(bh_result->b_page);
+ return -ENOENT;
+ }
+
+ /* if we've got a direct item, and the buffer or page was uptodate,
+ ** we don't want to pull data off disk again. skip to the
+ ** end, where we map the buffer and return
+ */
+ if (buffer_uptodate(bh_result)) {
+ goto finished;
+ } else
+ /*
+ ** grab_tail_page can trigger calls to reiserfs_get_block on up to date
+ ** pages without any buffers. If the page is up to date, we don't want
+ ** read old data off disk. Set the up to date bit on the buffer instead
+ ** and jump to the end
+ */
+ if (!bh_result->b_page || PageUptodate(bh_result->b_page)) {
set_buffer_uptodate(bh_result);
- goto finished ;
- }
-
- // read file tail into part of page
- offset = (cpu_key_k_offset(&key) - 1) & (PAGE_CACHE_SIZE - 1) ;
- fs_gen = get_generation(inode->i_sb) ;
- copy_item_head (&tmp_ih, ih);
-
- /* we only want to kmap if we are reading the tail into the page.
- ** this is not the common case, so we don't kmap until we are
- ** sure we need to. But, this means the item might move if
- ** kmap schedules
- */
- if (!p) {
- p = (char *)kmap(bh_result->b_page) ;
- if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {
- goto research;
- }
- }
- p += offset ;
- memset (p, 0, inode->i_sb->s_blocksize);
- do {
- if (!is_direct_le_ih (ih)) {
- BUG ();
- }
- /* make sure we don't read more bytes than actually exist in
- ** the file. This can happen in odd cases where i_size isn't
- ** correct, and when direct item padding results in a few
- ** extra bytes at the end of the direct item
- */
- if ((le_ih_k_offset(ih) + path.pos_in_item) > inode->i_size)
- break ;
- if ((le_ih_k_offset(ih) - 1 + ih_item_len(ih)) > inode->i_size) {
- chars = inode->i_size - (le_ih_k_offset(ih) - 1) - path.pos_in_item;
- done = 1 ;
- } else {
- chars = ih_item_len(ih) - path.pos_in_item;
- }
- memcpy (p, B_I_PITEM (bh, ih) + path.pos_in_item, chars);
-
- if (done)
- break ;
-
- p += chars;
-
- if (PATH_LAST_POSITION (&path) != (B_NR_ITEMS (bh) - 1))
- // we done, if read direct item is not the last item of
- // node FIXME: we could try to check right delimiting key
- // to see whether direct item continues in the right
- // neighbor or rely on i_size
- break;
-
- // update key to look for the next piece
- set_cpu_key_k_offset (&key, cpu_key_k_offset (&key) + chars);
- result = search_for_position_by_key (inode->i_sb, &key, &path);
- if (result != POSITION_FOUND)
- // i/o error most likely
- break;
- bh = get_last_bh (&path);
- ih = get_ih (&path);
- } while (1);
-
- flush_dcache_page(bh_result->b_page) ;
- kunmap(bh_result->b_page) ;
-
-finished:
- pathrelse (&path);
-
- if (result == IO_ERROR)
- return -EIO;
-
- /* this buffer has valid data, but isn't valid for io. mapping it to
- * block #0 tells the rest of reiserfs it just has a tail in it
- */
- map_bh(bh_result, inode->i_sb, 0);
- set_buffer_uptodate (bh_result);
- return 0;
-}
+ goto finished;
+ }
+ // read file tail into part of page
+ offset = (cpu_key_k_offset(&key) - 1) & (PAGE_CACHE_SIZE - 1);
+ fs_gen = get_generation(inode->i_sb);
+ copy_item_head(&tmp_ih, ih);
+
+ /* we only want to kmap if we are reading the tail into the page.
+ ** this is not the common case, so we don't kmap until we are
+ ** sure we need to. But, this means the item might move if
+ ** kmap schedules
+ */
+ if (!p) {
+ p = (char *)kmap(bh_result->b_page);
+ if (fs_changed(fs_gen, inode->i_sb)
+ && item_moved(&tmp_ih, &path)) {
+ goto research;
+ }
+ }
+ p += offset;
+ memset(p, 0, inode->i_sb->s_blocksize);
+ do {
+ if (!is_direct_le_ih(ih)) {
+ BUG();
+ }
+ /* make sure we don't read more bytes than actually exist in
+ ** the file. This can happen in odd cases where i_size isn't
+ ** correct, and when direct item padding results in a few
+ ** extra bytes at the end of the direct item
+ */
+ if ((le_ih_k_offset(ih) + path.pos_in_item) > inode->i_size)
+ break;
+ if ((le_ih_k_offset(ih) - 1 + ih_item_len(ih)) > inode->i_size) {
+ chars =
+ inode->i_size - (le_ih_k_offset(ih) - 1) -
+ path.pos_in_item;
+ done = 1;
+ } else {
+ chars = ih_item_len(ih) - path.pos_in_item;
+ }
+ memcpy(p, B_I_PITEM(bh, ih) + path.pos_in_item, chars);
+
+ if (done)
+ break;
+
+ p += chars;
+
+ if (PATH_LAST_POSITION(&path) != (B_NR_ITEMS(bh) - 1))
+ // we done, if read direct item is not the last item of
+ // node FIXME: we could try to check right delimiting key
+ // to see whether direct item continues in the right
+ // neighbor or rely on i_size
+ break;
+
+ // update key to look for the next piece
+ set_cpu_key_k_offset(&key, cpu_key_k_offset(&key) + chars);
+ result = search_for_position_by_key(inode->i_sb, &key, &path);
+ if (result != POSITION_FOUND)
+ // i/o error most likely
+ break;
+ bh = get_last_bh(&path);
+ ih = get_ih(&path);
+ } while (1);
+
+ flush_dcache_page(bh_result->b_page);
+ kunmap(bh_result->b_page);
+
+ finished:
+ pathrelse(&path);
+
+ if (result == IO_ERROR)
+ return -EIO;
+ /* this buffer has valid data, but isn't valid for io. mapping it to
+ * block #0 tells the rest of reiserfs it just has a tail in it
+ */
+ map_bh(bh_result, inode->i_sb, 0);
+ set_buffer_uptodate(bh_result);
+ return 0;
+}
// this is called to create file map. So, _get_block_create_0 will not
// read direct item
-static int reiserfs_bmap (struct inode * inode, sector_t block,
- struct buffer_head * bh_result, int create)
+static int reiserfs_bmap(struct inode *inode, sector_t block,
+ struct buffer_head *bh_result, int create)
{
- if (!file_capable (inode, block))
- return -EFBIG;
-
- reiserfs_write_lock(inode->i_sb);
- /* do not read the direct item */
- _get_block_create_0 (inode, block, bh_result, 0) ;
- reiserfs_write_unlock(inode->i_sb);
- return 0;
+ if (!file_capable(inode, block))
+ return -EFBIG;
+
+ reiserfs_write_lock(inode->i_sb);
+ /* do not read the direct item */
+ _get_block_create_0(inode, block, bh_result, 0);
+ reiserfs_write_unlock(inode->i_sb);
+ return 0;
}
/* special version of get_block that is only used by grab_tail_page right
@@ -444,9 +448,11 @@ static int reiserfs_bmap (struct inode * inode, sector_t block,
** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block,
** don't use this function.
*/
-static int reiserfs_get_block_create_0 (struct inode * inode, sector_t block,
- struct buffer_head * bh_result, int create) {
- return reiserfs_get_block(inode, block, bh_result, GET_BLOCK_NO_HOLE) ;
+static int reiserfs_get_block_create_0(struct inode *inode, sector_t block,
+ struct buffer_head *bh_result,
+ int create)
+{
+ return reiserfs_get_block(inode, block, bh_result, GET_BLOCK_NO_HOLE);
}
/* This is special helper for reiserfs_get_block in case we are executing
@@ -457,43 +463,42 @@ static int reiserfs_get_blocks_direct_io(struct inode *inode,
struct buffer_head *bh_result,
int create)
{
- int ret ;
-
- bh_result->b_page = NULL;
-
- /* We set the b_size before reiserfs_get_block call since it is
- referenced in convert_tail_for_hole() that may be called from
- reiserfs_get_block() */
- bh_result->b_size = (1 << inode->i_blkbits);
-
- ret = reiserfs_get_block(inode, iblock, bh_result,
- create | GET_BLOCK_NO_DANGLE) ;
- if (ret)
- goto out;
-
- /* don't allow direct io onto tail pages */
- if (buffer_mapped(bh_result) && bh_result->b_blocknr == 0) {
- /* make sure future calls to the direct io funcs for this offset
- ** in the file fail by unmapping the buffer
- */
- clear_buffer_mapped(bh_result);
- ret = -EINVAL ;
- }
- /* Possible unpacked tail. Flush the data before pages have
- disappeared */
- if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) {
- int err;
- lock_kernel();
- err = reiserfs_commit_for_inode(inode);
- REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
- unlock_kernel();
- if (err < 0)
- ret = err;
- }
-out:
- return ret ;
-}
+ int ret;
+
+ bh_result->b_page = NULL;
+ /* We set the b_size before reiserfs_get_block call since it is
+ referenced in convert_tail_for_hole() that may be called from
+ reiserfs_get_block() */
+ bh_result->b_size = (1 << inode->i_blkbits);
+
+ ret = reiserfs_get_block(inode, iblock, bh_result,
+ create | GET_BLOCK_NO_DANGLE);
+ if (ret)
+ goto out;
+
+ /* don't allow direct io onto tail pages */
+ if (buffer_mapped(bh_result) && bh_result->b_blocknr == 0) {
+ /* make sure future calls to the direct io funcs for this offset
+ ** in the file fail by unmapping the buffer
+ */
+ clear_buffer_mapped(bh_result);
+ ret = -EINVAL;
+ }
+ /* Possible unpacked tail. Flush the data before pages have
+ disappeared */
+ if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) {
+ int err;
+ lock_kernel();
+ err = reiserfs_commit_for_inode(inode);
+ REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
+ unlock_kernel();
+ if (err < 0)
+ ret = err;
+ }
+ out:
+ return ret;
+}
/*
** helper function for when reiserfs_get_block is called for a hole
@@ -505,490 +510,547 @@ out:
** you should not be in a transaction, or have any paths held when you
** call this.
*/
-static int convert_tail_for_hole(struct inode *inode,
- struct buffer_head *bh_result,
- loff_t tail_offset) {
- unsigned long index ;
- unsigned long tail_end ;
- unsigned long tail_start ;
- struct page * tail_page ;
- struct page * hole_page = bh_result->b_page ;
- int retval = 0 ;
-
- if ((tail_offset & (bh_result->b_size - 1)) != 1)
- return -EIO ;
-
- /* always try to read until the end of the block */
- tail_start = tail_offset & (PAGE_CACHE_SIZE - 1) ;
- tail_end = (tail_start | (bh_result->b_size - 1)) + 1 ;
-
- index = tail_offset >> PAGE_CACHE_SHIFT ;
- /* hole_page can be zero in case of direct_io, we are sure
- that we cannot get here if we write with O_DIRECT into
- tail page */
- if (!hole_page || index != hole_page->index) {
- tail_page = grab_cache_page(inode->i_mapping, index) ;
- retval = -ENOMEM;
- if (!tail_page) {
- goto out ;
- }
- } else {
- tail_page = hole_page ;
- }
-
- /* we don't have to make sure the conversion did not happen while
- ** we were locking the page because anyone that could convert
- ** must first take i_sem.
- **
- ** We must fix the tail page for writing because it might have buffers
- ** that are mapped, but have a block number of 0. This indicates tail
- ** data that has been read directly into the page, and block_prepare_write
- ** won't trigger a get_block in this case.
- */
- fix_tail_page_for_writing(tail_page) ;
- retval = reiserfs_prepare_write(NULL, tail_page, tail_start, tail_end);
- if (retval)
- goto unlock ;
-
- /* tail conversion might change the data in the page */
- flush_dcache_page(tail_page) ;
-
- retval = reiserfs_commit_write(NULL, tail_page, tail_start, tail_end) ;
-
-unlock:
- if (tail_page != hole_page) {
- unlock_page(tail_page) ;
- page_cache_release(tail_page) ;
- }
-out:
- return retval ;
+static int convert_tail_for_hole(struct inode *inode,
+ struct buffer_head *bh_result,
+ loff_t tail_offset)
+{
+ unsigned long index;
+ unsigned long tail_end;
+ unsigned long tail_start;
+ struct page *tail_page;
+ struct page *hole_page = bh_result->b_page;
+ int retval = 0;
+
+ if ((tail_offset & (bh_result->b_size - 1)) != 1)
+ return -EIO;
+
+ /* always try to read until the end of the block */
+ tail_start = tail_offset & (PAGE_CACHE_SIZE - 1);
+ tail_end = (tail_start | (bh_result->b_size - 1)) + 1;
+
+ index = tail_offset >> PAGE_CACHE_SHIFT;
+ /* hole_page can be zero in case of direct_io, we are sure
+ that we cannot get here if we write with O_DIRECT into
+ tail page */
+ if (!hole_page || index != hole_page->index) {
+ tail_page = grab_cache_page(inode->i_mapping, index);
+ retval = -ENOMEM;
+ if (!tail_page) {
+ goto out;
+ }
+ } else {
+ tail_page = hole_page;
+ }
+
+ /* we don't have to make sure the conversion did not happen while
+ ** we were locking the page because anyone that could convert
+ ** must first take i_sem.
+ **
+ ** We must fix the tail page for writing because it might have buffers
+ ** that are mapped, but have a block number of 0. This indicates tail
+ ** data that has been read directly into the page, and block_prepare_write
+ ** won't trigger a get_block in this case.
+ */
+ fix_tail_page_for_writing(tail_page);
+ retval = reiserfs_prepare_write(NULL, tail_page, tail_start, tail_end);
+ if (retval)
+ goto unlock;
+
+ /* tail conversion might change the data in the page */
+ flush_dcache_page(tail_page);
+
+ retval = reiserfs_commit_write(NULL, tail_page, tail_start, tail_end);
+
+ unlock:
+ if (tail_page != hole_page) {
+ unlock_page(tail_page);
+ page_cache_release(tail_page);
+ }
+ out:
+ return retval;
}
static inline int _allocate_block(struct reiserfs_transaction_handle *th,
- long block,
- struct inode *inode,
- b_blocknr_t *allocated_block_nr,
- struct path * path,
- int flags) {
- BUG_ON (!th->t_trans_id);
-
+ long block,
+ struct inode *inode,
+ b_blocknr_t * allocated_block_nr,
+ struct path *path, int flags)
+{
+ BUG_ON(!th->t_trans_id);
+
#ifdef REISERFS_PREALLOCATE
- if (!(flags & GET_BLOCK_NO_ISEM)) {
- return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr, path, block);
- }
+ if (!(flags & GET_BLOCK_NO_ISEM)) {
+ return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr,
+ path, block);
+ }
#endif
- return reiserfs_new_unf_blocknrs (th, inode, allocated_block_nr, path, block);
+ return reiserfs_new_unf_blocknrs(th, inode, allocated_block_nr, path,
+ block);
}
-int reiserfs_get_block (struct inode * inode, sector_t block,
- struct buffer_head * bh_result, int create)
+int reiserfs_get_block(struct inode *inode, sector_t block,
+ struct buffer_head *bh_result, int create)
{
- int repeat, retval = 0;
- b_blocknr_t allocated_block_nr = 0;// b_blocknr_t is (unsigned) 32 bit int
- INITIALIZE_PATH(path);
- int pos_in_item;
- struct cpu_key key;
- struct buffer_head * bh, * unbh = NULL;
- struct item_head * ih, tmp_ih;
- __le32 * item;
- int done;
- int fs_gen;
- struct reiserfs_transaction_handle *th = NULL;
- /* space reserved in transaction batch:
- . 3 balancings in direct->indirect conversion
- . 1 block involved into reiserfs_update_sd()
- XXX in practically impossible worst case direct2indirect()
- can incur (much) more than 3 balancings.
- quota update for user, group */
- int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);
- int version;
- int dangle = 1;
- loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ;
-
- /* bad.... */
- reiserfs_write_lock(inode->i_sb);
- version = get_inode_item_key_version (inode);
-
- if (block < 0) {
- reiserfs_write_unlock(inode->i_sb);
- return -EIO;
- }
+ int repeat, retval = 0;
+ b_blocknr_t allocated_block_nr = 0; // b_blocknr_t is (unsigned) 32 bit int
+ INITIALIZE_PATH(path);
+ int pos_in_item;
+ struct cpu_key key;
+ struct buffer_head *bh, *unbh = NULL;
+ struct item_head *ih, tmp_ih;
+ __le32 *item;
+ int done;
+ int fs_gen;
+ struct reiserfs_transaction_handle *th = NULL;
+ /* space reserved in transaction batch:
+ . 3 balancings in direct->indirect conversion
+ . 1 block involved into reiserfs_update_sd()
+ XXX in practically impossible worst case direct2indirect()
+ can incur (much) more than 3 balancings.
+ quota update for user, group */
+ int jbegin_count =
+ JOURNAL_PER_BALANCE_CNT * 3 + 1 +
+ 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);
+ int version;
+ int dangle = 1;
+ loff_t new_offset =
+ (((loff_t) block) << inode->i_sb->s_blocksize_bits) + 1;
+
+ /* bad.... */
+ reiserfs_write_lock(inode->i_sb);
+ version = get_inode_item_key_version(inode);
- if (!file_capable (inode, block)) {
- reiserfs_write_unlock(inode->i_sb);
- return -EFBIG;
- }
-
- /* if !create, we aren't changing the FS, so we don't need to
- ** log anything, so we don't need to start a transaction
- */
- if (!(create & GET_BLOCK_CREATE)) {
- int ret ;
- /* find number of block-th logical block of the file */
- ret = _get_block_create_0 (inode, block, bh_result,
- create | GET_BLOCK_READ_DIRECT) ;
- reiserfs_write_unlock(inode->i_sb);
- return ret;
- }
- /*
- * if we're already in a transaction, make sure to close
- * any new transactions we start in this func
- */
- if ((create & GET_BLOCK_NO_DANGLE) ||
- reiserfs_transaction_running(inode->i_sb))
- dangle = 0;
-
- /* If file is of such a size, that it might have a tail and tails are enabled
- ** we should mark it as possibly needing tail packing on close
- */
- if ( (have_large_tails (inode->i_sb) && inode->i_size < i_block_size (inode)*4) ||
- (have_small_tails (inode->i_sb) && inode->i_size < i_block_size(inode)) )
- REISERFS_I(inode)->i_flags |= i_pack_on_close_mask ;
-
- /* set the key of the first byte in the 'block'-th block of file */
- make_cpu_key (&key, inode, new_offset,
- TYPE_ANY, 3/*key length*/);
- if ((new_offset + inode->i_sb->s_blocksize - 1) > inode->i_size) {
-start_trans:
- th = reiserfs_persistent_transaction(inode->i_sb, jbegin_count);
- if (!th) {
- retval = -ENOMEM;
- goto failure;
- }
- reiserfs_update_inode_transaction(inode) ;
- }
- research:
-
- retval = search_for_position_by_key (inode->i_sb, &key, &path);
- if (retval == IO_ERROR) {
- retval = -EIO;
- goto failure;
- }
-
- bh = get_last_bh (&path);
- ih = get_ih (&path);
- item = get_item (&path);
- pos_in_item = path.pos_in_item;
-
- fs_gen = get_generation (inode->i_sb);
- copy_item_head (&tmp_ih, ih);
-
- if (allocation_needed (retval, allocated_block_nr, ih, item, pos_in_item)) {
- /* we have to allocate block for the unformatted node */
- if (!th) {
- pathrelse(&path) ;
- goto start_trans;
- }
-
- repeat = _allocate_block(th, block, inode, &allocated_block_nr, &path, create);
-
- if (repeat == NO_DISK_SPACE || repeat == QUOTA_EXCEEDED) {
- /* restart the transaction to give the journal a chance to free
- ** some blocks. releases the path, so we have to go back to
- ** research if we succeed on the second try
- */
- SB_JOURNAL(inode->i_sb)->j_next_async_flush = 1;
- retval = restart_transaction(th, i