reiserfs_delete_xattrs (inode);
- journal_begin(&th, inode->i_sb, jbegin_count) ;
+ if (journal_begin(&th, inode->i_sb, jbegin_count)) {
+ up (&inode->i_sem);
+ goto out;
+ }
reiserfs_update_inode_transaction(inode) ;
- reiserfs_delete_object (&th, inode);
+ if (reiserfs_delete_object (&th, inode)) {
+ up (&inode->i_sem);
+ goto out;
+ }
- journal_end(&th, inode->i_sb, jbegin_count) ;
+ if (journal_end(&th, inode->i_sb, jbegin_count)) {
+ up (&inode->i_sem);
+ goto out;
+ }
up (&inode->i_sem);
/* all items of file are deleted, so we can remove "save" link */
- remove_save_link (inode, 0/* not truncate */);
+ 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);
return 0;
}
-/*static*/ void restart_transaction(struct reiserfs_transaction_handle *th,
+/*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 ;
+ return 0 ;
}
pathrelse(path) ;
reiserfs_update_sd(th, inode) ;
- journal_end(th, s, len) ;
- journal_begin(th, s, JOURNAL_PER_BALANCE_CNT * 6) ;
- reiserfs_update_inode_transaction(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
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 (ret == 0 && buffer_mapped(bh_result) && bh_result->b_blocknr == 0) {
+ 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
*/
/* 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();
- reiserfs_commit_for_inode(inode);
+ 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 ;
}
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)) {
int reiserfs_get_block (struct inode * inode, sector_t block,
struct buffer_head * bh_result, int create)
{
- int repeat, retval;
+ 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;
** research if we succeed on the second try
*/
SB_JOURNAL(inode->i_sb)->j_next_async_flush = 1;
- restart_transaction(th, inode, &path) ;
+ retval = restart_transaction(th, inode, &path) ;
+ if (retval)
+ goto failure;
repeat = _allocate_block(th, block, inode, &allocated_block_nr, NULL, create);
if (repeat != NO_DISK_SPACE && repeat != QUOTA_EXCEEDED) {
}
set_block_dev_mapped(bh_result, unfm_ptr, inode);
pathrelse (&path);
+ retval = 0;
if (!dangle && th)
- reiserfs_end_persistent_transaction(th);
+ retval = reiserfs_end_persistent_transaction(th);
reiserfs_write_unlock(inode->i_sb);
** there is no need to make sure the inode is updated with this
** transaction
*/
- return 0;
+ return retval;
}
if (!th) {
* ugly, but we can only end the transaction if
* we aren't nested
*/
+ BUG_ON (!th->t_refcount);
if (th->t_refcount == 1) {
- reiserfs_end_persistent_transaction(th);
+ retval = reiserfs_end_persistent_transaction(th);
th = NULL;
+ if (retval)
+ goto failure;
}
retval = convert_tail_for_hole(inode, bh_result, tail_offset) ;
** ending their transaction will be able to continue.
*/
if (journal_transaction_should_end(th, th->t_blocks_allocated)) {
- restart_transaction(th, inode, &path) ;
+ retval = restart_transaction(th, inode, &path) ;
+ if (retval)
+ goto failure;
}
/* inserting indirect pointers for a hole can take a
** long time. reschedule if needed
retval = 0;
failure:
- if (th && !dangle) {
- reiserfs_update_sd(th, inode) ;
- reiserfs_end_persistent_transaction(th);
+ if (th && (!dangle || (retval && !th->t_trans_id))) {
+ int err;
+ if (th->t_trans_id)
+ reiserfs_update_sd(th, inode);
+ err = reiserfs_end_persistent_transaction(th);
+ if (err)
+ retval = err;
}
+
reiserfs_write_unlock(inode->i_sb);
reiserfs_check_path(&path) ;
return retval;
struct item_head *ih, tmp_ih ;
int retval;
+ BUG_ON (!th->t_trans_id);
+
make_cpu_key (&key, inode, SD_OFFSET, TYPE_STAT_DATA, 3);//key type is unimportant
for(;;) {
key.on_disk_key.k_objectid = data[0] ;
key.on_disk_key.k_dir_id = data[1] ;
+ reiserfs_write_lock(sb);
inode = reiserfs_iget(sb, &key) ;
if (inode && !IS_ERR(inode) && data[2] != 0 &&
data[2] != inode->i_generation) {
iput(inode) ;
inode = NULL ;
}
+ reiserfs_write_unlock(sb);
if (!inode)
inode = ERR_PTR(-ESTALE);
if (IS_ERR(inode))
struct reiserfs_transaction_handle th ;
int jbegin_count = 1 ;
- if (inode->i_sb->s_flags & MS_RDONLY) {
- reiserfs_warning (inode->i_sb,
- "clm-6005: writing inode %lu on readonly FS",
- inode->i_ino) ;
+ if (inode->i_sb->s_flags & MS_RDONLY)
return -EROFS;
- }
/* memory pressure can sometimes initiate write_inode calls with sync == 1,
** these cases are just when the system needs ram, not when the
** inode needs to reach disk for safety, and they can safely be
*/
if (do_sync && !(current->flags & PF_MEMALLOC)) {
reiserfs_write_lock(inode->i_sb);
- journal_begin(&th, inode->i_sb, jbegin_count) ;
- reiserfs_update_sd (&th, inode);
- journal_end_sync(&th, inode->i_sb, jbegin_count) ;
+ if (!journal_begin(&th, inode->i_sb, jbegin_count)) {
+ reiserfs_update_sd (&th, inode);
+ journal_end_sync(&th, inode->i_sb, jbegin_count) ;
+ }
reiserfs_write_unlock(inode->i_sb);
}
return 0;
char * body = empty_dir;
struct cpu_key key;
int retval;
+
+ BUG_ON (!th->t_trans_id);
_make_cpu_key (&key, KEY_FORMAT_3_5, le32_to_cpu (ih->ih_key.k_dir_id),
le32_to_cpu (ih->ih_key.k_objectid), DOT_OFFSET, TYPE_DIRENTRY, 3/*key length*/);
struct cpu_key key;
int retval;
+ BUG_ON (!th->t_trans_id);
+
_make_cpu_key (&key, KEY_FORMAT_3_5,
le32_to_cpu (ih->ih_key.k_dir_id),
le32_to_cpu (ih->ih_key.k_objectid),
struct stat_data sd;
int retval;
int err;
+
+ BUG_ON (!th->t_trans_id);
if (!dir || !dir->i_nlink) {
err = -EPERM;
**
** some code taken from block_truncate_page
*/
-void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {
+int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) {
struct reiserfs_transaction_handle th ;
/* we want the offset for the first byte after the end of the file */
unsigned long offset = p_s_inode->i_size & (PAGE_CACHE_SIZE - 1) ;
/* it is enough to reserve space in transaction for 2 balancings:
one for "save" link adding and another for the first
cut_from_item. 1 is for update_sd */
- journal_begin(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1 ) ;
+ error = journal_begin (&th, p_s_inode->i_sb,
+ JOURNAL_PER_BALANCE_CNT * 2 + 1);
+ if (error)
+ goto out;
reiserfs_update_inode_transaction(p_s_inode) ;
if (update_timestamps)
/* we are doing real truncate: if the system crashes before the last
transaction of truncating gets committed - on reboot the file
either appears truncated properly or not truncated at all */
add_save_link (&th, p_s_inode, 1);
- reiserfs_do_truncate (&th, p_s_inode, page, update_timestamps) ;
- journal_end(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1 ) ;
+ error = reiserfs_do_truncate (&th, p_s_inode, page, update_timestamps) ;
+ if (error)
+ goto out;
+ error = journal_end (&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
+ if (error)
+ goto out;
- if (update_timestamps)
- remove_save_link (p_s_inode, 1/* truncate */);
+ if (update_timestamps) {
+ error = remove_save_link (p_s_inode, 1/* truncate */);
+ if (error)
+ goto out;
+ }
if (page) {
length = offset & (blocksize - 1) ;
}
reiserfs_write_unlock(p_s_inode->i_sb);
+ return 0;
+out:
+ if (page) {
+ unlock_page (page);
+ page_cache_release (page);
+ }
+ reiserfs_write_unlock(p_s_inode->i_sb);
+ return error;
}
static int map_block_for_writepage(struct inode *inode,
if (!trans_running) {
/* vs-3050 is gone, no need to drop the path */
- journal_begin(&th, inode->i_sb, jbegin_count) ;
+ retval = journal_begin(&th, inode->i_sb, jbegin_count) ;
+ if (retval)
+ goto out;
reiserfs_update_inode_transaction(inode) ;
trans_running = 1;
if (fs_changed(fs_gen, inode->i_sb) && item_moved(&tmp_ih, &path)) {
out:
pathrelse(&path) ;
if (trans_running) {
- journal_end(&th, inode->i_sb, jbegin_count) ;
+ int err = journal_end(&th, inode->i_sb, jbegin_count) ;
+ if (err)
+ retval = err;
trans_running = 0;
}
reiserfs_write_unlock(inode->i_sb);
if (checked) {
ClearPageChecked(page);
reiserfs_write_lock(s);
- journal_begin(&th, s, bh_per_page + 1);
+ error = journal_begin(&th, s, bh_per_page + 1);
+ if (error) {
+ reiserfs_write_unlock(s);
+ goto fail;
+ }
reiserfs_update_inode_transaction(inode);
}
/* now go through and lock any dirty buffers on the page */
} while((bh = bh->b_this_page) != head);
if (checked) {
- journal_end(&th, s, bh_per_page + 1);
+ error = journal_end(&th, s, bh_per_page + 1);
reiserfs_write_unlock(s);
+ if (error)
+ goto fail;
}
BUG_ON(PageWriteback(page));
set_page_writeback(page);
fix_tail_page_for_writing(page) ;
if (reiserfs_transaction_running(inode->i_sb)) {
struct reiserfs_transaction_handle *th;
- th = (struct reiserfs_transaction_handle *)current->journal_info;
+ th = (struct reiserfs_transaction_handle *)current->journal_info;
+ BUG_ON (!th->t_refcount);
+ BUG_ON (!th->t_trans_id);
old_ref = th->t_refcount;
th->t_refcount++;
}
if (old_ref)
th->t_refcount--;
else {
+ int err;
reiserfs_write_lock(inode->i_sb);
- reiserfs_end_persistent_transaction(th);
+ err = reiserfs_end_persistent_transaction(th);
reiserfs_write_unlock(inode->i_sb);
+ if (err)
+ ret = err;
}
}
}
(have_small_tails (inode->i_sb) && inode->i_size > i_block_size(inode)) )
REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask ;
- journal_begin(&myth, inode->i_sb, 1) ;
+ ret = journal_begin(&myth, inode->i_sb, 1) ;
+ if (ret) {
+ reiserfs_write_unlock(inode->i_sb);
+ goto journal_error;
+ }
reiserfs_update_inode_transaction(inode) ;
inode->i_size = pos ;
reiserfs_update_sd(&myth, inode) ;
update_sd = 1;
- journal_end(&myth, inode->i_sb, 1) ;
+ ret = journal_end(&myth, inode->i_sb, 1) ;
reiserfs_write_unlock(inode->i_sb);
+ if (ret)
+ goto journal_error;
}
if (th) {
reiserfs_write_lock(inode->i_sb);
if (!update_sd)
reiserfs_update_sd(th, inode) ;
- reiserfs_end_persistent_transaction(th);
+ ret = reiserfs_end_persistent_transaction(th);
reiserfs_write_unlock(inode->i_sb);
+ if (ret)
+ goto out;
}
/* we test for O_SYNC here so we can commit the transaction
*/
if (f && (f->f_flags & O_SYNC)) {
reiserfs_write_lock(inode->i_sb);
- reiserfs_commit_for_inode(inode) ;
+ ret = reiserfs_commit_for_inode(inode) ;
reiserfs_write_unlock(inode->i_sb);
}
+out:
return ret ;
+
+journal_error:
+ if (th) {
+ reiserfs_write_lock(inode->i_sb);
+ if (!update_sd)
+ reiserfs_update_sd(th, inode) ;
+ ret = reiserfs_end_persistent_transaction(th);
+ reiserfs_write_unlock(inode->i_sb);
+ }
+
+ return ret;
}
void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode )
if (attr->ia_size > inode->i_size) {
error = generic_cont_expand(inode, attr->ia_size) ;
if (REISERFS_I(inode)->i_prealloc_count > 0) {
+ int err;
struct reiserfs_transaction_handle th ;
/* we're changing at most 2 bitmaps, inode + super */
- journal_begin(&th, inode->i_sb, 4) ;
- reiserfs_discard_prealloc (&th, inode);
- journal_end(&th, inode->i_sb, 4) ;
+ err = journal_begin(&th, inode->i_sb, 4) ;
+ if (!err) {
+ reiserfs_discard_prealloc (&th, inode);
+ err = journal_end(&th, inode->i_sb, 4) ;
+ }
+ if (err)
+ error = err;
}
if (error)
goto out;