162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/time.h> 662306a36Sopenharmony_ci#include <linux/fs.h> 762306a36Sopenharmony_ci#include "reiserfs.h" 862306a36Sopenharmony_ci#include "acl.h" 962306a36Sopenharmony_ci#include "xattr.h" 1062306a36Sopenharmony_ci#include <linux/exportfs.h> 1162306a36Sopenharmony_ci#include <linux/pagemap.h> 1262306a36Sopenharmony_ci#include <linux/highmem.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/uaccess.h> 1562306a36Sopenharmony_ci#include <asm/unaligned.h> 1662306a36Sopenharmony_ci#include <linux/buffer_head.h> 1762306a36Sopenharmony_ci#include <linux/mpage.h> 1862306a36Sopenharmony_ci#include <linux/writeback.h> 1962306a36Sopenharmony_ci#include <linux/quotaops.h> 2062306a36Sopenharmony_ci#include <linux/swap.h> 2162306a36Sopenharmony_ci#include <linux/uio.h> 2262306a36Sopenharmony_ci#include <linux/bio.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciint reiserfs_commit_write(struct file *f, struct page *page, 2562306a36Sopenharmony_ci unsigned from, unsigned to); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_civoid reiserfs_evict_inode(struct inode *inode) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci /* 3062306a36Sopenharmony_ci * We need blocks for transaction + (user+group) quota 3162306a36Sopenharmony_ci * update (possibly delete) 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci int jbegin_count = 3462306a36Sopenharmony_ci JOURNAL_PER_BALANCE_CNT * 2 + 3562306a36Sopenharmony_ci 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb); 3662306a36Sopenharmony_ci struct reiserfs_transaction_handle th; 3762306a36Sopenharmony_ci int err; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci if (!inode->i_nlink && !is_bad_inode(inode)) 4062306a36Sopenharmony_ci dquot_initialize(inode); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci truncate_inode_pages_final(&inode->i_data); 4362306a36Sopenharmony_ci if (inode->i_nlink) 4462306a36Sopenharmony_ci goto no_delete; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci /* 4762306a36Sopenharmony_ci * The = 0 happens when we abort creating a new inode 4862306a36Sopenharmony_ci * for some reason like lack of space.. 4962306a36Sopenharmony_ci * also handles bad_inode case 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci reiserfs_delete_xattrs(inode); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci if (journal_begin(&th, inode->i_sb, jbegin_count)) 5862306a36Sopenharmony_ci goto out; 5962306a36Sopenharmony_ci reiserfs_update_inode_transaction(inode); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci reiserfs_discard_prealloc(&th, inode); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci err = reiserfs_delete_object(&th, inode); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci /* 6662306a36Sopenharmony_ci * Do quota update inside a transaction for journaled quotas. 6762306a36Sopenharmony_ci * We must do that after delete_object so that quota updates 6862306a36Sopenharmony_ci * go into the same transaction as stat data deletion 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_ci if (!err) { 7162306a36Sopenharmony_ci int depth = reiserfs_write_unlock_nested(inode->i_sb); 7262306a36Sopenharmony_ci dquot_free_inode(inode); 7362306a36Sopenharmony_ci reiserfs_write_lock_nested(inode->i_sb, depth); 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (journal_end(&th)) 7762306a36Sopenharmony_ci goto out; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* 8062306a36Sopenharmony_ci * check return value from reiserfs_delete_object after 8162306a36Sopenharmony_ci * ending the transaction 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci if (err) 8462306a36Sopenharmony_ci goto out; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* 8762306a36Sopenharmony_ci * all items of file are deleted, so we can remove 8862306a36Sopenharmony_ci * "save" link 8962306a36Sopenharmony_ci * we can't do anything about an error here 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_ci remove_save_link(inode, 0 /* not truncate */); 9262306a36Sopenharmony_ciout: 9362306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 9462306a36Sopenharmony_ci } else { 9562306a36Sopenharmony_ci /* no object items are in the tree */ 9662306a36Sopenharmony_ci ; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* note this must go after the journal_end to prevent deadlock */ 10062306a36Sopenharmony_ci clear_inode(inode); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci dquot_drop(inode); 10362306a36Sopenharmony_ci inode->i_blocks = 0; 10462306a36Sopenharmony_ci return; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cino_delete: 10762306a36Sopenharmony_ci clear_inode(inode); 10862306a36Sopenharmony_ci dquot_drop(inode); 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid, 11262306a36Sopenharmony_ci __u32 objectid, loff_t offset, int type, int length) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci key->version = version; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci key->on_disk_key.k_dir_id = dirid; 11762306a36Sopenharmony_ci key->on_disk_key.k_objectid = objectid; 11862306a36Sopenharmony_ci set_cpu_key_k_offset(key, offset); 11962306a36Sopenharmony_ci set_cpu_key_k_type(key, type); 12062306a36Sopenharmony_ci key->key_length = length; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/* 12462306a36Sopenharmony_ci * take base of inode_key (it comes from inode always) (dirid, objectid) 12562306a36Sopenharmony_ci * and version from an inode, set offset and type of key 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_civoid make_cpu_key(struct cpu_key *key, struct inode *inode, loff_t offset, 12862306a36Sopenharmony_ci int type, int length) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci _make_cpu_key(key, get_inode_item_key_version(inode), 13162306a36Sopenharmony_ci le32_to_cpu(INODE_PKEY(inode)->k_dir_id), 13262306a36Sopenharmony_ci le32_to_cpu(INODE_PKEY(inode)->k_objectid), offset, type, 13362306a36Sopenharmony_ci length); 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/* when key is 0, do not set version and short key */ 13762306a36Sopenharmony_ciinline void make_le_item_head(struct item_head *ih, const struct cpu_key *key, 13862306a36Sopenharmony_ci int version, 13962306a36Sopenharmony_ci loff_t offset, int type, int length, 14062306a36Sopenharmony_ci int entry_count /*or ih_free_space */ ) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci if (key) { 14362306a36Sopenharmony_ci ih->ih_key.k_dir_id = cpu_to_le32(key->on_disk_key.k_dir_id); 14462306a36Sopenharmony_ci ih->ih_key.k_objectid = 14562306a36Sopenharmony_ci cpu_to_le32(key->on_disk_key.k_objectid); 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci put_ih_version(ih, version); 14862306a36Sopenharmony_ci set_le_ih_k_offset(ih, offset); 14962306a36Sopenharmony_ci set_le_ih_k_type(ih, type); 15062306a36Sopenharmony_ci put_ih_item_len(ih, length); 15162306a36Sopenharmony_ci /* set_ih_free_space (ih, 0); */ 15262306a36Sopenharmony_ci /* 15362306a36Sopenharmony_ci * for directory items it is entry count, for directs and stat 15462306a36Sopenharmony_ci * datas - 0xffff, for indirects - 0 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ci put_ih_entry_count(ih, entry_count); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/* 16062306a36Sopenharmony_ci * FIXME: we might cache recently accessed indirect item 16162306a36Sopenharmony_ci * Ugh. Not too eager for that.... 16262306a36Sopenharmony_ci * I cut the code until such time as I see a convincing argument (benchmark). 16362306a36Sopenharmony_ci * I don't want a bloated inode struct..., and I don't like code complexity.... 16462306a36Sopenharmony_ci */ 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci/* 16762306a36Sopenharmony_ci * cutting the code is fine, since it really isn't in use yet and is easy 16862306a36Sopenharmony_ci * to add back in. But, Vladimir has a really good idea here. Think 16962306a36Sopenharmony_ci * about what happens for reading a file. For each page, 17062306a36Sopenharmony_ci * The VFS layer calls reiserfs_read_folio, who searches the tree to find 17162306a36Sopenharmony_ci * an indirect item. This indirect item has X number of pointers, where 17262306a36Sopenharmony_ci * X is a big number if we've done the block allocation right. But, 17362306a36Sopenharmony_ci * we only use one or two of these pointers during each call to read_folio, 17462306a36Sopenharmony_ci * needlessly researching again later on. 17562306a36Sopenharmony_ci * 17662306a36Sopenharmony_ci * The size of the cache could be dynamic based on the size of the file. 17762306a36Sopenharmony_ci * 17862306a36Sopenharmony_ci * I'd also like to see us cache the location the stat data item, since 17962306a36Sopenharmony_ci * we are needlessly researching for that frequently. 18062306a36Sopenharmony_ci * 18162306a36Sopenharmony_ci * --chris 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci/* 18562306a36Sopenharmony_ci * If this page has a file tail in it, and 18662306a36Sopenharmony_ci * it was read in by get_block_create_0, the page data is valid, 18762306a36Sopenharmony_ci * but tail is still sitting in a direct item, and we can't write to 18862306a36Sopenharmony_ci * it. So, look through this page, and check all the mapped buffers 18962306a36Sopenharmony_ci * to make sure they have valid block numbers. Any that don't need 19062306a36Sopenharmony_ci * to be unmapped, so that __block_write_begin will correctly call 19162306a36Sopenharmony_ci * reiserfs_get_block to convert the tail into an unformatted node 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_cistatic inline void fix_tail_page_for_writing(struct page *page) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci struct buffer_head *head, *next, *bh; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (page && page_has_buffers(page)) { 19862306a36Sopenharmony_ci head = page_buffers(page); 19962306a36Sopenharmony_ci bh = head; 20062306a36Sopenharmony_ci do { 20162306a36Sopenharmony_ci next = bh->b_this_page; 20262306a36Sopenharmony_ci if (buffer_mapped(bh) && bh->b_blocknr == 0) { 20362306a36Sopenharmony_ci reiserfs_unmap_buffer(bh); 20462306a36Sopenharmony_ci } 20562306a36Sopenharmony_ci bh = next; 20662306a36Sopenharmony_ci } while (bh != head); 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci/* 21162306a36Sopenharmony_ci * reiserfs_get_block does not need to allocate a block only if it has been 21262306a36Sopenharmony_ci * done already or non-hole position has been found in the indirect item 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_cistatic inline int allocation_needed(int retval, b_blocknr_t allocated, 21562306a36Sopenharmony_ci struct item_head *ih, 21662306a36Sopenharmony_ci __le32 * item, int pos_in_item) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci if (allocated) 21962306a36Sopenharmony_ci return 0; 22062306a36Sopenharmony_ci if (retval == POSITION_FOUND && is_indirect_le_ih(ih) && 22162306a36Sopenharmony_ci get_block_num(item, pos_in_item)) 22262306a36Sopenharmony_ci return 0; 22362306a36Sopenharmony_ci return 1; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic inline int indirect_item_found(int retval, struct item_head *ih) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci return (retval == POSITION_FOUND) && is_indirect_le_ih(ih); 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic inline void set_block_dev_mapped(struct buffer_head *bh, 23262306a36Sopenharmony_ci b_blocknr_t block, struct inode *inode) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci map_bh(bh, inode->i_sb, block); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/* 23862306a36Sopenharmony_ci * files which were created in the earlier version can not be longer, 23962306a36Sopenharmony_ci * than 2 gb 24062306a36Sopenharmony_ci */ 24162306a36Sopenharmony_cistatic int file_capable(struct inode *inode, sector_t block) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci /* it is new file. */ 24462306a36Sopenharmony_ci if (get_inode_item_key_version(inode) != KEY_FORMAT_3_5 || 24562306a36Sopenharmony_ci /* old file, but 'block' is inside of 2gb */ 24662306a36Sopenharmony_ci block < (1 << (31 - inode->i_sb->s_blocksize_bits))) 24762306a36Sopenharmony_ci return 1; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic int restart_transaction(struct reiserfs_transaction_handle *th, 25362306a36Sopenharmony_ci struct inode *inode, struct treepath *path) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci struct super_block *s = th->t_super; 25662306a36Sopenharmony_ci int err; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci BUG_ON(!th->t_trans_id); 25962306a36Sopenharmony_ci BUG_ON(!th->t_refcount); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci pathrelse(path); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* we cannot restart while nested */ 26462306a36Sopenharmony_ci if (th->t_refcount > 1) { 26562306a36Sopenharmony_ci return 0; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci reiserfs_update_sd(th, inode); 26862306a36Sopenharmony_ci err = journal_end(th); 26962306a36Sopenharmony_ci if (!err) { 27062306a36Sopenharmony_ci err = journal_begin(th, s, JOURNAL_PER_BALANCE_CNT * 6); 27162306a36Sopenharmony_ci if (!err) 27262306a36Sopenharmony_ci reiserfs_update_inode_transaction(inode); 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci return err; 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci/* 27862306a36Sopenharmony_ci * it is called by get_block when create == 0. Returns block number 27962306a36Sopenharmony_ci * for 'block'-th logical block of file. When it hits direct item it 28062306a36Sopenharmony_ci * returns 0 (being called from bmap) or read direct item into piece 28162306a36Sopenharmony_ci * of page (bh_result) 28262306a36Sopenharmony_ci * Please improve the english/clarity in the comment above, as it is 28362306a36Sopenharmony_ci * hard to understand. 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_cistatic int _get_block_create_0(struct inode *inode, sector_t block, 28662306a36Sopenharmony_ci struct buffer_head *bh_result, int args) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci INITIALIZE_PATH(path); 28962306a36Sopenharmony_ci struct cpu_key key; 29062306a36Sopenharmony_ci struct buffer_head *bh; 29162306a36Sopenharmony_ci struct item_head *ih, tmp_ih; 29262306a36Sopenharmony_ci b_blocknr_t blocknr; 29362306a36Sopenharmony_ci char *p; 29462306a36Sopenharmony_ci int chars; 29562306a36Sopenharmony_ci int ret; 29662306a36Sopenharmony_ci int result; 29762306a36Sopenharmony_ci int done = 0; 29862306a36Sopenharmony_ci unsigned long offset; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* prepare the key to look for the 'block'-th block of file */ 30162306a36Sopenharmony_ci make_cpu_key(&key, inode, 30262306a36Sopenharmony_ci (loff_t) block * inode->i_sb->s_blocksize + 1, TYPE_ANY, 30362306a36Sopenharmony_ci 3); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci result = search_for_position_by_key(inode->i_sb, &key, &path); 30662306a36Sopenharmony_ci if (result != POSITION_FOUND) { 30762306a36Sopenharmony_ci pathrelse(&path); 30862306a36Sopenharmony_ci if (result == IO_ERROR) 30962306a36Sopenharmony_ci return -EIO; 31062306a36Sopenharmony_ci /* 31162306a36Sopenharmony_ci * We do not return -ENOENT if there is a hole but page is 31262306a36Sopenharmony_ci * uptodate, because it means that there is some MMAPED data 31362306a36Sopenharmony_ci * associated with it that is yet to be written to disk. 31462306a36Sopenharmony_ci */ 31562306a36Sopenharmony_ci if ((args & GET_BLOCK_NO_HOLE) 31662306a36Sopenharmony_ci && !PageUptodate(bh_result->b_page)) { 31762306a36Sopenharmony_ci return -ENOENT; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci return 0; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci bh = get_last_bh(&path); 32362306a36Sopenharmony_ci ih = tp_item_head(&path); 32462306a36Sopenharmony_ci if (is_indirect_le_ih(ih)) { 32562306a36Sopenharmony_ci __le32 *ind_item = (__le32 *) ih_item_body(bh, ih); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* 32862306a36Sopenharmony_ci * FIXME: here we could cache indirect item or part of it in 32962306a36Sopenharmony_ci * the inode to avoid search_by_key in case of subsequent 33062306a36Sopenharmony_ci * access to file 33162306a36Sopenharmony_ci */ 33262306a36Sopenharmony_ci blocknr = get_block_num(ind_item, path.pos_in_item); 33362306a36Sopenharmony_ci ret = 0; 33462306a36Sopenharmony_ci if (blocknr) { 33562306a36Sopenharmony_ci map_bh(bh_result, inode->i_sb, blocknr); 33662306a36Sopenharmony_ci if (path.pos_in_item == 33762306a36Sopenharmony_ci ((ih_item_len(ih) / UNFM_P_SIZE) - 1)) { 33862306a36Sopenharmony_ci set_buffer_boundary(bh_result); 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci } else 34162306a36Sopenharmony_ci /* 34262306a36Sopenharmony_ci * We do not return -ENOENT if there is a hole but 34362306a36Sopenharmony_ci * page is uptodate, because it means that there is 34462306a36Sopenharmony_ci * some MMAPED data associated with it that is 34562306a36Sopenharmony_ci * yet to be written to disk. 34662306a36Sopenharmony_ci */ 34762306a36Sopenharmony_ci if ((args & GET_BLOCK_NO_HOLE) 34862306a36Sopenharmony_ci && !PageUptodate(bh_result->b_page)) { 34962306a36Sopenharmony_ci ret = -ENOENT; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci pathrelse(&path); 35362306a36Sopenharmony_ci return ret; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci /* requested data are in direct item(s) */ 35662306a36Sopenharmony_ci if (!(args & GET_BLOCK_READ_DIRECT)) { 35762306a36Sopenharmony_ci /* 35862306a36Sopenharmony_ci * we are called by bmap. FIXME: we can not map block of file 35962306a36Sopenharmony_ci * when it is stored in direct item(s) 36062306a36Sopenharmony_ci */ 36162306a36Sopenharmony_ci pathrelse(&path); 36262306a36Sopenharmony_ci return -ENOENT; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci /* 36662306a36Sopenharmony_ci * if we've got a direct item, and the buffer or page was uptodate, 36762306a36Sopenharmony_ci * we don't want to pull data off disk again. skip to the 36862306a36Sopenharmony_ci * end, where we map the buffer and return 36962306a36Sopenharmony_ci */ 37062306a36Sopenharmony_ci if (buffer_uptodate(bh_result)) { 37162306a36Sopenharmony_ci goto finished; 37262306a36Sopenharmony_ci } else 37362306a36Sopenharmony_ci /* 37462306a36Sopenharmony_ci * grab_tail_page can trigger calls to reiserfs_get_block on 37562306a36Sopenharmony_ci * up to date pages without any buffers. If the page is up 37662306a36Sopenharmony_ci * to date, we don't want read old data off disk. Set the up 37762306a36Sopenharmony_ci * to date bit on the buffer instead and jump to the end 37862306a36Sopenharmony_ci */ 37962306a36Sopenharmony_ci if (!bh_result->b_page || PageUptodate(bh_result->b_page)) { 38062306a36Sopenharmony_ci set_buffer_uptodate(bh_result); 38162306a36Sopenharmony_ci goto finished; 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci /* read file tail into part of page */ 38462306a36Sopenharmony_ci offset = (cpu_key_k_offset(&key) - 1) & (PAGE_SIZE - 1); 38562306a36Sopenharmony_ci copy_item_head(&tmp_ih, ih); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci /* 38862306a36Sopenharmony_ci * we only want to kmap if we are reading the tail into the page. 38962306a36Sopenharmony_ci * this is not the common case, so we don't kmap until we are 39062306a36Sopenharmony_ci * sure we need to. But, this means the item might move if 39162306a36Sopenharmony_ci * kmap schedules 39262306a36Sopenharmony_ci */ 39362306a36Sopenharmony_ci p = (char *)kmap(bh_result->b_page); 39462306a36Sopenharmony_ci p += offset; 39562306a36Sopenharmony_ci memset(p, 0, inode->i_sb->s_blocksize); 39662306a36Sopenharmony_ci do { 39762306a36Sopenharmony_ci if (!is_direct_le_ih(ih)) { 39862306a36Sopenharmony_ci BUG(); 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci /* 40162306a36Sopenharmony_ci * make sure we don't read more bytes than actually exist in 40262306a36Sopenharmony_ci * the file. This can happen in odd cases where i_size isn't 40362306a36Sopenharmony_ci * correct, and when direct item padding results in a few 40462306a36Sopenharmony_ci * extra bytes at the end of the direct item 40562306a36Sopenharmony_ci */ 40662306a36Sopenharmony_ci if ((le_ih_k_offset(ih) + path.pos_in_item) > inode->i_size) 40762306a36Sopenharmony_ci break; 40862306a36Sopenharmony_ci if ((le_ih_k_offset(ih) - 1 + ih_item_len(ih)) > inode->i_size) { 40962306a36Sopenharmony_ci chars = 41062306a36Sopenharmony_ci inode->i_size - (le_ih_k_offset(ih) - 1) - 41162306a36Sopenharmony_ci path.pos_in_item; 41262306a36Sopenharmony_ci done = 1; 41362306a36Sopenharmony_ci } else { 41462306a36Sopenharmony_ci chars = ih_item_len(ih) - path.pos_in_item; 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci memcpy(p, ih_item_body(bh, ih) + path.pos_in_item, chars); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci if (done) 41962306a36Sopenharmony_ci break; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci p += chars; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci /* 42462306a36Sopenharmony_ci * we done, if read direct item is not the last item of 42562306a36Sopenharmony_ci * node FIXME: we could try to check right delimiting key 42662306a36Sopenharmony_ci * to see whether direct item continues in the right 42762306a36Sopenharmony_ci * neighbor or rely on i_size 42862306a36Sopenharmony_ci */ 42962306a36Sopenharmony_ci if (PATH_LAST_POSITION(&path) != (B_NR_ITEMS(bh) - 1)) 43062306a36Sopenharmony_ci break; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci /* update key to look for the next piece */ 43362306a36Sopenharmony_ci set_cpu_key_k_offset(&key, cpu_key_k_offset(&key) + chars); 43462306a36Sopenharmony_ci result = search_for_position_by_key(inode->i_sb, &key, &path); 43562306a36Sopenharmony_ci if (result != POSITION_FOUND) 43662306a36Sopenharmony_ci /* i/o error most likely */ 43762306a36Sopenharmony_ci break; 43862306a36Sopenharmony_ci bh = get_last_bh(&path); 43962306a36Sopenharmony_ci ih = tp_item_head(&path); 44062306a36Sopenharmony_ci } while (1); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci flush_dcache_page(bh_result->b_page); 44362306a36Sopenharmony_ci kunmap(bh_result->b_page); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cifinished: 44662306a36Sopenharmony_ci pathrelse(&path); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci if (result == IO_ERROR) 44962306a36Sopenharmony_ci return -EIO; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci /* 45262306a36Sopenharmony_ci * this buffer has valid data, but isn't valid for io. mapping it to 45362306a36Sopenharmony_ci * block #0 tells the rest of reiserfs it just has a tail in it 45462306a36Sopenharmony_ci */ 45562306a36Sopenharmony_ci map_bh(bh_result, inode->i_sb, 0); 45662306a36Sopenharmony_ci set_buffer_uptodate(bh_result); 45762306a36Sopenharmony_ci return 0; 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci/* 46162306a36Sopenharmony_ci * this is called to create file map. So, _get_block_create_0 will not 46262306a36Sopenharmony_ci * read direct item 46362306a36Sopenharmony_ci */ 46462306a36Sopenharmony_cistatic int reiserfs_bmap(struct inode *inode, sector_t block, 46562306a36Sopenharmony_ci struct buffer_head *bh_result, int create) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci if (!file_capable(inode, block)) 46862306a36Sopenharmony_ci return -EFBIG; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 47162306a36Sopenharmony_ci /* do not read the direct item */ 47262306a36Sopenharmony_ci _get_block_create_0(inode, block, bh_result, 0); 47362306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 47462306a36Sopenharmony_ci return 0; 47562306a36Sopenharmony_ci} 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci/* 47862306a36Sopenharmony_ci * special version of get_block that is only used by grab_tail_page right 47962306a36Sopenharmony_ci * now. It is sent to __block_write_begin, and when you try to get a 48062306a36Sopenharmony_ci * block past the end of the file (or a block from a hole) it returns 48162306a36Sopenharmony_ci * -ENOENT instead of a valid buffer. __block_write_begin expects to 48262306a36Sopenharmony_ci * be able to do i/o on the buffers returned, unless an error value 48362306a36Sopenharmony_ci * is also returned. 48462306a36Sopenharmony_ci * 48562306a36Sopenharmony_ci * So, this allows __block_write_begin to be used for reading a single block 48662306a36Sopenharmony_ci * in a page. Where it does not produce a valid page for holes, or past the 48762306a36Sopenharmony_ci * end of the file. This turns out to be exactly what we need for reading 48862306a36Sopenharmony_ci * tails for conversion. 48962306a36Sopenharmony_ci * 49062306a36Sopenharmony_ci * The point of the wrapper is forcing a certain value for create, even 49162306a36Sopenharmony_ci * though the VFS layer is calling this function with create==1. If you 49262306a36Sopenharmony_ci * don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block, 49362306a36Sopenharmony_ci * don't use this function. 49462306a36Sopenharmony_ci*/ 49562306a36Sopenharmony_cistatic int reiserfs_get_block_create_0(struct inode *inode, sector_t block, 49662306a36Sopenharmony_ci struct buffer_head *bh_result, 49762306a36Sopenharmony_ci int create) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci return reiserfs_get_block(inode, block, bh_result, GET_BLOCK_NO_HOLE); 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci/* 50362306a36Sopenharmony_ci * This is special helper for reiserfs_get_block in case we are executing 50462306a36Sopenharmony_ci * direct_IO request. 50562306a36Sopenharmony_ci */ 50662306a36Sopenharmony_cistatic int reiserfs_get_blocks_direct_io(struct inode *inode, 50762306a36Sopenharmony_ci sector_t iblock, 50862306a36Sopenharmony_ci struct buffer_head *bh_result, 50962306a36Sopenharmony_ci int create) 51062306a36Sopenharmony_ci{ 51162306a36Sopenharmony_ci int ret; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci bh_result->b_page = NULL; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci /* 51662306a36Sopenharmony_ci * We set the b_size before reiserfs_get_block call since it is 51762306a36Sopenharmony_ci * referenced in convert_tail_for_hole() that may be called from 51862306a36Sopenharmony_ci * reiserfs_get_block() 51962306a36Sopenharmony_ci */ 52062306a36Sopenharmony_ci bh_result->b_size = i_blocksize(inode); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci ret = reiserfs_get_block(inode, iblock, bh_result, 52362306a36Sopenharmony_ci create | GET_BLOCK_NO_DANGLE); 52462306a36Sopenharmony_ci if (ret) 52562306a36Sopenharmony_ci goto out; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci /* don't allow direct io onto tail pages */ 52862306a36Sopenharmony_ci if (buffer_mapped(bh_result) && bh_result->b_blocknr == 0) { 52962306a36Sopenharmony_ci /* 53062306a36Sopenharmony_ci * make sure future calls to the direct io funcs for this 53162306a36Sopenharmony_ci * offset in the file fail by unmapping the buffer 53262306a36Sopenharmony_ci */ 53362306a36Sopenharmony_ci clear_buffer_mapped(bh_result); 53462306a36Sopenharmony_ci ret = -EINVAL; 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci /* 53862306a36Sopenharmony_ci * Possible unpacked tail. Flush the data before pages have 53962306a36Sopenharmony_ci * disappeared 54062306a36Sopenharmony_ci */ 54162306a36Sopenharmony_ci if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) { 54262306a36Sopenharmony_ci int err; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci err = reiserfs_commit_for_inode(inode); 54762306a36Sopenharmony_ci REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci if (err < 0) 55262306a36Sopenharmony_ci ret = err; 55362306a36Sopenharmony_ci } 55462306a36Sopenharmony_ciout: 55562306a36Sopenharmony_ci return ret; 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci/* 55962306a36Sopenharmony_ci * helper function for when reiserfs_get_block is called for a hole 56062306a36Sopenharmony_ci * but the file tail is still in a direct item 56162306a36Sopenharmony_ci * bh_result is the buffer head for the hole 56262306a36Sopenharmony_ci * tail_offset is the offset of the start of the tail in the file 56362306a36Sopenharmony_ci * 56462306a36Sopenharmony_ci * This calls prepare_write, which will start a new transaction 56562306a36Sopenharmony_ci * you should not be in a transaction, or have any paths held when you 56662306a36Sopenharmony_ci * call this. 56762306a36Sopenharmony_ci */ 56862306a36Sopenharmony_cistatic int convert_tail_for_hole(struct inode *inode, 56962306a36Sopenharmony_ci struct buffer_head *bh_result, 57062306a36Sopenharmony_ci loff_t tail_offset) 57162306a36Sopenharmony_ci{ 57262306a36Sopenharmony_ci unsigned long index; 57362306a36Sopenharmony_ci unsigned long tail_end; 57462306a36Sopenharmony_ci unsigned long tail_start; 57562306a36Sopenharmony_ci struct page *tail_page; 57662306a36Sopenharmony_ci struct page *hole_page = bh_result->b_page; 57762306a36Sopenharmony_ci int retval = 0; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if ((tail_offset & (bh_result->b_size - 1)) != 1) 58062306a36Sopenharmony_ci return -EIO; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci /* always try to read until the end of the block */ 58362306a36Sopenharmony_ci tail_start = tail_offset & (PAGE_SIZE - 1); 58462306a36Sopenharmony_ci tail_end = (tail_start | (bh_result->b_size - 1)) + 1; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci index = tail_offset >> PAGE_SHIFT; 58762306a36Sopenharmony_ci /* 58862306a36Sopenharmony_ci * hole_page can be zero in case of direct_io, we are sure 58962306a36Sopenharmony_ci * that we cannot get here if we write with O_DIRECT into tail page 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_ci if (!hole_page || index != hole_page->index) { 59262306a36Sopenharmony_ci tail_page = grab_cache_page(inode->i_mapping, index); 59362306a36Sopenharmony_ci retval = -ENOMEM; 59462306a36Sopenharmony_ci if (!tail_page) { 59562306a36Sopenharmony_ci goto out; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci } else { 59862306a36Sopenharmony_ci tail_page = hole_page; 59962306a36Sopenharmony_ci } 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci /* 60262306a36Sopenharmony_ci * we don't have to make sure the conversion did not happen while 60362306a36Sopenharmony_ci * we were locking the page because anyone that could convert 60462306a36Sopenharmony_ci * must first take i_mutex. 60562306a36Sopenharmony_ci * 60662306a36Sopenharmony_ci * We must fix the tail page for writing because it might have buffers 60762306a36Sopenharmony_ci * that are mapped, but have a block number of 0. This indicates tail 60862306a36Sopenharmony_ci * data that has been read directly into the page, and 60962306a36Sopenharmony_ci * __block_write_begin won't trigger a get_block in this case. 61062306a36Sopenharmony_ci */ 61162306a36Sopenharmony_ci fix_tail_page_for_writing(tail_page); 61262306a36Sopenharmony_ci retval = __reiserfs_write_begin(tail_page, tail_start, 61362306a36Sopenharmony_ci tail_end - tail_start); 61462306a36Sopenharmony_ci if (retval) 61562306a36Sopenharmony_ci goto unlock; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci /* tail conversion might change the data in the page */ 61862306a36Sopenharmony_ci flush_dcache_page(tail_page); 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci retval = reiserfs_commit_write(NULL, tail_page, tail_start, tail_end); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ciunlock: 62362306a36Sopenharmony_ci if (tail_page != hole_page) { 62462306a36Sopenharmony_ci unlock_page(tail_page); 62562306a36Sopenharmony_ci put_page(tail_page); 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ciout: 62862306a36Sopenharmony_ci return retval; 62962306a36Sopenharmony_ci} 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_cistatic inline int _allocate_block(struct reiserfs_transaction_handle *th, 63262306a36Sopenharmony_ci sector_t block, 63362306a36Sopenharmony_ci struct inode *inode, 63462306a36Sopenharmony_ci b_blocknr_t * allocated_block_nr, 63562306a36Sopenharmony_ci struct treepath *path, int flags) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci BUG_ON(!th->t_trans_id); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci#ifdef REISERFS_PREALLOCATE 64062306a36Sopenharmony_ci if (!(flags & GET_BLOCK_NO_IMUX)) { 64162306a36Sopenharmony_ci return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr, 64262306a36Sopenharmony_ci path, block); 64362306a36Sopenharmony_ci } 64462306a36Sopenharmony_ci#endif 64562306a36Sopenharmony_ci return reiserfs_new_unf_blocknrs(th, inode, allocated_block_nr, path, 64662306a36Sopenharmony_ci block); 64762306a36Sopenharmony_ci} 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ciint reiserfs_get_block(struct inode *inode, sector_t block, 65062306a36Sopenharmony_ci struct buffer_head *bh_result, int create) 65162306a36Sopenharmony_ci{ 65262306a36Sopenharmony_ci int repeat, retval = 0; 65362306a36Sopenharmony_ci /* b_blocknr_t is (unsigned) 32 bit int*/ 65462306a36Sopenharmony_ci b_blocknr_t allocated_block_nr = 0; 65562306a36Sopenharmony_ci INITIALIZE_PATH(path); 65662306a36Sopenharmony_ci int pos_in_item; 65762306a36Sopenharmony_ci struct cpu_key key; 65862306a36Sopenharmony_ci struct buffer_head *bh, *unbh = NULL; 65962306a36Sopenharmony_ci struct item_head *ih, tmp_ih; 66062306a36Sopenharmony_ci __le32 *item; 66162306a36Sopenharmony_ci int done; 66262306a36Sopenharmony_ci int fs_gen; 66362306a36Sopenharmony_ci struct reiserfs_transaction_handle *th = NULL; 66462306a36Sopenharmony_ci /* 66562306a36Sopenharmony_ci * space reserved in transaction batch: 66662306a36Sopenharmony_ci * . 3 balancings in direct->indirect conversion 66762306a36Sopenharmony_ci * . 1 block involved into reiserfs_update_sd() 66862306a36Sopenharmony_ci * XXX in practically impossible worst case direct2indirect() 66962306a36Sopenharmony_ci * can incur (much) more than 3 balancings. 67062306a36Sopenharmony_ci * quota update for user, group 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci int jbegin_count = 67362306a36Sopenharmony_ci JOURNAL_PER_BALANCE_CNT * 3 + 1 + 67462306a36Sopenharmony_ci 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb); 67562306a36Sopenharmony_ci int version; 67662306a36Sopenharmony_ci int dangle = 1; 67762306a36Sopenharmony_ci loff_t new_offset = 67862306a36Sopenharmony_ci (((loff_t) block) << inode->i_sb->s_blocksize_bits) + 1; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 68162306a36Sopenharmony_ci version = get_inode_item_key_version(inode); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci if (!file_capable(inode, block)) { 68462306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 68562306a36Sopenharmony_ci return -EFBIG; 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci /* 68962306a36Sopenharmony_ci * if !create, we aren't changing the FS, so we don't need to 69062306a36Sopenharmony_ci * log anything, so we don't need to start a transaction 69162306a36Sopenharmony_ci */ 69262306a36Sopenharmony_ci if (!(create & GET_BLOCK_CREATE)) { 69362306a36Sopenharmony_ci int ret; 69462306a36Sopenharmony_ci /* find number of block-th logical block of the file */ 69562306a36Sopenharmony_ci ret = _get_block_create_0(inode, block, bh_result, 69662306a36Sopenharmony_ci create | GET_BLOCK_READ_DIRECT); 69762306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 69862306a36Sopenharmony_ci return ret; 69962306a36Sopenharmony_ci } 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci /* 70262306a36Sopenharmony_ci * if we're already in a transaction, make sure to close 70362306a36Sopenharmony_ci * any new transactions we start in this func 70462306a36Sopenharmony_ci */ 70562306a36Sopenharmony_ci if ((create & GET_BLOCK_NO_DANGLE) || 70662306a36Sopenharmony_ci reiserfs_transaction_running(inode->i_sb)) 70762306a36Sopenharmony_ci dangle = 0; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci /* 71062306a36Sopenharmony_ci * If file is of such a size, that it might have a tail and 71162306a36Sopenharmony_ci * tails are enabled we should mark it as possibly needing 71262306a36Sopenharmony_ci * tail packing on close 71362306a36Sopenharmony_ci */ 71462306a36Sopenharmony_ci if ((have_large_tails(inode->i_sb) 71562306a36Sopenharmony_ci && inode->i_size < i_block_size(inode) * 4) 71662306a36Sopenharmony_ci || (have_small_tails(inode->i_sb) 71762306a36Sopenharmony_ci && inode->i_size < i_block_size(inode))) 71862306a36Sopenharmony_ci REISERFS_I(inode)->i_flags |= i_pack_on_close_mask; 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci /* set the key of the first byte in the 'block'-th block of file */ 72162306a36Sopenharmony_ci make_cpu_key(&key, inode, new_offset, TYPE_ANY, 3 /*key length */ ); 72262306a36Sopenharmony_ci if ((new_offset + inode->i_sb->s_blocksize - 1) > inode->i_size) { 72362306a36Sopenharmony_cistart_trans: 72462306a36Sopenharmony_ci th = reiserfs_persistent_transaction(inode->i_sb, jbegin_count); 72562306a36Sopenharmony_ci if (!th) { 72662306a36Sopenharmony_ci retval = -ENOMEM; 72762306a36Sopenharmony_ci goto failure; 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci reiserfs_update_inode_transaction(inode); 73062306a36Sopenharmony_ci } 73162306a36Sopenharmony_ciresearch: 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci retval = search_for_position_by_key(inode->i_sb, &key, &path); 73462306a36Sopenharmony_ci if (retval == IO_ERROR) { 73562306a36Sopenharmony_ci retval = -EIO; 73662306a36Sopenharmony_ci goto failure; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci bh = get_last_bh(&path); 74062306a36Sopenharmony_ci ih = tp_item_head(&path); 74162306a36Sopenharmony_ci item = tp_item_body(&path); 74262306a36Sopenharmony_ci pos_in_item = path.pos_in_item; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci fs_gen = get_generation(inode->i_sb); 74562306a36Sopenharmony_ci copy_item_head(&tmp_ih, ih); 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (allocation_needed 74862306a36Sopenharmony_ci (retval, allocated_block_nr, ih, item, pos_in_item)) { 74962306a36Sopenharmony_ci /* we have to allocate block for the unformatted node */ 75062306a36Sopenharmony_ci if (!th) { 75162306a36Sopenharmony_ci pathrelse(&path); 75262306a36Sopenharmony_ci goto start_trans; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci repeat = 75662306a36Sopenharmony_ci _allocate_block(th, block, inode, &allocated_block_nr, 75762306a36Sopenharmony_ci &path, create); 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci /* 76062306a36Sopenharmony_ci * restart the transaction to give the journal a chance to free 76162306a36Sopenharmony_ci * some blocks. releases the path, so we have to go back to 76262306a36Sopenharmony_ci * research if we succeed on the second try 76362306a36Sopenharmony_ci */ 76462306a36Sopenharmony_ci if (repeat == NO_DISK_SPACE || repeat == QUOTA_EXCEEDED) { 76562306a36Sopenharmony_ci SB_JOURNAL(inode->i_sb)->j_next_async_flush = 1; 76662306a36Sopenharmony_ci retval = restart_transaction(th, inode, &path); 76762306a36Sopenharmony_ci if (retval) 76862306a36Sopenharmony_ci goto failure; 76962306a36Sopenharmony_ci repeat = 77062306a36Sopenharmony_ci _allocate_block(th, block, inode, 77162306a36Sopenharmony_ci &allocated_block_nr, NULL, create); 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci if (repeat != NO_DISK_SPACE && repeat != QUOTA_EXCEEDED) { 77462306a36Sopenharmony_ci goto research; 77562306a36Sopenharmony_ci } 77662306a36Sopenharmony_ci if (repeat == QUOTA_EXCEEDED) 77762306a36Sopenharmony_ci retval = -EDQUOT; 77862306a36Sopenharmony_ci else 77962306a36Sopenharmony_ci retval = -ENOSPC; 78062306a36Sopenharmony_ci goto failure; 78162306a36Sopenharmony_ci } 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci if (fs_changed(fs_gen, inode->i_sb) 78462306a36Sopenharmony_ci && item_moved(&tmp_ih, &path)) { 78562306a36Sopenharmony_ci goto research; 78662306a36Sopenharmony_ci } 78762306a36Sopenharmony_ci } 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci if (indirect_item_found(retval, ih)) { 79062306a36Sopenharmony_ci b_blocknr_t unfm_ptr; 79162306a36Sopenharmony_ci /* 79262306a36Sopenharmony_ci * 'block'-th block is in the file already (there is 79362306a36Sopenharmony_ci * corresponding cell in some indirect item). But it may be 79462306a36Sopenharmony_ci * zero unformatted node pointer (hole) 79562306a36Sopenharmony_ci */ 79662306a36Sopenharmony_ci unfm_ptr = get_block_num(item, pos_in_item); 79762306a36Sopenharmony_ci if (unfm_ptr == 0) { 79862306a36Sopenharmony_ci /* use allocated block to plug the hole */ 79962306a36Sopenharmony_ci reiserfs_prepare_for_journal(inode->i_sb, bh, 1); 80062306a36Sopenharmony_ci if (fs_changed(fs_gen, inode->i_sb) 80162306a36Sopenharmony_ci && item_moved(&tmp_ih, &path)) { 80262306a36Sopenharmony_ci reiserfs_restore_prepared_buffer(inode->i_sb, 80362306a36Sopenharmony_ci bh); 80462306a36Sopenharmony_ci goto research; 80562306a36Sopenharmony_ci } 80662306a36Sopenharmony_ci set_buffer_new(bh_result); 80762306a36Sopenharmony_ci if (buffer_dirty(bh_result) 80862306a36Sopenharmony_ci && reiserfs_data_ordered(inode->i_sb)) 80962306a36Sopenharmony_ci reiserfs_add_ordered_list(inode, bh_result); 81062306a36Sopenharmony_ci put_block_num(item, pos_in_item, allocated_block_nr); 81162306a36Sopenharmony_ci unfm_ptr = allocated_block_nr; 81262306a36Sopenharmony_ci journal_mark_dirty(th, bh); 81362306a36Sopenharmony_ci reiserfs_update_sd(th, inode); 81462306a36Sopenharmony_ci } 81562306a36Sopenharmony_ci set_block_dev_mapped(bh_result, unfm_ptr, inode); 81662306a36Sopenharmony_ci pathrelse(&path); 81762306a36Sopenharmony_ci retval = 0; 81862306a36Sopenharmony_ci if (!dangle && th) 81962306a36Sopenharmony_ci retval = reiserfs_end_persistent_transaction(th); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci /* 82462306a36Sopenharmony_ci * the item was found, so new blocks were not added to the file 82562306a36Sopenharmony_ci * there is no need to make sure the inode is updated with this 82662306a36Sopenharmony_ci * transaction 82762306a36Sopenharmony_ci */ 82862306a36Sopenharmony_ci return retval; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci if (!th) { 83262306a36Sopenharmony_ci pathrelse(&path); 83362306a36Sopenharmony_ci goto start_trans; 83462306a36Sopenharmony_ci } 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci /* 83762306a36Sopenharmony_ci * desired position is not found or is in the direct item. We have 83862306a36Sopenharmony_ci * to append file with holes up to 'block'-th block converting 83962306a36Sopenharmony_ci * direct items to indirect one if necessary 84062306a36Sopenharmony_ci */ 84162306a36Sopenharmony_ci done = 0; 84262306a36Sopenharmony_ci do { 84362306a36Sopenharmony_ci if (is_statdata_le_ih(ih)) { 84462306a36Sopenharmony_ci __le32 unp = 0; 84562306a36Sopenharmony_ci struct cpu_key tmp_key; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci /* indirect item has to be inserted */ 84862306a36Sopenharmony_ci make_le_item_head(&tmp_ih, &key, version, 1, 84962306a36Sopenharmony_ci TYPE_INDIRECT, UNFM_P_SIZE, 85062306a36Sopenharmony_ci 0 /* free_space */ ); 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci /* 85362306a36Sopenharmony_ci * we are going to add 'block'-th block to the file. 85462306a36Sopenharmony_ci * Use allocated block for that 85562306a36Sopenharmony_ci */ 85662306a36Sopenharmony_ci if (cpu_key_k_offset(&key) == 1) { 85762306a36Sopenharmony_ci unp = cpu_to_le32(allocated_block_nr); 85862306a36Sopenharmony_ci set_block_dev_mapped(bh_result, 85962306a36Sopenharmony_ci allocated_block_nr, inode); 86062306a36Sopenharmony_ci set_buffer_new(bh_result); 86162306a36Sopenharmony_ci done = 1; 86262306a36Sopenharmony_ci } 86362306a36Sopenharmony_ci tmp_key = key; /* ;) */ 86462306a36Sopenharmony_ci set_cpu_key_k_offset(&tmp_key, 1); 86562306a36Sopenharmony_ci PATH_LAST_POSITION(&path)++; 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci retval = 86862306a36Sopenharmony_ci reiserfs_insert_item(th, &path, &tmp_key, &tmp_ih, 86962306a36Sopenharmony_ci inode, (char *)&unp); 87062306a36Sopenharmony_ci if (retval) { 87162306a36Sopenharmony_ci reiserfs_free_block(th, inode, 87262306a36Sopenharmony_ci allocated_block_nr, 1); 87362306a36Sopenharmony_ci /* 87462306a36Sopenharmony_ci * retval == -ENOSPC, -EDQUOT or -EIO 87562306a36Sopenharmony_ci * or -EEXIST 87662306a36Sopenharmony_ci */ 87762306a36Sopenharmony_ci goto failure; 87862306a36Sopenharmony_ci } 87962306a36Sopenharmony_ci } else if (is_direct_le_ih(ih)) { 88062306a36Sopenharmony_ci /* direct item has to be converted */ 88162306a36Sopenharmony_ci loff_t tail_offset; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci tail_offset = 88462306a36Sopenharmony_ci ((le_ih_k_offset(ih) - 88562306a36Sopenharmony_ci 1) & ~(inode->i_sb->s_blocksize - 1)) + 1; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci /* 88862306a36Sopenharmony_ci * direct item we just found fits into block we have 88962306a36Sopenharmony_ci * to map. Convert it into unformatted node: use 89062306a36Sopenharmony_ci * bh_result for the conversion 89162306a36Sopenharmony_ci */ 89262306a36Sopenharmony_ci if (tail_offset == cpu_key_k_offset(&key)) { 89362306a36Sopenharmony_ci set_block_dev_mapped(bh_result, 89462306a36Sopenharmony_ci allocated_block_nr, inode); 89562306a36Sopenharmony_ci unbh = bh_result; 89662306a36Sopenharmony_ci done = 1; 89762306a36Sopenharmony_ci } else { 89862306a36Sopenharmony_ci /* 89962306a36Sopenharmony_ci * we have to pad file tail stored in direct 90062306a36Sopenharmony_ci * item(s) up to block size and convert it 90162306a36Sopenharmony_ci * to unformatted node. FIXME: this should 90262306a36Sopenharmony_ci * also get into page cache 90362306a36Sopenharmony_ci */ 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci pathrelse(&path); 90662306a36Sopenharmony_ci /* 90762306a36Sopenharmony_ci * ugly, but we can only end the transaction if 90862306a36Sopenharmony_ci * we aren't nested 90962306a36Sopenharmony_ci */ 91062306a36Sopenharmony_ci BUG_ON(!th->t_refcount); 91162306a36Sopenharmony_ci if (th->t_refcount == 1) { 91262306a36Sopenharmony_ci retval = 91362306a36Sopenharmony_ci reiserfs_end_persistent_transaction 91462306a36Sopenharmony_ci (th); 91562306a36Sopenharmony_ci th = NULL; 91662306a36Sopenharmony_ci if (retval) 91762306a36Sopenharmony_ci goto failure; 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci retval = 92162306a36Sopenharmony_ci convert_tail_for_hole(inode, bh_result, 92262306a36Sopenharmony_ci tail_offset); 92362306a36Sopenharmony_ci if (retval) { 92462306a36Sopenharmony_ci if (retval != -ENOSPC) 92562306a36Sopenharmony_ci reiserfs_error(inode->i_sb, 92662306a36Sopenharmony_ci "clm-6004", 92762306a36Sopenharmony_ci "convert tail failed " 92862306a36Sopenharmony_ci "inode %lu, error %d", 92962306a36Sopenharmony_ci inode->i_ino, 93062306a36Sopenharmony_ci retval); 93162306a36Sopenharmony_ci if (allocated_block_nr) { 93262306a36Sopenharmony_ci /* 93362306a36Sopenharmony_ci * the bitmap, the super, 93462306a36Sopenharmony_ci * and the stat data == 3 93562306a36Sopenharmony_ci */ 93662306a36Sopenharmony_ci if (!th) 93762306a36Sopenharmony_ci th = reiserfs_persistent_transaction(inode->i_sb, 3); 93862306a36Sopenharmony_ci if (th) 93962306a36Sopenharmony_ci reiserfs_free_block(th, 94062306a36Sopenharmony_ci inode, 94162306a36Sopenharmony_ci allocated_block_nr, 94262306a36Sopenharmony_ci 1); 94362306a36Sopenharmony_ci } 94462306a36Sopenharmony_ci goto failure; 94562306a36Sopenharmony_ci } 94662306a36Sopenharmony_ci goto research; 94762306a36Sopenharmony_ci } 94862306a36Sopenharmony_ci retval = 94962306a36Sopenharmony_ci direct2indirect(th, inode, &path, unbh, 95062306a36Sopenharmony_ci tail_offset); 95162306a36Sopenharmony_ci if (retval) { 95262306a36Sopenharmony_ci reiserfs_unmap_buffer(unbh); 95362306a36Sopenharmony_ci reiserfs_free_block(th, inode, 95462306a36Sopenharmony_ci allocated_block_nr, 1); 95562306a36Sopenharmony_ci goto failure; 95662306a36Sopenharmony_ci } 95762306a36Sopenharmony_ci /* 95862306a36Sopenharmony_ci * it is important the set_buffer_uptodate is done 95962306a36Sopenharmony_ci * after the direct2indirect. The buffer might 96062306a36Sopenharmony_ci * contain valid data newer than the data on disk 96162306a36Sopenharmony_ci * (read by read_folio, changed, and then sent here by 96262306a36Sopenharmony_ci * writepage). direct2indirect needs to know if unbh 96362306a36Sopenharmony_ci * was already up to date, so it can decide if the 96462306a36Sopenharmony_ci * data in unbh needs to be replaced with data from 96562306a36Sopenharmony_ci * the disk 96662306a36Sopenharmony_ci */ 96762306a36Sopenharmony_ci set_buffer_uptodate(unbh); 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci /* 97062306a36Sopenharmony_ci * unbh->b_page == NULL in case of DIRECT_IO request, 97162306a36Sopenharmony_ci * this means buffer will disappear shortly, so it 97262306a36Sopenharmony_ci * should not be added to 97362306a36Sopenharmony_ci */ 97462306a36Sopenharmony_ci if (unbh->b_page) { 97562306a36Sopenharmony_ci /* 97662306a36Sopenharmony_ci * we've converted the tail, so we must 97762306a36Sopenharmony_ci * flush unbh before the transaction commits 97862306a36Sopenharmony_ci */ 97962306a36Sopenharmony_ci reiserfs_add_tail_list(inode, unbh); 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci /* 98262306a36Sopenharmony_ci * mark it dirty now to prevent commit_write 98362306a36Sopenharmony_ci * from adding this buffer to the inode's 98462306a36Sopenharmony_ci * dirty buffer list 98562306a36Sopenharmony_ci */ 98662306a36Sopenharmony_ci /* 98762306a36Sopenharmony_ci * AKPM: changed __mark_buffer_dirty to 98862306a36Sopenharmony_ci * mark_buffer_dirty(). It's still atomic, 98962306a36Sopenharmony_ci * but it sets the page dirty too, which makes 99062306a36Sopenharmony_ci * it eligible for writeback at any time by the 99162306a36Sopenharmony_ci * VM (which was also the case with 99262306a36Sopenharmony_ci * __mark_buffer_dirty()) 99362306a36Sopenharmony_ci */ 99462306a36Sopenharmony_ci mark_buffer_dirty(unbh); 99562306a36Sopenharmony_ci } 99662306a36Sopenharmony_ci } else { 99762306a36Sopenharmony_ci /* 99862306a36Sopenharmony_ci * append indirect item with holes if needed, when 99962306a36Sopenharmony_ci * appending pointer to 'block'-th block use block, 100062306a36Sopenharmony_ci * which is already allocated 100162306a36Sopenharmony_ci */ 100262306a36Sopenharmony_ci struct cpu_key tmp_key; 100362306a36Sopenharmony_ci /* 100462306a36Sopenharmony_ci * We use this in case we need to allocate 100562306a36Sopenharmony_ci * only one block which is a fastpath 100662306a36Sopenharmony_ci */ 100762306a36Sopenharmony_ci unp_t unf_single = 0; 100862306a36Sopenharmony_ci unp_t *un; 100962306a36Sopenharmony_ci __u64 max_to_insert = 101062306a36Sopenharmony_ci MAX_ITEM_LEN(inode->i_sb->s_blocksize) / 101162306a36Sopenharmony_ci UNFM_P_SIZE; 101262306a36Sopenharmony_ci __u64 blocks_needed; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci RFALSE(pos_in_item != ih_item_len(ih) / UNFM_P_SIZE, 101562306a36Sopenharmony_ci "vs-804: invalid position for append"); 101662306a36Sopenharmony_ci /* 101762306a36Sopenharmony_ci * indirect item has to be appended, 101862306a36Sopenharmony_ci * set up key of that position 101962306a36Sopenharmony_ci * (key type is unimportant) 102062306a36Sopenharmony_ci */ 102162306a36Sopenharmony_ci make_cpu_key(&tmp_key, inode, 102262306a36Sopenharmony_ci le_key_k_offset(version, 102362306a36Sopenharmony_ci &ih->ih_key) + 102462306a36Sopenharmony_ci op_bytes_number(ih, 102562306a36Sopenharmony_ci inode->i_sb->s_blocksize), 102662306a36Sopenharmony_ci TYPE_INDIRECT, 3); 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci RFALSE(cpu_key_k_offset(&tmp_key) > cpu_key_k_offset(&key), 102962306a36Sopenharmony_ci "green-805: invalid offset"); 103062306a36Sopenharmony_ci blocks_needed = 103162306a36Sopenharmony_ci 1 + 103262306a36Sopenharmony_ci ((cpu_key_k_offset(&key) - 103362306a36Sopenharmony_ci cpu_key_k_offset(&tmp_key)) >> inode->i_sb-> 103462306a36Sopenharmony_ci s_blocksize_bits); 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci if (blocks_needed == 1) { 103762306a36Sopenharmony_ci un = &unf_single; 103862306a36Sopenharmony_ci } else { 103962306a36Sopenharmony_ci un = kcalloc(min(blocks_needed, max_to_insert), 104062306a36Sopenharmony_ci UNFM_P_SIZE, GFP_NOFS); 104162306a36Sopenharmony_ci if (!un) { 104262306a36Sopenharmony_ci un = &unf_single; 104362306a36Sopenharmony_ci blocks_needed = 1; 104462306a36Sopenharmony_ci max_to_insert = 0; 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci } 104762306a36Sopenharmony_ci if (blocks_needed <= max_to_insert) { 104862306a36Sopenharmony_ci /* 104962306a36Sopenharmony_ci * we are going to add target block to 105062306a36Sopenharmony_ci * the file. Use allocated block for that 105162306a36Sopenharmony_ci */ 105262306a36Sopenharmony_ci un[blocks_needed - 1] = 105362306a36Sopenharmony_ci cpu_to_le32(allocated_block_nr); 105462306a36Sopenharmony_ci set_block_dev_mapped(bh_result, 105562306a36Sopenharmony_ci allocated_block_nr, inode); 105662306a36Sopenharmony_ci set_buffer_new(bh_result); 105762306a36Sopenharmony_ci done = 1; 105862306a36Sopenharmony_ci } else { 105962306a36Sopenharmony_ci /* paste hole to the indirect item */ 106062306a36Sopenharmony_ci /* 106162306a36Sopenharmony_ci * If kcalloc failed, max_to_insert becomes 106262306a36Sopenharmony_ci * zero and it means we only have space for 106362306a36Sopenharmony_ci * one block 106462306a36Sopenharmony_ci */ 106562306a36Sopenharmony_ci blocks_needed = 106662306a36Sopenharmony_ci max_to_insert ? max_to_insert : 1; 106762306a36Sopenharmony_ci } 106862306a36Sopenharmony_ci retval = 106962306a36Sopenharmony_ci reiserfs_paste_into_item(th, &path, &tmp_key, inode, 107062306a36Sopenharmony_ci (char *)un, 107162306a36Sopenharmony_ci UNFM_P_SIZE * 107262306a36Sopenharmony_ci blocks_needed); 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci if (blocks_needed != 1) 107562306a36Sopenharmony_ci kfree(un); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci if (retval) { 107862306a36Sopenharmony_ci reiserfs_free_block(th, inode, 107962306a36Sopenharmony_ci allocated_block_nr, 1); 108062306a36Sopenharmony_ci goto failure; 108162306a36Sopenharmony_ci } 108262306a36Sopenharmony_ci if (!done) { 108362306a36Sopenharmony_ci /* 108462306a36Sopenharmony_ci * We need to mark new file size in case 108562306a36Sopenharmony_ci * this function will be interrupted/aborted 108662306a36Sopenharmony_ci * later on. And we may do this only for 108762306a36Sopenharmony_ci * holes. 108862306a36Sopenharmony_ci */ 108962306a36Sopenharmony_ci inode->i_size += 109062306a36Sopenharmony_ci inode->i_sb->s_blocksize * blocks_needed; 109162306a36Sopenharmony_ci } 109262306a36Sopenharmony_ci } 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci if (done == 1) 109562306a36Sopenharmony_ci break; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci /* 109862306a36Sopenharmony_ci * this loop could log more blocks than we had originally 109962306a36Sopenharmony_ci * asked for. So, we have to allow the transaction to end 110062306a36Sopenharmony_ci * if it is too big or too full. Update the inode so things 110162306a36Sopenharmony_ci * are consistent if we crash before the function returns 110262306a36Sopenharmony_ci * release the path so that anybody waiting on the path before 110362306a36Sopenharmony_ci * ending their transaction will be able to continue. 110462306a36Sopenharmony_ci */ 110562306a36Sopenharmony_ci if (journal_transaction_should_end(th, th->t_blocks_allocated)) { 110662306a36Sopenharmony_ci retval = restart_transaction(th, inode, &path); 110762306a36Sopenharmony_ci if (retval) 110862306a36Sopenharmony_ci goto failure; 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci /* 111162306a36Sopenharmony_ci * inserting indirect pointers for a hole can take a 111262306a36Sopenharmony_ci * long time. reschedule if needed and also release the write 111362306a36Sopenharmony_ci * lock for others. 111462306a36Sopenharmony_ci */ 111562306a36Sopenharmony_ci reiserfs_cond_resched(inode->i_sb); 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci retval = search_for_position_by_key(inode->i_sb, &key, &path); 111862306a36Sopenharmony_ci if (retval == IO_ERROR) { 111962306a36Sopenharmony_ci retval = -EIO; 112062306a36Sopenharmony_ci goto failure; 112162306a36Sopenharmony_ci } 112262306a36Sopenharmony_ci if (retval == POSITION_FOUND) { 112362306a36Sopenharmony_ci reiserfs_warning(inode->i_sb, "vs-825", 112462306a36Sopenharmony_ci "%K should not be found", &key); 112562306a36Sopenharmony_ci retval = -EEXIST; 112662306a36Sopenharmony_ci if (allocated_block_nr) 112762306a36Sopenharmony_ci reiserfs_free_block(th, inode, 112862306a36Sopenharmony_ci allocated_block_nr, 1); 112962306a36Sopenharmony_ci pathrelse(&path); 113062306a36Sopenharmony_ci goto failure; 113162306a36Sopenharmony_ci } 113262306a36Sopenharmony_ci bh = get_last_bh(&path); 113362306a36Sopenharmony_ci ih = tp_item_head(&path); 113462306a36Sopenharmony_ci item = tp_item_body(&path); 113562306a36Sopenharmony_ci pos_in_item = path.pos_in_item; 113662306a36Sopenharmony_ci } while (1); 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci retval = 0; 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_cifailure: 114162306a36Sopenharmony_ci if (th && (!dangle || (retval && !th->t_trans_id))) { 114262306a36Sopenharmony_ci int err; 114362306a36Sopenharmony_ci if (th->t_trans_id) 114462306a36Sopenharmony_ci reiserfs_update_sd(th, inode); 114562306a36Sopenharmony_ci err = reiserfs_end_persistent_transaction(th); 114662306a36Sopenharmony_ci if (err) 114762306a36Sopenharmony_ci retval = err; 114862306a36Sopenharmony_ci } 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 115162306a36Sopenharmony_ci reiserfs_check_path(&path); 115262306a36Sopenharmony_ci return retval; 115362306a36Sopenharmony_ci} 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_cistatic void reiserfs_readahead(struct readahead_control *rac) 115662306a36Sopenharmony_ci{ 115762306a36Sopenharmony_ci mpage_readahead(rac, reiserfs_get_block); 115862306a36Sopenharmony_ci} 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci/* 116162306a36Sopenharmony_ci * Compute real number of used bytes by file 116262306a36Sopenharmony_ci * Following three functions can go away when we'll have enough space in 116362306a36Sopenharmony_ci * stat item 116462306a36Sopenharmony_ci */ 116562306a36Sopenharmony_cistatic int real_space_diff(struct inode *inode, int sd_size) 116662306a36Sopenharmony_ci{ 116762306a36Sopenharmony_ci int bytes; 116862306a36Sopenharmony_ci loff_t blocksize = inode->i_sb->s_blocksize; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) 117162306a36Sopenharmony_ci return sd_size; 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci /* 117462306a36Sopenharmony_ci * End of file is also in full block with indirect reference, so round 117562306a36Sopenharmony_ci * up to the next block. 117662306a36Sopenharmony_ci * 117762306a36Sopenharmony_ci * there is just no way to know if the tail is actually packed 117862306a36Sopenharmony_ci * on the file, so we have to assume it isn't. When we pack the 117962306a36Sopenharmony_ci * tail, we add 4 bytes to pretend there really is an unformatted 118062306a36Sopenharmony_ci * node pointer 118162306a36Sopenharmony_ci */ 118262306a36Sopenharmony_ci bytes = 118362306a36Sopenharmony_ci ((inode->i_size + 118462306a36Sopenharmony_ci (blocksize - 1)) >> inode->i_sb->s_blocksize_bits) * UNFM_P_SIZE + 118562306a36Sopenharmony_ci sd_size; 118662306a36Sopenharmony_ci return bytes; 118762306a36Sopenharmony_ci} 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_cistatic inline loff_t to_real_used_space(struct inode *inode, ulong blocks, 119062306a36Sopenharmony_ci int sd_size) 119162306a36Sopenharmony_ci{ 119262306a36Sopenharmony_ci if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) { 119362306a36Sopenharmony_ci return inode->i_size + 119462306a36Sopenharmony_ci (loff_t) (real_space_diff(inode, sd_size)); 119562306a36Sopenharmony_ci } 119662306a36Sopenharmony_ci return ((loff_t) real_space_diff(inode, sd_size)) + 119762306a36Sopenharmony_ci (((loff_t) blocks) << 9); 119862306a36Sopenharmony_ci} 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci/* Compute number of blocks used by file in ReiserFS counting */ 120162306a36Sopenharmony_cistatic inline ulong to_fake_used_blocks(struct inode *inode, int sd_size) 120262306a36Sopenharmony_ci{ 120362306a36Sopenharmony_ci loff_t bytes = inode_get_bytes(inode); 120462306a36Sopenharmony_ci loff_t real_space = real_space_diff(inode, sd_size); 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci /* keeps fsck and non-quota versions of reiserfs happy */ 120762306a36Sopenharmony_ci if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) { 120862306a36Sopenharmony_ci bytes += (loff_t) 511; 120962306a36Sopenharmony_ci } 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci /* 121262306a36Sopenharmony_ci * files from before the quota patch might i_blocks such that 121362306a36Sopenharmony_ci * bytes < real_space. Deal with that here to prevent it from 121462306a36Sopenharmony_ci * going negative. 121562306a36Sopenharmony_ci */ 121662306a36Sopenharmony_ci if (bytes < real_space) 121762306a36Sopenharmony_ci return 0; 121862306a36Sopenharmony_ci return (bytes - real_space) >> 9; 121962306a36Sopenharmony_ci} 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci/* 122262306a36Sopenharmony_ci * BAD: new directories have stat data of new type and all other items 122362306a36Sopenharmony_ci * of old type. Version stored in the inode says about body items, so 122462306a36Sopenharmony_ci * in update_stat_data we can not rely on inode, but have to check 122562306a36Sopenharmony_ci * item version directly 122662306a36Sopenharmony_ci */ 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci/* called by read_locked_inode */ 122962306a36Sopenharmony_cistatic void init_inode(struct inode *inode, struct treepath *path) 123062306a36Sopenharmony_ci{ 123162306a36Sopenharmony_ci struct buffer_head *bh; 123262306a36Sopenharmony_ci struct item_head *ih; 123362306a36Sopenharmony_ci __u32 rdev; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci bh = PATH_PLAST_BUFFER(path); 123662306a36Sopenharmony_ci ih = tp_item_head(path); 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci copy_key(INODE_PKEY(inode), &ih->ih_key); 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci INIT_LIST_HEAD(&REISERFS_I(inode)->i_prealloc_list); 124162306a36Sopenharmony_ci REISERFS_I(inode)->i_flags = 0; 124262306a36Sopenharmony_ci REISERFS_I(inode)->i_prealloc_block = 0; 124362306a36Sopenharmony_ci REISERFS_I(inode)->i_prealloc_count = 0; 124462306a36Sopenharmony_ci REISERFS_I(inode)->i_trans_id = 0; 124562306a36Sopenharmony_ci REISERFS_I(inode)->i_jl = NULL; 124662306a36Sopenharmony_ci reiserfs_init_xattr_rwsem(inode); 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci if (stat_data_v1(ih)) { 124962306a36Sopenharmony_ci struct stat_data_v1 *sd = 125062306a36Sopenharmony_ci (struct stat_data_v1 *)ih_item_body(bh, ih); 125162306a36Sopenharmony_ci unsigned long blocks; 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci set_inode_item_key_version(inode, KEY_FORMAT_3_5); 125462306a36Sopenharmony_ci set_inode_sd_version(inode, STAT_DATA_V1); 125562306a36Sopenharmony_ci inode->i_mode = sd_v1_mode(sd); 125662306a36Sopenharmony_ci set_nlink(inode, sd_v1_nlink(sd)); 125762306a36Sopenharmony_ci i_uid_write(inode, sd_v1_uid(sd)); 125862306a36Sopenharmony_ci i_gid_write(inode, sd_v1_gid(sd)); 125962306a36Sopenharmony_ci inode->i_size = sd_v1_size(sd); 126062306a36Sopenharmony_ci inode->i_atime.tv_sec = sd_v1_atime(sd); 126162306a36Sopenharmony_ci inode->i_mtime.tv_sec = sd_v1_mtime(sd); 126262306a36Sopenharmony_ci inode_set_ctime(inode, sd_v1_ctime(sd), 0); 126362306a36Sopenharmony_ci inode->i_atime.tv_nsec = 0; 126462306a36Sopenharmony_ci inode->i_mtime.tv_nsec = 0; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci inode->i_blocks = sd_v1_blocks(sd); 126762306a36Sopenharmony_ci inode->i_generation = le32_to_cpu(INODE_PKEY(inode)->k_dir_id); 126862306a36Sopenharmony_ci blocks = (inode->i_size + 511) >> 9; 126962306a36Sopenharmony_ci blocks = _ROUND_UP(blocks, inode->i_sb->s_blocksize >> 9); 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci /* 127262306a36Sopenharmony_ci * there was a bug in <=3.5.23 when i_blocks could take 127362306a36Sopenharmony_ci * negative values. Starting from 3.5.17 this value could 127462306a36Sopenharmony_ci * even be stored in stat data. For such files we set 127562306a36Sopenharmony_ci * i_blocks based on file size. Just 2 notes: this can be 127662306a36Sopenharmony_ci * wrong for sparse files. On-disk value will be only 127762306a36Sopenharmony_ci * updated if file's inode will ever change 127862306a36Sopenharmony_ci */ 127962306a36Sopenharmony_ci if (inode->i_blocks > blocks) { 128062306a36Sopenharmony_ci inode->i_blocks = blocks; 128162306a36Sopenharmony_ci } 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci rdev = sd_v1_rdev(sd); 128462306a36Sopenharmony_ci REISERFS_I(inode)->i_first_direct_byte = 128562306a36Sopenharmony_ci sd_v1_first_direct_byte(sd); 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci /* 128862306a36Sopenharmony_ci * an early bug in the quota code can give us an odd 128962306a36Sopenharmony_ci * number for the block count. This is incorrect, fix it here. 129062306a36Sopenharmony_ci */ 129162306a36Sopenharmony_ci if (inode->i_blocks & 1) { 129262306a36Sopenharmony_ci inode->i_blocks++; 129362306a36Sopenharmony_ci } 129462306a36Sopenharmony_ci inode_set_bytes(inode, 129562306a36Sopenharmony_ci to_real_used_space(inode, inode->i_blocks, 129662306a36Sopenharmony_ci SD_V1_SIZE)); 129762306a36Sopenharmony_ci /* 129862306a36Sopenharmony_ci * nopack is initially zero for v1 objects. For v2 objects, 129962306a36Sopenharmony_ci * nopack is initialised from sd_attrs 130062306a36Sopenharmony_ci */ 130162306a36Sopenharmony_ci REISERFS_I(inode)->i_flags &= ~i_nopack_mask; 130262306a36Sopenharmony_ci } else { 130362306a36Sopenharmony_ci /* 130462306a36Sopenharmony_ci * new stat data found, but object may have old items 130562306a36Sopenharmony_ci * (directories and symlinks) 130662306a36Sopenharmony_ci */ 130762306a36Sopenharmony_ci struct stat_data *sd = (struct stat_data *)ih_item_body(bh, ih); 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci inode->i_mode = sd_v2_mode(sd); 131062306a36Sopenharmony_ci set_nlink(inode, sd_v2_nlink(sd)); 131162306a36Sopenharmony_ci i_uid_write(inode, sd_v2_uid(sd)); 131262306a36Sopenharmony_ci inode->i_size = sd_v2_size(sd); 131362306a36Sopenharmony_ci i_gid_write(inode, sd_v2_gid(sd)); 131462306a36Sopenharmony_ci inode->i_mtime.tv_sec = sd_v2_mtime(sd); 131562306a36Sopenharmony_ci inode->i_atime.tv_sec = sd_v2_atime(sd); 131662306a36Sopenharmony_ci inode_set_ctime(inode, sd_v2_ctime(sd), 0); 131762306a36Sopenharmony_ci inode->i_mtime.tv_nsec = 0; 131862306a36Sopenharmony_ci inode->i_atime.tv_nsec = 0; 131962306a36Sopenharmony_ci inode->i_blocks = sd_v2_blocks(sd); 132062306a36Sopenharmony_ci rdev = sd_v2_rdev(sd); 132162306a36Sopenharmony_ci if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 132262306a36Sopenharmony_ci inode->i_generation = 132362306a36Sopenharmony_ci le32_to_cpu(INODE_PKEY(inode)->k_dir_id); 132462306a36Sopenharmony_ci else 132562306a36Sopenharmony_ci inode->i_generation = sd_v2_generation(sd); 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) 132862306a36Sopenharmony_ci set_inode_item_key_version(inode, KEY_FORMAT_3_5); 132962306a36Sopenharmony_ci else 133062306a36Sopenharmony_ci set_inode_item_key_version(inode, KEY_FORMAT_3_6); 133162306a36Sopenharmony_ci REISERFS_I(inode)->i_first_direct_byte = 0; 133262306a36Sopenharmony_ci set_inode_sd_version(inode, STAT_DATA_V2); 133362306a36Sopenharmony_ci inode_set_bytes(inode, 133462306a36Sopenharmony_ci to_real_used_space(inode, inode->i_blocks, 133562306a36Sopenharmony_ci SD_V2_SIZE)); 133662306a36Sopenharmony_ci /* 133762306a36Sopenharmony_ci * read persistent inode attributes from sd and initialise 133862306a36Sopenharmony_ci * generic inode flags from them 133962306a36Sopenharmony_ci */ 134062306a36Sopenharmony_ci REISERFS_I(inode)->i_attrs = sd_v2_attrs(sd); 134162306a36Sopenharmony_ci sd_attrs_to_i_attrs(sd_v2_attrs(sd), inode); 134262306a36Sopenharmony_ci } 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci pathrelse(path); 134562306a36Sopenharmony_ci if (S_ISREG(inode->i_mode)) { 134662306a36Sopenharmony_ci inode->i_op = &reiserfs_file_inode_operations; 134762306a36Sopenharmony_ci inode->i_fop = &reiserfs_file_operations; 134862306a36Sopenharmony_ci inode->i_mapping->a_ops = &reiserfs_address_space_operations; 134962306a36Sopenharmony_ci } else if (S_ISDIR(inode->i_mode)) { 135062306a36Sopenharmony_ci inode->i_op = &reiserfs_dir_inode_operations; 135162306a36Sopenharmony_ci inode->i_fop = &reiserfs_dir_operations; 135262306a36Sopenharmony_ci } else if (S_ISLNK(inode->i_mode)) { 135362306a36Sopenharmony_ci inode->i_op = &reiserfs_symlink_inode_operations; 135462306a36Sopenharmony_ci inode_nohighmem(inode); 135562306a36Sopenharmony_ci inode->i_mapping->a_ops = &reiserfs_address_space_operations; 135662306a36Sopenharmony_ci } else { 135762306a36Sopenharmony_ci inode->i_blocks = 0; 135862306a36Sopenharmony_ci inode->i_op = &reiserfs_special_inode_operations; 135962306a36Sopenharmony_ci init_special_inode(inode, inode->i_mode, new_decode_dev(rdev)); 136062306a36Sopenharmony_ci } 136162306a36Sopenharmony_ci} 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci/* update new stat data with inode fields */ 136462306a36Sopenharmony_cistatic void inode2sd(void *sd, struct inode *inode, loff_t size) 136562306a36Sopenharmony_ci{ 136662306a36Sopenharmony_ci struct stat_data *sd_v2 = (struct stat_data *)sd; 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci set_sd_v2_mode(sd_v2, inode->i_mode); 136962306a36Sopenharmony_ci set_sd_v2_nlink(sd_v2, inode->i_nlink); 137062306a36Sopenharmony_ci set_sd_v2_uid(sd_v2, i_uid_read(inode)); 137162306a36Sopenharmony_ci set_sd_v2_size(sd_v2, size); 137262306a36Sopenharmony_ci set_sd_v2_gid(sd_v2, i_gid_read(inode)); 137362306a36Sopenharmony_ci set_sd_v2_mtime(sd_v2, inode->i_mtime.tv_sec); 137462306a36Sopenharmony_ci set_sd_v2_atime(sd_v2, inode->i_atime.tv_sec); 137562306a36Sopenharmony_ci set_sd_v2_ctime(sd_v2, inode_get_ctime(inode).tv_sec); 137662306a36Sopenharmony_ci set_sd_v2_blocks(sd_v2, to_fake_used_blocks(inode, SD_V2_SIZE)); 137762306a36Sopenharmony_ci if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 137862306a36Sopenharmony_ci set_sd_v2_rdev(sd_v2, new_encode_dev(inode->i_rdev)); 137962306a36Sopenharmony_ci else 138062306a36Sopenharmony_ci set_sd_v2_generation(sd_v2, inode->i_generation); 138162306a36Sopenharmony_ci set_sd_v2_attrs(sd_v2, REISERFS_I(inode)->i_attrs); 138262306a36Sopenharmony_ci} 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci/* used to copy inode's fields to old stat data */ 138562306a36Sopenharmony_cistatic void inode2sd_v1(void *sd, struct inode *inode, loff_t size) 138662306a36Sopenharmony_ci{ 138762306a36Sopenharmony_ci struct stat_data_v1 *sd_v1 = (struct stat_data_v1 *)sd; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci set_sd_v1_mode(sd_v1, inode->i_mode); 139062306a36Sopenharmony_ci set_sd_v1_uid(sd_v1, i_uid_read(inode)); 139162306a36Sopenharmony_ci set_sd_v1_gid(sd_v1, i_gid_read(inode)); 139262306a36Sopenharmony_ci set_sd_v1_nlink(sd_v1, inode->i_nlink); 139362306a36Sopenharmony_ci set_sd_v1_size(sd_v1, size); 139462306a36Sopenharmony_ci set_sd_v1_atime(sd_v1, inode->i_atime.tv_sec); 139562306a36Sopenharmony_ci set_sd_v1_ctime(sd_v1, inode_get_ctime(inode).tv_sec); 139662306a36Sopenharmony_ci set_sd_v1_mtime(sd_v1, inode->i_mtime.tv_sec); 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 139962306a36Sopenharmony_ci set_sd_v1_rdev(sd_v1, new_encode_dev(inode->i_rdev)); 140062306a36Sopenharmony_ci else 140162306a36Sopenharmony_ci set_sd_v1_blocks(sd_v1, to_fake_used_blocks(inode, SD_V1_SIZE)); 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci /* Sigh. i_first_direct_byte is back */ 140462306a36Sopenharmony_ci set_sd_v1_first_direct_byte(sd_v1, 140562306a36Sopenharmony_ci REISERFS_I(inode)->i_first_direct_byte); 140662306a36Sopenharmony_ci} 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_ci/* 140962306a36Sopenharmony_ci * NOTE, you must prepare the buffer head before sending it here, 141062306a36Sopenharmony_ci * and then log it after the call 141162306a36Sopenharmony_ci */ 141262306a36Sopenharmony_cistatic void update_stat_data(struct treepath *path, struct inode *inode, 141362306a36Sopenharmony_ci loff_t size) 141462306a36Sopenharmony_ci{ 141562306a36Sopenharmony_ci struct buffer_head *bh; 141662306a36Sopenharmony_ci struct item_head *ih; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci bh = PATH_PLAST_BUFFER(path); 141962306a36Sopenharmony_ci ih = tp_item_head(path); 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci if (!is_statdata_le_ih(ih)) 142262306a36Sopenharmony_ci reiserfs_panic(inode->i_sb, "vs-13065", "key %k, found item %h", 142362306a36Sopenharmony_ci INODE_PKEY(inode), ih); 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci /* path points to old stat data */ 142662306a36Sopenharmony_ci if (stat_data_v1(ih)) { 142762306a36Sopenharmony_ci inode2sd_v1(ih_item_body(bh, ih), inode, size); 142862306a36Sopenharmony_ci } else { 142962306a36Sopenharmony_ci inode2sd(ih_item_body(bh, ih), inode, size); 143062306a36Sopenharmony_ci } 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci return; 143362306a36Sopenharmony_ci} 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_civoid reiserfs_update_sd_size(struct reiserfs_transaction_handle *th, 143662306a36Sopenharmony_ci struct inode *inode, loff_t size) 143762306a36Sopenharmony_ci{ 143862306a36Sopenharmony_ci struct cpu_key key; 143962306a36Sopenharmony_ci INITIALIZE_PATH(path); 144062306a36Sopenharmony_ci struct buffer_head *bh; 144162306a36Sopenharmony_ci int fs_gen; 144262306a36Sopenharmony_ci struct item_head *ih, tmp_ih; 144362306a36Sopenharmony_ci int retval; 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci BUG_ON(!th->t_trans_id); 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci /* key type is unimportant */ 144862306a36Sopenharmony_ci make_cpu_key(&key, inode, SD_OFFSET, TYPE_STAT_DATA, 3); 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci for (;;) { 145162306a36Sopenharmony_ci int pos; 145262306a36Sopenharmony_ci /* look for the object's stat data */ 145362306a36Sopenharmony_ci retval = search_item(inode->i_sb, &key, &path); 145462306a36Sopenharmony_ci if (retval == IO_ERROR) { 145562306a36Sopenharmony_ci reiserfs_error(inode->i_sb, "vs-13050", 145662306a36Sopenharmony_ci "i/o failure occurred trying to " 145762306a36Sopenharmony_ci "update %K stat data", &key); 145862306a36Sopenharmony_ci return; 145962306a36Sopenharmony_ci } 146062306a36Sopenharmony_ci if (retval == ITEM_NOT_FOUND) { 146162306a36Sopenharmony_ci pos = PATH_LAST_POSITION(&path); 146262306a36Sopenharmony_ci pathrelse(&path); 146362306a36Sopenharmony_ci if (inode->i_nlink == 0) { 146462306a36Sopenharmony_ci /*reiserfs_warning (inode->i_sb, "vs-13050: reiserfs_update_sd: i_nlink == 0, stat data not found"); */ 146562306a36Sopenharmony_ci return; 146662306a36Sopenharmony_ci } 146762306a36Sopenharmony_ci reiserfs_warning(inode->i_sb, "vs-13060", 146862306a36Sopenharmony_ci "stat data of object %k (nlink == %d) " 146962306a36Sopenharmony_ci "not found (pos %d)", 147062306a36Sopenharmony_ci INODE_PKEY(inode), inode->i_nlink, 147162306a36Sopenharmony_ci pos); 147262306a36Sopenharmony_ci reiserfs_check_path(&path); 147362306a36Sopenharmony_ci return; 147462306a36Sopenharmony_ci } 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci /* 147762306a36Sopenharmony_ci * sigh, prepare_for_journal might schedule. When it 147862306a36Sopenharmony_ci * schedules the FS might change. We have to detect that, 147962306a36Sopenharmony_ci * and loop back to the search if the stat data item has moved 148062306a36Sopenharmony_ci */ 148162306a36Sopenharmony_ci bh = get_last_bh(&path); 148262306a36Sopenharmony_ci ih = tp_item_head(&path); 148362306a36Sopenharmony_ci copy_item_head(&tmp_ih, ih); 148462306a36Sopenharmony_ci fs_gen = get_generation(inode->i_sb); 148562306a36Sopenharmony_ci reiserfs_prepare_for_journal(inode->i_sb, bh, 1); 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci /* Stat_data item has been moved after scheduling. */ 148862306a36Sopenharmony_ci if (fs_changed(fs_gen, inode->i_sb) 148962306a36Sopenharmony_ci && item_moved(&tmp_ih, &path)) { 149062306a36Sopenharmony_ci reiserfs_restore_prepared_buffer(inode->i_sb, bh); 149162306a36Sopenharmony_ci continue; 149262306a36Sopenharmony_ci } 149362306a36Sopenharmony_ci break; 149462306a36Sopenharmony_ci } 149562306a36Sopenharmony_ci update_stat_data(&path, inode, size); 149662306a36Sopenharmony_ci journal_mark_dirty(th, bh); 149762306a36Sopenharmony_ci pathrelse(&path); 149862306a36Sopenharmony_ci return; 149962306a36Sopenharmony_ci} 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci/* 150262306a36Sopenharmony_ci * reiserfs_read_locked_inode is called to read the inode off disk, and it 150362306a36Sopenharmony_ci * does a make_bad_inode when things go wrong. But, we need to make sure 150462306a36Sopenharmony_ci * and clear the key in the private portion of the inode, otherwise a 150562306a36Sopenharmony_ci * corresponding iput might try to delete whatever object the inode last 150662306a36Sopenharmony_ci * represented. 150762306a36Sopenharmony_ci */ 150862306a36Sopenharmony_cistatic void reiserfs_make_bad_inode(struct inode *inode) 150962306a36Sopenharmony_ci{ 151062306a36Sopenharmony_ci memset(INODE_PKEY(inode), 0, KEY_SIZE); 151162306a36Sopenharmony_ci make_bad_inode(inode); 151262306a36Sopenharmony_ci} 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_ci/* 151562306a36Sopenharmony_ci * initially this function was derived from minix or ext2's analog and 151662306a36Sopenharmony_ci * evolved as the prototype did 151762306a36Sopenharmony_ci */ 151862306a36Sopenharmony_ciint reiserfs_init_locked_inode(struct inode *inode, void *p) 151962306a36Sopenharmony_ci{ 152062306a36Sopenharmony_ci struct reiserfs_iget_args *args = (struct reiserfs_iget_args *)p; 152162306a36Sopenharmony_ci inode->i_ino = args->objectid; 152262306a36Sopenharmony_ci INODE_PKEY(inode)->k_dir_id = cpu_to_le32(args->dirid); 152362306a36Sopenharmony_ci return 0; 152462306a36Sopenharmony_ci} 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci/* 152762306a36Sopenharmony_ci * looks for stat data in the tree, and fills up the fields of in-core 152862306a36Sopenharmony_ci * inode stat data fields 152962306a36Sopenharmony_ci */ 153062306a36Sopenharmony_civoid reiserfs_read_locked_inode(struct inode *inode, 153162306a36Sopenharmony_ci struct reiserfs_iget_args *args) 153262306a36Sopenharmony_ci{ 153362306a36Sopenharmony_ci INITIALIZE_PATH(path_to_sd); 153462306a36Sopenharmony_ci struct cpu_key key; 153562306a36Sopenharmony_ci unsigned long dirino; 153662306a36Sopenharmony_ci int retval; 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci dirino = args->dirid; 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci /* 154162306a36Sopenharmony_ci * set version 1, version 2 could be used too, because stat data 154262306a36Sopenharmony_ci * key is the same in both versions 154362306a36Sopenharmony_ci */ 154462306a36Sopenharmony_ci _make_cpu_key(&key, KEY_FORMAT_3_5, dirino, inode->i_ino, 0, 0, 3); 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci /* look for the object's stat data */ 154762306a36Sopenharmony_ci retval = search_item(inode->i_sb, &key, &path_to_sd); 154862306a36Sopenharmony_ci if (retval == IO_ERROR) { 154962306a36Sopenharmony_ci reiserfs_error(inode->i_sb, "vs-13070", 155062306a36Sopenharmony_ci "i/o failure occurred trying to find " 155162306a36Sopenharmony_ci "stat data of %K", &key); 155262306a36Sopenharmony_ci reiserfs_make_bad_inode(inode); 155362306a36Sopenharmony_ci return; 155462306a36Sopenharmony_ci } 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci /* a stale NFS handle can trigger this without it being an error */ 155762306a36Sopenharmony_ci if (retval != ITEM_FOUND) { 155862306a36Sopenharmony_ci pathrelse(&path_to_sd); 155962306a36Sopenharmony_ci reiserfs_make_bad_inode(inode); 156062306a36Sopenharmony_ci clear_nlink(inode); 156162306a36Sopenharmony_ci return; 156262306a36Sopenharmony_ci } 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci init_inode(inode, &path_to_sd); 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci /* 156762306a36Sopenharmony_ci * It is possible that knfsd is trying to access inode of a file 156862306a36Sopenharmony_ci * that is being removed from the disk by some other thread. As we 156962306a36Sopenharmony_ci * update sd on unlink all that is required is to check for nlink 157062306a36Sopenharmony_ci * here. This bug was first found by Sizif when debugging 157162306a36Sopenharmony_ci * SquidNG/Butterfly, forgotten, and found again after Philippe 157262306a36Sopenharmony_ci * Gramoulle <philippe.gramoulle@mmania.com> reproduced it. 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ci * More logical fix would require changes in fs/inode.c:iput() to 157562306a36Sopenharmony_ci * remove inode from hash-table _after_ fs cleaned disk stuff up and 157662306a36Sopenharmony_ci * in iget() to return NULL if I_FREEING inode is found in 157762306a36Sopenharmony_ci * hash-table. 157862306a36Sopenharmony_ci */ 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci /* 158162306a36Sopenharmony_ci * Currently there is one place where it's ok to meet inode with 158262306a36Sopenharmony_ci * nlink==0: processing of open-unlinked and half-truncated files 158362306a36Sopenharmony_ci * during mount (fs/reiserfs/super.c:finish_unfinished()). 158462306a36Sopenharmony_ci */ 158562306a36Sopenharmony_ci if ((inode->i_nlink == 0) && 158662306a36Sopenharmony_ci !REISERFS_SB(inode->i_sb)->s_is_unlinked_ok) { 158762306a36Sopenharmony_ci reiserfs_warning(inode->i_sb, "vs-13075", 158862306a36Sopenharmony_ci "dead inode read from disk %K. " 158962306a36Sopenharmony_ci "This is likely to be race with knfsd. Ignore", 159062306a36Sopenharmony_ci &key); 159162306a36Sopenharmony_ci reiserfs_make_bad_inode(inode); 159262306a36Sopenharmony_ci } 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci /* init inode should be relsing */ 159562306a36Sopenharmony_ci reiserfs_check_path(&path_to_sd); 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci /* 159862306a36Sopenharmony_ci * Stat data v1 doesn't support ACLs. 159962306a36Sopenharmony_ci */ 160062306a36Sopenharmony_ci if (get_inode_sd_version(inode) == STAT_DATA_V1) 160162306a36Sopenharmony_ci cache_no_acl(inode); 160262306a36Sopenharmony_ci} 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci/* 160562306a36Sopenharmony_ci * reiserfs_find_actor() - "find actor" reiserfs supplies to iget5_locked(). 160662306a36Sopenharmony_ci * 160762306a36Sopenharmony_ci * @inode: inode from hash table to check 160862306a36Sopenharmony_ci * @opaque: "cookie" passed to iget5_locked(). This is &reiserfs_iget_args. 160962306a36Sopenharmony_ci * 161062306a36Sopenharmony_ci * This function is called by iget5_locked() to distinguish reiserfs inodes 161162306a36Sopenharmony_ci * having the same inode numbers. Such inodes can only exist due to some 161262306a36Sopenharmony_ci * error condition. One of them should be bad. Inodes with identical 161362306a36Sopenharmony_ci * inode numbers (objectids) are distinguished by parent directory ids. 161462306a36Sopenharmony_ci * 161562306a36Sopenharmony_ci */ 161662306a36Sopenharmony_ciint reiserfs_find_actor(struct inode *inode, void *opaque) 161762306a36Sopenharmony_ci{ 161862306a36Sopenharmony_ci struct reiserfs_iget_args *args; 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci args = opaque; 162162306a36Sopenharmony_ci /* args is already in CPU order */ 162262306a36Sopenharmony_ci return (inode->i_ino == args->objectid) && 162362306a36Sopenharmony_ci (le32_to_cpu(INODE_PKEY(inode)->k_dir_id) == args->dirid); 162462306a36Sopenharmony_ci} 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_cistruct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key) 162762306a36Sopenharmony_ci{ 162862306a36Sopenharmony_ci struct inode *inode; 162962306a36Sopenharmony_ci struct reiserfs_iget_args args; 163062306a36Sopenharmony_ci int depth; 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci args.objectid = key->on_disk_key.k_objectid; 163362306a36Sopenharmony_ci args.dirid = key->on_disk_key.k_dir_id; 163462306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(s); 163562306a36Sopenharmony_ci inode = iget5_locked(s, key->on_disk_key.k_objectid, 163662306a36Sopenharmony_ci reiserfs_find_actor, reiserfs_init_locked_inode, 163762306a36Sopenharmony_ci (void *)(&args)); 163862306a36Sopenharmony_ci reiserfs_write_lock_nested(s, depth); 163962306a36Sopenharmony_ci if (!inode) 164062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci if (inode->i_state & I_NEW) { 164362306a36Sopenharmony_ci reiserfs_read_locked_inode(inode, &args); 164462306a36Sopenharmony_ci unlock_new_inode(inode); 164562306a36Sopenharmony_ci } 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci if (comp_short_keys(INODE_PKEY(inode), key) || is_bad_inode(inode)) { 164862306a36Sopenharmony_ci /* either due to i/o error or a stale NFS handle */ 164962306a36Sopenharmony_ci iput(inode); 165062306a36Sopenharmony_ci inode = NULL; 165162306a36Sopenharmony_ci } 165262306a36Sopenharmony_ci return inode; 165362306a36Sopenharmony_ci} 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_cistatic struct dentry *reiserfs_get_dentry(struct super_block *sb, 165662306a36Sopenharmony_ci u32 objectid, u32 dir_id, u32 generation) 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci{ 165962306a36Sopenharmony_ci struct cpu_key key; 166062306a36Sopenharmony_ci struct inode *inode; 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci key.on_disk_key.k_objectid = objectid; 166362306a36Sopenharmony_ci key.on_disk_key.k_dir_id = dir_id; 166462306a36Sopenharmony_ci reiserfs_write_lock(sb); 166562306a36Sopenharmony_ci inode = reiserfs_iget(sb, &key); 166662306a36Sopenharmony_ci if (inode && !IS_ERR(inode) && generation != 0 && 166762306a36Sopenharmony_ci generation != inode->i_generation) { 166862306a36Sopenharmony_ci iput(inode); 166962306a36Sopenharmony_ci inode = NULL; 167062306a36Sopenharmony_ci } 167162306a36Sopenharmony_ci reiserfs_write_unlock(sb); 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci return d_obtain_alias(inode); 167462306a36Sopenharmony_ci} 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_cistruct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, 167762306a36Sopenharmony_ci int fh_len, int fh_type) 167862306a36Sopenharmony_ci{ 167962306a36Sopenharmony_ci /* 168062306a36Sopenharmony_ci * fhtype happens to reflect the number of u32s encoded. 168162306a36Sopenharmony_ci * due to a bug in earlier code, fhtype might indicate there 168262306a36Sopenharmony_ci * are more u32s then actually fitted. 168362306a36Sopenharmony_ci * so if fhtype seems to be more than len, reduce fhtype. 168462306a36Sopenharmony_ci * Valid types are: 168562306a36Sopenharmony_ci * 2 - objectid + dir_id - legacy support 168662306a36Sopenharmony_ci * 3 - objectid + dir_id + generation 168762306a36Sopenharmony_ci * 4 - objectid + dir_id + objectid and dirid of parent - legacy 168862306a36Sopenharmony_ci * 5 - objectid + dir_id + generation + objectid and dirid of parent 168962306a36Sopenharmony_ci * 6 - as above plus generation of directory 169062306a36Sopenharmony_ci * 6 does not fit in NFSv2 handles 169162306a36Sopenharmony_ci */ 169262306a36Sopenharmony_ci if (fh_type > fh_len) { 169362306a36Sopenharmony_ci if (fh_type != 6 || fh_len != 5) 169462306a36Sopenharmony_ci reiserfs_warning(sb, "reiserfs-13077", 169562306a36Sopenharmony_ci "nfsd/reiserfs, fhtype=%d, len=%d - odd", 169662306a36Sopenharmony_ci fh_type, fh_len); 169762306a36Sopenharmony_ci fh_type = fh_len; 169862306a36Sopenharmony_ci } 169962306a36Sopenharmony_ci if (fh_len < 2) 170062306a36Sopenharmony_ci return NULL; 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1], 170362306a36Sopenharmony_ci (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0); 170462306a36Sopenharmony_ci} 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_cistruct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, 170762306a36Sopenharmony_ci int fh_len, int fh_type) 170862306a36Sopenharmony_ci{ 170962306a36Sopenharmony_ci if (fh_type > fh_len) 171062306a36Sopenharmony_ci fh_type = fh_len; 171162306a36Sopenharmony_ci if (fh_type < 4) 171262306a36Sopenharmony_ci return NULL; 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci return reiserfs_get_dentry(sb, 171562306a36Sopenharmony_ci (fh_type >= 5) ? fid->raw[3] : fid->raw[2], 171662306a36Sopenharmony_ci (fh_type >= 5) ? fid->raw[4] : fid->raw[3], 171762306a36Sopenharmony_ci (fh_type == 6) ? fid->raw[5] : 0); 171862306a36Sopenharmony_ci} 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ciint reiserfs_encode_fh(struct inode *inode, __u32 * data, int *lenp, 172162306a36Sopenharmony_ci struct inode *parent) 172262306a36Sopenharmony_ci{ 172362306a36Sopenharmony_ci int maxlen = *lenp; 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci if (parent && (maxlen < 5)) { 172662306a36Sopenharmony_ci *lenp = 5; 172762306a36Sopenharmony_ci return FILEID_INVALID; 172862306a36Sopenharmony_ci } else if (maxlen < 3) { 172962306a36Sopenharmony_ci *lenp = 3; 173062306a36Sopenharmony_ci return FILEID_INVALID; 173162306a36Sopenharmony_ci } 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_ci data[0] = inode->i_ino; 173462306a36Sopenharmony_ci data[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id); 173562306a36Sopenharmony_ci data[2] = inode->i_generation; 173662306a36Sopenharmony_ci *lenp = 3; 173762306a36Sopenharmony_ci if (parent) { 173862306a36Sopenharmony_ci data[3] = parent->i_ino; 173962306a36Sopenharmony_ci data[4] = le32_to_cpu(INODE_PKEY(parent)->k_dir_id); 174062306a36Sopenharmony_ci *lenp = 5; 174162306a36Sopenharmony_ci if (maxlen >= 6) { 174262306a36Sopenharmony_ci data[5] = parent->i_generation; 174362306a36Sopenharmony_ci *lenp = 6; 174462306a36Sopenharmony_ci } 174562306a36Sopenharmony_ci } 174662306a36Sopenharmony_ci return *lenp; 174762306a36Sopenharmony_ci} 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci/* 175062306a36Sopenharmony_ci * looks for stat data, then copies fields to it, marks the buffer 175162306a36Sopenharmony_ci * containing stat data as dirty 175262306a36Sopenharmony_ci */ 175362306a36Sopenharmony_ci/* 175462306a36Sopenharmony_ci * reiserfs inodes are never really dirty, since the dirty inode call 175562306a36Sopenharmony_ci * always logs them. This call allows the VFS inode marking routines 175662306a36Sopenharmony_ci * to properly mark inodes for datasync and such, but only actually 175762306a36Sopenharmony_ci * does something when called for a synchronous update. 175862306a36Sopenharmony_ci */ 175962306a36Sopenharmony_ciint reiserfs_write_inode(struct inode *inode, struct writeback_control *wbc) 176062306a36Sopenharmony_ci{ 176162306a36Sopenharmony_ci struct reiserfs_transaction_handle th; 176262306a36Sopenharmony_ci int jbegin_count = 1; 176362306a36Sopenharmony_ci 176462306a36Sopenharmony_ci if (sb_rdonly(inode->i_sb)) 176562306a36Sopenharmony_ci return -EROFS; 176662306a36Sopenharmony_ci /* 176762306a36Sopenharmony_ci * memory pressure can sometimes initiate write_inode calls with 176862306a36Sopenharmony_ci * sync == 1, 176962306a36Sopenharmony_ci * these cases are just when the system needs ram, not when the 177062306a36Sopenharmony_ci * inode needs to reach disk for safety, and they can safely be 177162306a36Sopenharmony_ci * ignored because the altered inode has already been logged. 177262306a36Sopenharmony_ci */ 177362306a36Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL && !(current->flags & PF_MEMALLOC)) { 177462306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 177562306a36Sopenharmony_ci if (!journal_begin(&th, inode->i_sb, jbegin_count)) { 177662306a36Sopenharmony_ci reiserfs_update_sd(&th, inode); 177762306a36Sopenharmony_ci journal_end_sync(&th); 177862306a36Sopenharmony_ci } 177962306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 178062306a36Sopenharmony_ci } 178162306a36Sopenharmony_ci return 0; 178262306a36Sopenharmony_ci} 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci/* 178562306a36Sopenharmony_ci * stat data of new object is inserted already, this inserts the item 178662306a36Sopenharmony_ci * containing "." and ".." entries 178762306a36Sopenharmony_ci */ 178862306a36Sopenharmony_cistatic int reiserfs_new_directory(struct reiserfs_transaction_handle *th, 178962306a36Sopenharmony_ci struct inode *inode, 179062306a36Sopenharmony_ci struct item_head *ih, struct treepath *path, 179162306a36Sopenharmony_ci struct inode *dir) 179262306a36Sopenharmony_ci{ 179362306a36Sopenharmony_ci struct super_block *sb = th->t_super; 179462306a36Sopenharmony_ci char empty_dir[EMPTY_DIR_SIZE]; 179562306a36Sopenharmony_ci char *body = empty_dir; 179662306a36Sopenharmony_ci struct cpu_key key; 179762306a36Sopenharmony_ci int retval; 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci BUG_ON(!th->t_trans_id); 180062306a36Sopenharmony_ci 180162306a36Sopenharmony_ci _make_cpu_key(&key, KEY_FORMAT_3_5, le32_to_cpu(ih->ih_key.k_dir_id), 180262306a36Sopenharmony_ci le32_to_cpu(ih->ih_key.k_objectid), DOT_OFFSET, 180362306a36Sopenharmony_ci TYPE_DIRENTRY, 3 /*key length */ ); 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci /* 180662306a36Sopenharmony_ci * compose item head for new item. Directories consist of items of 180762306a36Sopenharmony_ci * old type (ITEM_VERSION_1). Do not set key (second arg is 0), it 180862306a36Sopenharmony_ci * is done by reiserfs_new_inode 180962306a36Sopenharmony_ci */ 181062306a36Sopenharmony_ci if (old_format_only(sb)) { 181162306a36Sopenharmony_ci make_le_item_head(ih, NULL, KEY_FORMAT_3_5, DOT_OFFSET, 181262306a36Sopenharmony_ci TYPE_DIRENTRY, EMPTY_DIR_SIZE_V1, 2); 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci make_empty_dir_item_v1(body, ih->ih_key.k_dir_id, 181562306a36Sopenharmony_ci ih->ih_key.k_objectid, 181662306a36Sopenharmony_ci INODE_PKEY(dir)->k_dir_id, 181762306a36Sopenharmony_ci INODE_PKEY(dir)->k_objectid); 181862306a36Sopenharmony_ci } else { 181962306a36Sopenharmony_ci make_le_item_head(ih, NULL, KEY_FORMAT_3_5, DOT_OFFSET, 182062306a36Sopenharmony_ci TYPE_DIRENTRY, EMPTY_DIR_SIZE, 2); 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci make_empty_dir_item(body, ih->ih_key.k_dir_id, 182362306a36Sopenharmony_ci ih->ih_key.k_objectid, 182462306a36Sopenharmony_ci INODE_PKEY(dir)->k_dir_id, 182562306a36Sopenharmony_ci INODE_PKEY(dir)->k_objectid); 182662306a36Sopenharmony_ci } 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ci /* look for place in the tree for new item */ 182962306a36Sopenharmony_ci retval = search_item(sb, &key, path); 183062306a36Sopenharmony_ci if (retval == IO_ERROR) { 183162306a36Sopenharmony_ci reiserfs_error(sb, "vs-13080", 183262306a36Sopenharmony_ci "i/o failure occurred creating new directory"); 183362306a36Sopenharmony_ci return -EIO; 183462306a36Sopenharmony_ci } 183562306a36Sopenharmony_ci if (retval == ITEM_FOUND) { 183662306a36Sopenharmony_ci pathrelse(path); 183762306a36Sopenharmony_ci reiserfs_warning(sb, "vs-13070", 183862306a36Sopenharmony_ci "object with this key exists (%k)", 183962306a36Sopenharmony_ci &(ih->ih_key)); 184062306a36Sopenharmony_ci return -EEXIST; 184162306a36Sopenharmony_ci } 184262306a36Sopenharmony_ci 184362306a36Sopenharmony_ci /* insert item, that is empty directory item */ 184462306a36Sopenharmony_ci return reiserfs_insert_item(th, path, &key, ih, inode, body); 184562306a36Sopenharmony_ci} 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_ci/* 184862306a36Sopenharmony_ci * stat data of object has been inserted, this inserts the item 184962306a36Sopenharmony_ci * containing the body of symlink 185062306a36Sopenharmony_ci */ 185162306a36Sopenharmony_cistatic int reiserfs_new_symlink(struct reiserfs_transaction_handle *th, 185262306a36Sopenharmony_ci struct inode *inode, 185362306a36Sopenharmony_ci struct item_head *ih, 185462306a36Sopenharmony_ci struct treepath *path, const char *symname, 185562306a36Sopenharmony_ci int item_len) 185662306a36Sopenharmony_ci{ 185762306a36Sopenharmony_ci struct super_block *sb = th->t_super; 185862306a36Sopenharmony_ci struct cpu_key key; 185962306a36Sopenharmony_ci int retval; 186062306a36Sopenharmony_ci 186162306a36Sopenharmony_ci BUG_ON(!th->t_trans_id); 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci _make_cpu_key(&key, KEY_FORMAT_3_5, 186462306a36Sopenharmony_ci le32_to_cpu(ih->ih_key.k_dir_id), 186562306a36Sopenharmony_ci le32_to_cpu(ih->ih_key.k_objectid), 186662306a36Sopenharmony_ci 1, TYPE_DIRECT, 3 /*key length */ ); 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci make_le_item_head(ih, NULL, KEY_FORMAT_3_5, 1, TYPE_DIRECT, item_len, 186962306a36Sopenharmony_ci 0 /*free_space */ ); 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci /* look for place in the tree for new item */ 187262306a36Sopenharmony_ci retval = search_item(sb, &key, path); 187362306a36Sopenharmony_ci if (retval == IO_ERROR) { 187462306a36Sopenharmony_ci reiserfs_error(sb, "vs-13080", 187562306a36Sopenharmony_ci "i/o failure occurred creating new symlink"); 187662306a36Sopenharmony_ci return -EIO; 187762306a36Sopenharmony_ci } 187862306a36Sopenharmony_ci if (retval == ITEM_FOUND) { 187962306a36Sopenharmony_ci pathrelse(path); 188062306a36Sopenharmony_ci reiserfs_warning(sb, "vs-13080", 188162306a36Sopenharmony_ci "object with this key exists (%k)", 188262306a36Sopenharmony_ci &(ih->ih_key)); 188362306a36Sopenharmony_ci return -EEXIST; 188462306a36Sopenharmony_ci } 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci /* insert item, that is body of symlink */ 188762306a36Sopenharmony_ci return reiserfs_insert_item(th, path, &key, ih, inode, symname); 188862306a36Sopenharmony_ci} 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci/* 189162306a36Sopenharmony_ci * inserts the stat data into the tree, and then calls 189262306a36Sopenharmony_ci * reiserfs_new_directory (to insert ".", ".." item if new object is 189362306a36Sopenharmony_ci * directory) or reiserfs_new_symlink (to insert symlink body if new 189462306a36Sopenharmony_ci * object is symlink) or nothing (if new object is regular file) 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci * NOTE! uid and gid must already be set in the inode. If we return 189762306a36Sopenharmony_ci * non-zero due to an error, we have to drop the quota previously allocated 189862306a36Sopenharmony_ci * for the fresh inode. This can only be done outside a transaction, so 189962306a36Sopenharmony_ci * if we return non-zero, we also end the transaction. 190062306a36Sopenharmony_ci * 190162306a36Sopenharmony_ci * @th: active transaction handle 190262306a36Sopenharmony_ci * @dir: parent directory for new inode 190362306a36Sopenharmony_ci * @mode: mode of new inode 190462306a36Sopenharmony_ci * @symname: symlink contents if inode is symlink 190562306a36Sopenharmony_ci * @isize: 0 for regular file, EMPTY_DIR_SIZE for dirs, strlen(symname) for 190662306a36Sopenharmony_ci * symlinks 190762306a36Sopenharmony_ci * @inode: inode to be filled 190862306a36Sopenharmony_ci * @security: optional security context to associate with this inode 190962306a36Sopenharmony_ci */ 191062306a36Sopenharmony_ciint reiserfs_new_inode(struct reiserfs_transaction_handle *th, 191162306a36Sopenharmony_ci struct inode *dir, umode_t mode, const char *symname, 191262306a36Sopenharmony_ci /* 0 for regular, EMTRY_DIR_SIZE for dirs, 191362306a36Sopenharmony_ci strlen (symname) for symlinks) */ 191462306a36Sopenharmony_ci loff_t i_size, struct dentry *dentry, 191562306a36Sopenharmony_ci struct inode *inode, 191662306a36Sopenharmony_ci struct reiserfs_security_handle *security) 191762306a36Sopenharmony_ci{ 191862306a36Sopenharmony_ci struct super_block *sb = dir->i_sb; 191962306a36Sopenharmony_ci struct reiserfs_iget_args args; 192062306a36Sopenharmony_ci INITIALIZE_PATH(path_to_key); 192162306a36Sopenharmony_ci struct cpu_key key; 192262306a36Sopenharmony_ci struct item_head ih; 192362306a36Sopenharmony_ci struct stat_data sd; 192462306a36Sopenharmony_ci int retval; 192562306a36Sopenharmony_ci int err; 192662306a36Sopenharmony_ci int depth; 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci BUG_ON(!th->t_trans_id); 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(sb); 193162306a36Sopenharmony_ci err = dquot_alloc_inode(inode); 193262306a36Sopenharmony_ci reiserfs_write_lock_nested(sb, depth); 193362306a36Sopenharmony_ci if (err) 193462306a36Sopenharmony_ci goto out_end_trans; 193562306a36Sopenharmony_ci if (!dir->i_nlink) { 193662306a36Sopenharmony_ci err = -EPERM; 193762306a36Sopenharmony_ci goto out_bad_inode; 193862306a36Sopenharmony_ci } 193962306a36Sopenharmony_ci 194062306a36Sopenharmony_ci /* item head of new item */ 194162306a36Sopenharmony_ci ih.ih_key.k_dir_id = reiserfs_choose_packing(dir); 194262306a36Sopenharmony_ci ih.ih_key.k_objectid = cpu_to_le32(reiserfs_get_unused_objectid(th)); 194362306a36Sopenharmony_ci if (!ih.ih_key.k_objectid) { 194462306a36Sopenharmony_ci err = -ENOMEM; 194562306a36Sopenharmony_ci goto out_bad_inode; 194662306a36Sopenharmony_ci } 194762306a36Sopenharmony_ci args.objectid = inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid); 194862306a36Sopenharmony_ci if (old_format_only(sb)) 194962306a36Sopenharmony_ci make_le_item_head(&ih, NULL, KEY_FORMAT_3_5, SD_OFFSET, 195062306a36Sopenharmony_ci TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT); 195162306a36Sopenharmony_ci else 195262306a36Sopenharmony_ci make_le_item_head(&ih, NULL, KEY_FORMAT_3_6, SD_OFFSET, 195362306a36Sopenharmony_ci TYPE_STAT_DATA, SD_SIZE, MAX_US_INT); 195462306a36Sopenharmony_ci memcpy(INODE_PKEY(inode), &ih.ih_key, KEY_SIZE); 195562306a36Sopenharmony_ci args.dirid = le32_to_cpu(ih.ih_key.k_dir_id); 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(inode->i_sb); 195862306a36Sopenharmony_ci err = insert_inode_locked4(inode, args.objectid, 195962306a36Sopenharmony_ci reiserfs_find_actor, &args); 196062306a36Sopenharmony_ci reiserfs_write_lock_nested(inode->i_sb, depth); 196162306a36Sopenharmony_ci if (err) { 196262306a36Sopenharmony_ci err = -EINVAL; 196362306a36Sopenharmony_ci goto out_bad_inode; 196462306a36Sopenharmony_ci } 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ci if (old_format_only(sb)) 196762306a36Sopenharmony_ci /* 196862306a36Sopenharmony_ci * not a perfect generation count, as object ids can be reused, 196962306a36Sopenharmony_ci * but this is as good as reiserfs can do right now. 197062306a36Sopenharmony_ci * note that the private part of inode isn't filled in yet, 197162306a36Sopenharmony_ci * we have to use the directory. 197262306a36Sopenharmony_ci */ 197362306a36Sopenharmony_ci inode->i_generation = le32_to_cpu(INODE_PKEY(dir)->k_objectid); 197462306a36Sopenharmony_ci else 197562306a36Sopenharmony_ci#if defined( USE_INODE_GENERATION_COUNTER ) 197662306a36Sopenharmony_ci inode->i_generation = 197762306a36Sopenharmony_ci le32_to_cpu(REISERFS_SB(sb)->s_rs->s_inode_generation); 197862306a36Sopenharmony_ci#else 197962306a36Sopenharmony_ci inode->i_generation = ++event; 198062306a36Sopenharmony_ci#endif 198162306a36Sopenharmony_ci 198262306a36Sopenharmony_ci /* fill stat data */ 198362306a36Sopenharmony_ci set_nlink(inode, (S_ISDIR(mode) ? 2 : 1)); 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci /* uid and gid must already be set by the caller for quota init */ 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode); 198862306a36Sopenharmony_ci inode->i_size = i_size; 198962306a36Sopenharmony_ci inode->i_blocks = 0; 199062306a36Sopenharmony_ci inode->i_bytes = 0; 199162306a36Sopenharmony_ci REISERFS_I(inode)->i_first_direct_byte = S_ISLNK(mode) ? 1 : 199262306a36Sopenharmony_ci U32_MAX /*NO_BYTES_IN_DIRECT_ITEM */ ; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci INIT_LIST_HEAD(&REISERFS_I(inode)->i_prealloc_list); 199562306a36Sopenharmony_ci REISERFS_I(inode)->i_flags = 0; 199662306a36Sopenharmony_ci REISERFS_I(inode)->i_prealloc_block = 0; 199762306a36Sopenharmony_ci REISERFS_I(inode)->i_prealloc_count = 0; 199862306a36Sopenharmony_ci REISERFS_I(inode)->i_trans_id = 0; 199962306a36Sopenharmony_ci REISERFS_I(inode)->i_jl = NULL; 200062306a36Sopenharmony_ci REISERFS_I(inode)->i_attrs = 200162306a36Sopenharmony_ci REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK; 200262306a36Sopenharmony_ci sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode); 200362306a36Sopenharmony_ci reiserfs_init_xattr_rwsem(inode); 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci /* key to search for correct place for new stat data */ 200662306a36Sopenharmony_ci _make_cpu_key(&key, KEY_FORMAT_3_6, le32_to_cpu(ih.ih_key.k_dir_id), 200762306a36Sopenharmony_ci le32_to_cpu(ih.ih_key.k_objectid), SD_OFFSET, 200862306a36Sopenharmony_ci TYPE_STAT_DATA, 3 /*key length */ ); 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci /* find proper place for inserting of stat data */ 201162306a36Sopenharmony_ci retval = search_item(sb, &key, &path_to_key); 201262306a36Sopenharmony_ci if (retval == IO_ERROR) { 201362306a36Sopenharmony_ci err = -EIO; 201462306a36Sopenharmony_ci goto out_bad_inode; 201562306a36Sopenharmony_ci } 201662306a36Sopenharmony_ci if (retval == ITEM_FOUND) { 201762306a36Sopenharmony_ci pathrelse(&path_to_key); 201862306a36Sopenharmony_ci err = -EEXIST; 201962306a36Sopenharmony_ci goto out_bad_inode; 202062306a36Sopenharmony_ci } 202162306a36Sopenharmony_ci if (old_format_only(sb)) { 202262306a36Sopenharmony_ci /* i_uid or i_gid is too big to be stored in stat data v3.5 */ 202362306a36Sopenharmony_ci if (i_uid_read(inode) & ~0xffff || i_gid_read(inode) & ~0xffff) { 202462306a36Sopenharmony_ci pathrelse(&path_to_key); 202562306a36Sopenharmony_ci err = -EINVAL; 202662306a36Sopenharmony_ci goto out_bad_inode; 202762306a36Sopenharmony_ci } 202862306a36Sopenharmony_ci inode2sd_v1(&sd, inode, inode->i_size); 202962306a36Sopenharmony_ci } else { 203062306a36Sopenharmony_ci inode2sd(&sd, inode, inode->i_size); 203162306a36Sopenharmony_ci } 203262306a36Sopenharmony_ci /* 203362306a36Sopenharmony_ci * store in in-core inode the key of stat data and version all 203462306a36Sopenharmony_ci * object items will have (directory items will have old offset 203562306a36Sopenharmony_ci * format, other new objects will consist of new items) 203662306a36Sopenharmony_ci */ 203762306a36Sopenharmony_ci if (old_format_only(sb) || S_ISDIR(mode) || S_ISLNK(mode)) 203862306a36Sopenharmony_ci set_inode_item_key_version(inode, KEY_FORMAT_3_5); 203962306a36Sopenharmony_ci else 204062306a36Sopenharmony_ci set_inode_item_key_version(inode, KEY_FORMAT_3_6); 204162306a36Sopenharmony_ci if (old_format_only(sb)) 204262306a36Sopenharmony_ci set_inode_sd_version(inode, STAT_DATA_V1); 204362306a36Sopenharmony_ci else 204462306a36Sopenharmony_ci set_inode_sd_version(inode, STAT_DATA_V2); 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci /* insert the stat data into the tree */ 204762306a36Sopenharmony_ci#ifdef DISPLACE_NEW_PACKING_LOCALITIES 204862306a36Sopenharmony_ci if (REISERFS_I(dir)->new_packing_locality) 204962306a36Sopenharmony_ci th->displace_new_blocks = 1; 205062306a36Sopenharmony_ci#endif 205162306a36Sopenharmony_ci retval = 205262306a36Sopenharmony_ci reiserfs_insert_item(th, &path_to_key, &key, &ih, inode, 205362306a36Sopenharmony_ci (char *)(&sd)); 205462306a36Sopenharmony_ci if (retval) { 205562306a36Sopenharmony_ci err = retval; 205662306a36Sopenharmony_ci reiserfs_check_path(&path_to_key); 205762306a36Sopenharmony_ci goto out_bad_inode; 205862306a36Sopenharmony_ci } 205962306a36Sopenharmony_ci#ifdef DISPLACE_NEW_PACKING_LOCALITIES 206062306a36Sopenharmony_ci if (!th->displace_new_blocks) 206162306a36Sopenharmony_ci REISERFS_I(dir)->new_packing_locality = 0; 206262306a36Sopenharmony_ci#endif 206362306a36Sopenharmony_ci if (S_ISDIR(mode)) { 206462306a36Sopenharmony_ci /* insert item with "." and ".." */ 206562306a36Sopenharmony_ci retval = 206662306a36Sopenharmony_ci reiserfs_new_directory(th, inode, &ih, &path_to_key, dir); 206762306a36Sopenharmony_ci } 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci if (S_ISLNK(mode)) { 207062306a36Sopenharmony_ci /* insert body of symlink */ 207162306a36Sopenharmony_ci if (!old_format_only(sb)) 207262306a36Sopenharmony_ci i_size = ROUND_UP(i_size); 207362306a36Sopenharmony_ci retval = 207462306a36Sopenharmony_ci reiserfs_new_symlink(th, inode, &ih, &path_to_key, symname, 207562306a36Sopenharmony_ci i_size); 207662306a36Sopenharmony_ci } 207762306a36Sopenharmony_ci if (retval) { 207862306a36Sopenharmony_ci err = retval; 207962306a36Sopenharmony_ci reiserfs_check_path(&path_to_key); 208062306a36Sopenharmony_ci journal_end(th); 208162306a36Sopenharmony_ci goto out_inserted_sd; 208262306a36Sopenharmony_ci } 208362306a36Sopenharmony_ci 208462306a36Sopenharmony_ci /* 208562306a36Sopenharmony_ci * Mark it private if we're creating the privroot 208662306a36Sopenharmony_ci * or something under it. 208762306a36Sopenharmony_ci */ 208862306a36Sopenharmony_ci if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root) 208962306a36Sopenharmony_ci reiserfs_init_priv_inode(inode); 209062306a36Sopenharmony_ci 209162306a36Sopenharmony_ci if (reiserfs_posixacl(inode->i_sb)) { 209262306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 209362306a36Sopenharmony_ci retval = reiserfs_inherit_default_acl(th, dir, dentry, inode); 209462306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 209562306a36Sopenharmony_ci if (retval) { 209662306a36Sopenharmony_ci err = retval; 209762306a36Sopenharmony_ci reiserfs_check_path(&path_to_key); 209862306a36Sopenharmony_ci journal_end(th); 209962306a36Sopenharmony_ci goto out_inserted_sd; 210062306a36Sopenharmony_ci } 210162306a36Sopenharmony_ci } else if (inode->i_sb->s_flags & SB_POSIXACL) { 210262306a36Sopenharmony_ci reiserfs_warning(inode->i_sb, "jdm-13090", 210362306a36Sopenharmony_ci "ACLs aren't enabled in the fs, " 210462306a36Sopenharmony_ci "but vfs thinks they are!"); 210562306a36Sopenharmony_ci } 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_ci if (security->name) { 210862306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 210962306a36Sopenharmony_ci retval = reiserfs_security_write(th, inode, security); 211062306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 211162306a36Sopenharmony_ci if (retval) { 211262306a36Sopenharmony_ci err = retval; 211362306a36Sopenharmony_ci reiserfs_check_path(&path_to_key); 211462306a36Sopenharmony_ci retval = journal_end(th); 211562306a36Sopenharmony_ci if (retval) 211662306a36Sopenharmony_ci err = retval; 211762306a36Sopenharmony_ci goto out_inserted_sd; 211862306a36Sopenharmony_ci } 211962306a36Sopenharmony_ci } 212062306a36Sopenharmony_ci 212162306a36Sopenharmony_ci reiserfs_update_sd(th, inode); 212262306a36Sopenharmony_ci reiserfs_check_path(&path_to_key); 212362306a36Sopenharmony_ci 212462306a36Sopenharmony_ci return 0; 212562306a36Sopenharmony_ci 212662306a36Sopenharmony_ciout_bad_inode: 212762306a36Sopenharmony_ci /* Invalidate the object, nothing was inserted yet */ 212862306a36Sopenharmony_ci INODE_PKEY(inode)->k_objectid = 0; 212962306a36Sopenharmony_ci 213062306a36Sopenharmony_ci /* Quota change must be inside a transaction for journaling */ 213162306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(inode->i_sb); 213262306a36Sopenharmony_ci dquot_free_inode(inode); 213362306a36Sopenharmony_ci reiserfs_write_lock_nested(inode->i_sb, depth); 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_ciout_end_trans: 213662306a36Sopenharmony_ci journal_end(th); 213762306a36Sopenharmony_ci /* 213862306a36Sopenharmony_ci * Drop can be outside and it needs more credits so it's better 213962306a36Sopenharmony_ci * to have it outside 214062306a36Sopenharmony_ci */ 214162306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(inode->i_sb); 214262306a36Sopenharmony_ci dquot_drop(inode); 214362306a36Sopenharmony_ci reiserfs_write_lock_nested(inode->i_sb, depth); 214462306a36Sopenharmony_ci inode->i_flags |= S_NOQUOTA; 214562306a36Sopenharmony_ci make_bad_inode(inode); 214662306a36Sopenharmony_ci 214762306a36Sopenharmony_ciout_inserted_sd: 214862306a36Sopenharmony_ci clear_nlink(inode); 214962306a36Sopenharmony_ci th->t_trans_id = 0; /* so the caller can't use this handle later */ 215062306a36Sopenharmony_ci if (inode->i_state & I_NEW) 215162306a36Sopenharmony_ci unlock_new_inode(inode); 215262306a36Sopenharmony_ci iput(inode); 215362306a36Sopenharmony_ci return err; 215462306a36Sopenharmony_ci} 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_ci/* 215762306a36Sopenharmony_ci * finds the tail page in the page cache, 215862306a36Sopenharmony_ci * reads the last block in. 215962306a36Sopenharmony_ci * 216062306a36Sopenharmony_ci * On success, page_result is set to a locked, pinned page, and bh_result 216162306a36Sopenharmony_ci * is set to an up to date buffer for the last block in the file. returns 0. 216262306a36Sopenharmony_ci * 216362306a36Sopenharmony_ci * tail conversion is not done, so bh_result might not be valid for writing 216462306a36Sopenharmony_ci * check buffer_mapped(bh_result) and bh_result->b_blocknr != 0 before 216562306a36Sopenharmony_ci * trying to write the block. 216662306a36Sopenharmony_ci * 216762306a36Sopenharmony_ci * on failure, nonzero is returned, page_result and bh_result are untouched. 216862306a36Sopenharmony_ci */ 216962306a36Sopenharmony_cistatic int grab_tail_page(struct inode *inode, 217062306a36Sopenharmony_ci struct page **page_result, 217162306a36Sopenharmony_ci struct buffer_head **bh_result) 217262306a36Sopenharmony_ci{ 217362306a36Sopenharmony_ci 217462306a36Sopenharmony_ci /* 217562306a36Sopenharmony_ci * we want the page with the last byte in the file, 217662306a36Sopenharmony_ci * not the page that will hold the next byte for appending 217762306a36Sopenharmony_ci */ 217862306a36Sopenharmony_ci unsigned long index = (inode->i_size - 1) >> PAGE_SHIFT; 217962306a36Sopenharmony_ci unsigned long pos = 0; 218062306a36Sopenharmony_ci unsigned long start = 0; 218162306a36Sopenharmony_ci unsigned long blocksize = inode->i_sb->s_blocksize; 218262306a36Sopenharmony_ci unsigned long offset = (inode->i_size) & (PAGE_SIZE - 1); 218362306a36Sopenharmony_ci struct buffer_head *bh; 218462306a36Sopenharmony_ci struct buffer_head *head; 218562306a36Sopenharmony_ci struct page *page; 218662306a36Sopenharmony_ci int error; 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_ci /* 218962306a36Sopenharmony_ci * we know that we are only called with inode->i_size > 0. 219062306a36Sopenharmony_ci * we also know that a file tail can never be as big as a block 219162306a36Sopenharmony_ci * If i_size % blocksize == 0, our file is currently block aligned 219262306a36Sopenharmony_ci * and it won't need converting or zeroing after a truncate. 219362306a36Sopenharmony_ci */ 219462306a36Sopenharmony_ci if ((offset & (blocksize - 1)) == 0) { 219562306a36Sopenharmony_ci return -ENOENT; 219662306a36Sopenharmony_ci } 219762306a36Sopenharmony_ci page = grab_cache_page(inode->i_mapping, index); 219862306a36Sopenharmony_ci error = -ENOMEM; 219962306a36Sopenharmony_ci if (!page) { 220062306a36Sopenharmony_ci goto out; 220162306a36Sopenharmony_ci } 220262306a36Sopenharmony_ci /* start within the page of the last block in the file */ 220362306a36Sopenharmony_ci start = (offset / blocksize) * blocksize; 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci error = __block_write_begin(page, start, offset - start, 220662306a36Sopenharmony_ci reiserfs_get_block_create_0); 220762306a36Sopenharmony_ci if (error) 220862306a36Sopenharmony_ci goto unlock; 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci head = page_buffers(page); 221162306a36Sopenharmony_ci bh = head; 221262306a36Sopenharmony_ci do { 221362306a36Sopenharmony_ci if (pos >= start) { 221462306a36Sopenharmony_ci break; 221562306a36Sopenharmony_ci } 221662306a36Sopenharmony_ci bh = bh->b_this_page; 221762306a36Sopenharmony_ci pos += blocksize; 221862306a36Sopenharmony_ci } while (bh != head); 221962306a36Sopenharmony_ci 222062306a36Sopenharmony_ci if (!buffer_uptodate(bh)) { 222162306a36Sopenharmony_ci /* 222262306a36Sopenharmony_ci * note, this should never happen, prepare_write should be 222362306a36Sopenharmony_ci * taking care of this for us. If the buffer isn't up to 222462306a36Sopenharmony_ci * date, I've screwed up the code to find the buffer, or the 222562306a36Sopenharmony_ci * code to call prepare_write 222662306a36Sopenharmony_ci */ 222762306a36Sopenharmony_ci reiserfs_error(inode->i_sb, "clm-6000", 222862306a36Sopenharmony_ci "error reading block %lu", bh->b_blocknr); 222962306a36Sopenharmony_ci error = -EIO; 223062306a36Sopenharmony_ci goto unlock; 223162306a36Sopenharmony_ci } 223262306a36Sopenharmony_ci *bh_result = bh; 223362306a36Sopenharmony_ci *page_result = page; 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ciout: 223662306a36Sopenharmony_ci return error; 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ciunlock: 223962306a36Sopenharmony_ci unlock_page(page); 224062306a36Sopenharmony_ci put_page(page); 224162306a36Sopenharmony_ci return error; 224262306a36Sopenharmony_ci} 224362306a36Sopenharmony_ci 224462306a36Sopenharmony_ci/* 224562306a36Sopenharmony_ci * vfs version of truncate file. Must NOT be called with 224662306a36Sopenharmony_ci * a transaction already started. 224762306a36Sopenharmony_ci * 224862306a36Sopenharmony_ci * some code taken from block_truncate_page 224962306a36Sopenharmony_ci */ 225062306a36Sopenharmony_ciint reiserfs_truncate_file(struct inode *inode, int update_timestamps) 225162306a36Sopenharmony_ci{ 225262306a36Sopenharmony_ci struct reiserfs_transaction_handle th; 225362306a36Sopenharmony_ci /* we want the offset for the first byte after the end of the file */ 225462306a36Sopenharmony_ci unsigned long offset = inode->i_size & (PAGE_SIZE - 1); 225562306a36Sopenharmony_ci unsigned blocksize = inode->i_sb->s_blocksize; 225662306a36Sopenharmony_ci unsigned length; 225762306a36Sopenharmony_ci struct page *page = NULL; 225862306a36Sopenharmony_ci int error; 225962306a36Sopenharmony_ci struct buffer_head *bh = NULL; 226062306a36Sopenharmony_ci int err2; 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 226362306a36Sopenharmony_ci 226462306a36Sopenharmony_ci if (inode->i_size > 0) { 226562306a36Sopenharmony_ci error = grab_tail_page(inode, &page, &bh); 226662306a36Sopenharmony_ci if (error) { 226762306a36Sopenharmony_ci /* 226862306a36Sopenharmony_ci * -ENOENT means we truncated past the end of the 226962306a36Sopenharmony_ci * file, and get_block_create_0 could not find a 227062306a36Sopenharmony_ci * block to read in, which is ok. 227162306a36Sopenharmony_ci */ 227262306a36Sopenharmony_ci if (error != -ENOENT) 227362306a36Sopenharmony_ci reiserfs_error(inode->i_sb, "clm-6001", 227462306a36Sopenharmony_ci "grab_tail_page failed %d", 227562306a36Sopenharmony_ci error); 227662306a36Sopenharmony_ci page = NULL; 227762306a36Sopenharmony_ci bh = NULL; 227862306a36Sopenharmony_ci } 227962306a36Sopenharmony_ci } 228062306a36Sopenharmony_ci 228162306a36Sopenharmony_ci /* 228262306a36Sopenharmony_ci * so, if page != NULL, we have a buffer head for the offset at 228362306a36Sopenharmony_ci * the end of the file. if the bh is mapped, and bh->b_blocknr != 0, 228462306a36Sopenharmony_ci * then we have an unformatted node. Otherwise, we have a direct item, 228562306a36Sopenharmony_ci * and no zeroing is required on disk. We zero after the truncate, 228662306a36Sopenharmony_ci * because the truncate might pack the item anyway 228762306a36Sopenharmony_ci * (it will unmap bh if it packs). 228862306a36Sopenharmony_ci * 228962306a36Sopenharmony_ci * it is enough to reserve space in transaction for 2 balancings: 229062306a36Sopenharmony_ci * one for "save" link adding and another for the first 229162306a36Sopenharmony_ci * cut_from_item. 1 is for update_sd 229262306a36Sopenharmony_ci */ 229362306a36Sopenharmony_ci error = journal_begin(&th, inode->i_sb, 229462306a36Sopenharmony_ci JOURNAL_PER_BALANCE_CNT * 2 + 1); 229562306a36Sopenharmony_ci if (error) 229662306a36Sopenharmony_ci goto out; 229762306a36Sopenharmony_ci reiserfs_update_inode_transaction(inode); 229862306a36Sopenharmony_ci if (update_timestamps) 229962306a36Sopenharmony_ci /* 230062306a36Sopenharmony_ci * we are doing real truncate: if the system crashes 230162306a36Sopenharmony_ci * before the last transaction of truncating gets committed 230262306a36Sopenharmony_ci * - on reboot the file either appears truncated properly 230362306a36Sopenharmony_ci * or not truncated at all 230462306a36Sopenharmony_ci */ 230562306a36Sopenharmony_ci add_save_link(&th, inode, 1); 230662306a36Sopenharmony_ci err2 = reiserfs_do_truncate(&th, inode, page, update_timestamps); 230762306a36Sopenharmony_ci error = journal_end(&th); 230862306a36Sopenharmony_ci if (error) 230962306a36Sopenharmony_ci goto out; 231062306a36Sopenharmony_ci 231162306a36Sopenharmony_ci /* check reiserfs_do_truncate after ending the transaction */ 231262306a36Sopenharmony_ci if (err2) { 231362306a36Sopenharmony_ci error = err2; 231462306a36Sopenharmony_ci goto out; 231562306a36Sopenharmony_ci } 231662306a36Sopenharmony_ci 231762306a36Sopenharmony_ci if (update_timestamps) { 231862306a36Sopenharmony_ci error = remove_save_link(inode, 1 /* truncate */); 231962306a36Sopenharmony_ci if (error) 232062306a36Sopenharmony_ci goto out; 232162306a36Sopenharmony_ci } 232262306a36Sopenharmony_ci 232362306a36Sopenharmony_ci if (page) { 232462306a36Sopenharmony_ci length = offset & (blocksize - 1); 232562306a36Sopenharmony_ci /* if we are not on a block boundary */ 232662306a36Sopenharmony_ci if (length) { 232762306a36Sopenharmony_ci length = blocksize - length; 232862306a36Sopenharmony_ci zero_user(page, offset, length); 232962306a36Sopenharmony_ci if (buffer_mapped(bh) && bh->b_blocknr != 0) { 233062306a36Sopenharmony_ci mark_buffer_dirty(bh); 233162306a36Sopenharmony_ci } 233262306a36Sopenharmony_ci } 233362306a36Sopenharmony_ci unlock_page(page); 233462306a36Sopenharmony_ci put_page(page); 233562306a36Sopenharmony_ci } 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci return 0; 234062306a36Sopenharmony_ciout: 234162306a36Sopenharmony_ci if (page) { 234262306a36Sopenharmony_ci unlock_page(page); 234362306a36Sopenharmony_ci put_page(page); 234462306a36Sopenharmony_ci } 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 234762306a36Sopenharmony_ci 234862306a36Sopenharmony_ci return error; 234962306a36Sopenharmony_ci} 235062306a36Sopenharmony_ci 235162306a36Sopenharmony_cistatic int map_block_for_writepage(struct inode *inode, 235262306a36Sopenharmony_ci struct buffer_head *bh_result, 235362306a36Sopenharmony_ci unsigned long block) 235462306a36Sopenharmony_ci{ 235562306a36Sopenharmony_ci struct reiserfs_transaction_handle th; 235662306a36Sopenharmony_ci int fs_gen; 235762306a36Sopenharmony_ci struct item_head tmp_ih; 235862306a36Sopenharmony_ci struct item_head *ih; 235962306a36Sopenharmony_ci struct buffer_head *bh; 236062306a36Sopenharmony_ci __le32 *item; 236162306a36Sopenharmony_ci struct cpu_key key; 236262306a36Sopenharmony_ci INITIALIZE_PATH(path); 236362306a36Sopenharmony_ci int pos_in_item; 236462306a36Sopenharmony_ci int jbegin_count = JOURNAL_PER_BALANCE_CNT; 236562306a36Sopenharmony_ci loff_t byte_offset = ((loff_t)block << inode->i_sb->s_blocksize_bits)+1; 236662306a36Sopenharmony_ci int retval; 236762306a36Sopenharmony_ci int use_get_block = 0; 236862306a36Sopenharmony_ci int bytes_copied = 0; 236962306a36Sopenharmony_ci int copy_size; 237062306a36Sopenharmony_ci int trans_running = 0; 237162306a36Sopenharmony_ci 237262306a36Sopenharmony_ci /* 237362306a36Sopenharmony_ci * catch places below that try to log something without 237462306a36Sopenharmony_ci * starting a trans 237562306a36Sopenharmony_ci */ 237662306a36Sopenharmony_ci th.t_trans_id = 0; 237762306a36Sopenharmony_ci 237862306a36Sopenharmony_ci if (!buffer_uptodate(bh_result)) { 237962306a36Sopenharmony_ci return -EIO; 238062306a36Sopenharmony_ci } 238162306a36Sopenharmony_ci 238262306a36Sopenharmony_ci kmap(bh_result->b_page); 238362306a36Sopenharmony_cistart_over: 238462306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 238562306a36Sopenharmony_ci make_cpu_key(&key, inode, byte_offset, TYPE_ANY, 3); 238662306a36Sopenharmony_ci 238762306a36Sopenharmony_ciresearch: 238862306a36Sopenharmony_ci retval = search_for_position_by_key(inode->i_sb, &key, &path); 238962306a36Sopenharmony_ci if (retval != POSITION_FOUND) { 239062306a36Sopenharmony_ci use_get_block = 1; 239162306a36Sopenharmony_ci goto out; 239262306a36Sopenharmony_ci } 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_ci bh = get_last_bh(&path); 239562306a36Sopenharmony_ci ih = tp_item_head(&path); 239662306a36Sopenharmony_ci item = tp_item_body(&path); 239762306a36Sopenharmony_ci pos_in_item = path.pos_in_item; 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci /* we've found an unformatted node */ 240062306a36Sopenharmony_ci if (indirect_item_found(retval, ih)) { 240162306a36Sopenharmony_ci if (bytes_copied > 0) { 240262306a36Sopenharmony_ci reiserfs_warning(inode->i_sb, "clm-6002", 240362306a36Sopenharmony_ci "bytes_copied %d", bytes_copied); 240462306a36Sopenharmony_ci } 240562306a36Sopenharmony_ci if (!get_block_num(item, pos_in_item)) { 240662306a36Sopenharmony_ci /* crap, we are writing to a hole */ 240762306a36Sopenharmony_ci use_get_block = 1; 240862306a36Sopenharmony_ci goto out; 240962306a36Sopenharmony_ci } 241062306a36Sopenharmony_ci set_block_dev_mapped(bh_result, 241162306a36Sopenharmony_ci get_block_num(item, pos_in_item), inode); 241262306a36Sopenharmony_ci } else if (is_direct_le_ih(ih)) { 241362306a36Sopenharmony_ci char *p; 241462306a36Sopenharmony_ci p = page_address(bh_result->b_page); 241562306a36Sopenharmony_ci p += (byte_offset - 1) & (PAGE_SIZE - 1); 241662306a36Sopenharmony_ci copy_size = ih_item_len(ih) - pos_in_item; 241762306a36Sopenharmony_ci 241862306a36Sopenharmony_ci fs_gen = get_generation(inode->i_sb); 241962306a36Sopenharmony_ci copy_item_head(&tmp_ih, ih); 242062306a36Sopenharmony_ci 242162306a36Sopenharmony_ci if (!trans_running) { 242262306a36Sopenharmony_ci /* vs-3050 is gone, no need to drop the path */ 242362306a36Sopenharmony_ci retval = journal_begin(&th, inode->i_sb, jbegin_count); 242462306a36Sopenharmony_ci if (retval) 242562306a36Sopenharmony_ci goto out; 242662306a36Sopenharmony_ci reiserfs_update_inode_transaction(inode); 242762306a36Sopenharmony_ci trans_running = 1; 242862306a36Sopenharmony_ci if (fs_changed(fs_gen, inode->i_sb) 242962306a36Sopenharmony_ci && item_moved(&tmp_ih, &path)) { 243062306a36Sopenharmony_ci reiserfs_restore_prepared_buffer(inode->i_sb, 243162306a36Sopenharmony_ci bh); 243262306a36Sopenharmony_ci goto research; 243362306a36Sopenharmony_ci } 243462306a36Sopenharmony_ci } 243562306a36Sopenharmony_ci 243662306a36Sopenharmony_ci reiserfs_prepare_for_journal(inode->i_sb, bh, 1); 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_ci if (fs_changed(fs_gen, inode->i_sb) 243962306a36Sopenharmony_ci && item_moved(&tmp_ih, &path)) { 244062306a36Sopenharmony_ci reiserfs_restore_prepared_buffer(inode->i_sb, bh); 244162306a36Sopenharmony_ci goto research; 244262306a36Sopenharmony_ci } 244362306a36Sopenharmony_ci 244462306a36Sopenharmony_ci memcpy(ih_item_body(bh, ih) + pos_in_item, p + bytes_copied, 244562306a36Sopenharmony_ci copy_size); 244662306a36Sopenharmony_ci 244762306a36Sopenharmony_ci journal_mark_dirty(&th, bh); 244862306a36Sopenharmony_ci bytes_copied += copy_size; 244962306a36Sopenharmony_ci set_block_dev_mapped(bh_result, 0, inode); 245062306a36Sopenharmony_ci 245162306a36Sopenharmony_ci /* are there still bytes left? */ 245262306a36Sopenharmony_ci if (bytes_copied < bh_result->b_size && 245362306a36Sopenharmony_ci (byte_offset + bytes_copied) < inode->i_size) { 245462306a36Sopenharmony_ci set_cpu_key_k_offset(&key, 245562306a36Sopenharmony_ci cpu_key_k_offset(&key) + 245662306a36Sopenharmony_ci copy_size); 245762306a36Sopenharmony_ci goto research; 245862306a36Sopenharmony_ci } 245962306a36Sopenharmony_ci } else { 246062306a36Sopenharmony_ci reiserfs_warning(inode->i_sb, "clm-6003", 246162306a36Sopenharmony_ci "bad item inode %lu", inode->i_ino); 246262306a36Sopenharmony_ci retval = -EIO; 246362306a36Sopenharmony_ci goto out; 246462306a36Sopenharmony_ci } 246562306a36Sopenharmony_ci retval = 0; 246662306a36Sopenharmony_ci 246762306a36Sopenharmony_ciout: 246862306a36Sopenharmony_ci pathrelse(&path); 246962306a36Sopenharmony_ci if (trans_running) { 247062306a36Sopenharmony_ci int err = journal_end(&th); 247162306a36Sopenharmony_ci if (err) 247262306a36Sopenharmony_ci retval = err; 247362306a36Sopenharmony_ci trans_running = 0; 247462306a36Sopenharmony_ci } 247562306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 247662306a36Sopenharmony_ci 247762306a36Sopenharmony_ci /* this is where we fill in holes in the file. */ 247862306a36Sopenharmony_ci if (use_get_block) { 247962306a36Sopenharmony_ci retval = reiserfs_get_block(inode, block, bh_result, 248062306a36Sopenharmony_ci GET_BLOCK_CREATE | GET_BLOCK_NO_IMUX 248162306a36Sopenharmony_ci | GET_BLOCK_NO_DANGLE); 248262306a36Sopenharmony_ci if (!retval) { 248362306a36Sopenharmony_ci if (!buffer_mapped(bh_result) 248462306a36Sopenharmony_ci || bh_result->b_blocknr == 0) { 248562306a36Sopenharmony_ci /* get_block failed to find a mapped unformatted node. */ 248662306a36Sopenharmony_ci use_get_block = 0; 248762306a36Sopenharmony_ci goto start_over; 248862306a36Sopenharmony_ci } 248962306a36Sopenharmony_ci } 249062306a36Sopenharmony_ci } 249162306a36Sopenharmony_ci kunmap(bh_result->b_page); 249262306a36Sopenharmony_ci 249362306a36Sopenharmony_ci if (!retval && buffer_mapped(bh_result) && bh_result->b_blocknr == 0) { 249462306a36Sopenharmony_ci /* 249562306a36Sopenharmony_ci * we've copied data from the page into the direct item, so the 249662306a36Sopenharmony_ci * buffer in the page is now clean, mark it to reflect that. 249762306a36Sopenharmony_ci */ 249862306a36Sopenharmony_ci lock_buffer(bh_result); 249962306a36Sopenharmony_ci clear_buffer_dirty(bh_result); 250062306a36Sopenharmony_ci unlock_buffer(bh_result); 250162306a36Sopenharmony_ci } 250262306a36Sopenharmony_ci return retval; 250362306a36Sopenharmony_ci} 250462306a36Sopenharmony_ci 250562306a36Sopenharmony_ci/* 250662306a36Sopenharmony_ci * mason@suse.com: updated in 2.5.54 to follow the same general io 250762306a36Sopenharmony_ci * start/recovery path as __block_write_full_folio, along with special 250862306a36Sopenharmony_ci * code to handle reiserfs tails. 250962306a36Sopenharmony_ci */ 251062306a36Sopenharmony_cistatic int reiserfs_write_full_page(struct page *page, 251162306a36Sopenharmony_ci struct writeback_control *wbc) 251262306a36Sopenharmony_ci{ 251362306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 251462306a36Sopenharmony_ci unsigned long end_index = inode->i_size >> PAGE_SHIFT; 251562306a36Sopenharmony_ci int error = 0; 251662306a36Sopenharmony_ci unsigned long block; 251762306a36Sopenharmony_ci sector_t last_block; 251862306a36Sopenharmony_ci struct buffer_head *head, *bh; 251962306a36Sopenharmony_ci int partial = 0; 252062306a36Sopenharmony_ci int nr = 0; 252162306a36Sopenharmony_ci int checked = PageChecked(page); 252262306a36Sopenharmony_ci struct reiserfs_transaction_handle th; 252362306a36Sopenharmony_ci struct super_block *s = inode->i_sb; 252462306a36Sopenharmony_ci int bh_per_page = PAGE_SIZE / s->s_blocksize; 252562306a36Sopenharmony_ci th.t_trans_id = 0; 252662306a36Sopenharmony_ci 252762306a36Sopenharmony_ci /* no logging allowed when nonblocking or from PF_MEMALLOC */ 252862306a36Sopenharmony_ci if (checked && (current->flags & PF_MEMALLOC)) { 252962306a36Sopenharmony_ci redirty_page_for_writepage(wbc, page); 253062306a36Sopenharmony_ci unlock_page(page); 253162306a36Sopenharmony_ci return 0; 253262306a36Sopenharmony_ci } 253362306a36Sopenharmony_ci 253462306a36Sopenharmony_ci /* 253562306a36Sopenharmony_ci * The page dirty bit is cleared before writepage is called, which 253662306a36Sopenharmony_ci * means we have to tell create_empty_buffers to make dirty buffers 253762306a36Sopenharmony_ci * The page really should be up to date at this point, so tossing 253862306a36Sopenharmony_ci * in the BH_Uptodate is just a sanity check. 253962306a36Sopenharmony_ci */ 254062306a36Sopenharmony_ci if (!page_has_buffers(page)) { 254162306a36Sopenharmony_ci create_empty_buffers(page, s->s_blocksize, 254262306a36Sopenharmony_ci (1 << BH_Dirty) | (1 << BH_Uptodate)); 254362306a36Sopenharmony_ci } 254462306a36Sopenharmony_ci head = page_buffers(page); 254562306a36Sopenharmony_ci 254662306a36Sopenharmony_ci /* 254762306a36Sopenharmony_ci * last page in the file, zero out any contents past the 254862306a36Sopenharmony_ci * last byte in the file 254962306a36Sopenharmony_ci */ 255062306a36Sopenharmony_ci if (page->index >= end_index) { 255162306a36Sopenharmony_ci unsigned last_offset; 255262306a36Sopenharmony_ci 255362306a36Sopenharmony_ci last_offset = inode->i_size & (PAGE_SIZE - 1); 255462306a36Sopenharmony_ci /* no file contents in this page */ 255562306a36Sopenharmony_ci if (page->index >= end_index + 1 || !last_offset) { 255662306a36Sopenharmony_ci unlock_page(page); 255762306a36Sopenharmony_ci return 0; 255862306a36Sopenharmony_ci } 255962306a36Sopenharmony_ci zero_user_segment(page, last_offset, PAGE_SIZE); 256062306a36Sopenharmony_ci } 256162306a36Sopenharmony_ci bh = head; 256262306a36Sopenharmony_ci block = page->index << (PAGE_SHIFT - s->s_blocksize_bits); 256362306a36Sopenharmony_ci last_block = (i_size_read(inode) - 1) >> inode->i_blkbits; 256462306a36Sopenharmony_ci /* first map all the buffers, logging any direct items we find */ 256562306a36Sopenharmony_ci do { 256662306a36Sopenharmony_ci if (block > last_block) { 256762306a36Sopenharmony_ci /* 256862306a36Sopenharmony_ci * This can happen when the block size is less than 256962306a36Sopenharmony_ci * the page size. The corresponding bytes in the page 257062306a36Sopenharmony_ci * were zero filled above 257162306a36Sopenharmony_ci */ 257262306a36Sopenharmony_ci clear_buffer_dirty(bh); 257362306a36Sopenharmony_ci set_buffer_uptodate(bh); 257462306a36Sopenharmony_ci } else if ((checked || buffer_dirty(bh)) && 257562306a36Sopenharmony_ci (!buffer_mapped(bh) || bh->b_blocknr == 0)) { 257662306a36Sopenharmony_ci /* 257762306a36Sopenharmony_ci * not mapped yet, or it points to a direct item, search 257862306a36Sopenharmony_ci * the btree for the mapping info, and log any direct 257962306a36Sopenharmony_ci * items found 258062306a36Sopenharmony_ci */ 258162306a36Sopenharmony_ci if ((error = map_block_for_writepage(inode, bh, block))) { 258262306a36Sopenharmony_ci goto fail; 258362306a36Sopenharmony_ci } 258462306a36Sopenharmony_ci } 258562306a36Sopenharmony_ci bh = bh->b_this_page; 258662306a36Sopenharmony_ci block++; 258762306a36Sopenharmony_ci } while (bh != head); 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_ci /* 259062306a36Sopenharmony_ci * we start the transaction after map_block_for_writepage, 259162306a36Sopenharmony_ci * because it can create holes in the file (an unbounded operation). 259262306a36Sopenharmony_ci * starting it here, we can make a reliable estimate for how many 259362306a36Sopenharmony_ci * blocks we're going to log 259462306a36Sopenharmony_ci */ 259562306a36Sopenharmony_ci if (checked) { 259662306a36Sopenharmony_ci ClearPageChecked(page); 259762306a36Sopenharmony_ci reiserfs_write_lock(s); 259862306a36Sopenharmony_ci error = journal_begin(&th, s, bh_per_page + 1); 259962306a36Sopenharmony_ci if (error) { 260062306a36Sopenharmony_ci reiserfs_write_unlock(s); 260162306a36Sopenharmony_ci goto fail; 260262306a36Sopenharmony_ci } 260362306a36Sopenharmony_ci reiserfs_update_inode_transaction(inode); 260462306a36Sopenharmony_ci } 260562306a36Sopenharmony_ci /* now go through and lock any dirty buffers on the page */ 260662306a36Sopenharmony_ci do { 260762306a36Sopenharmony_ci get_bh(bh); 260862306a36Sopenharmony_ci if (!buffer_mapped(bh)) 260962306a36Sopenharmony_ci continue; 261062306a36Sopenharmony_ci if (buffer_mapped(bh) && bh->b_blocknr == 0) 261162306a36Sopenharmony_ci continue; 261262306a36Sopenharmony_ci 261362306a36Sopenharmony_ci if (checked) { 261462306a36Sopenharmony_ci reiserfs_prepare_for_journal(s, bh, 1); 261562306a36Sopenharmony_ci journal_mark_dirty(&th, bh); 261662306a36Sopenharmony_ci continue; 261762306a36Sopenharmony_ci } 261862306a36Sopenharmony_ci /* 261962306a36Sopenharmony_ci * from this point on, we know the buffer is mapped to a 262062306a36Sopenharmony_ci * real block and not a direct item 262162306a36Sopenharmony_ci */ 262262306a36Sopenharmony_ci if (wbc->sync_mode != WB_SYNC_NONE) { 262362306a36Sopenharmony_ci lock_buffer(bh); 262462306a36Sopenharmony_ci } else { 262562306a36Sopenharmony_ci if (!trylock_buffer(bh)) { 262662306a36Sopenharmony_ci redirty_page_for_writepage(wbc, page); 262762306a36Sopenharmony_ci continue; 262862306a36Sopenharmony_ci } 262962306a36Sopenharmony_ci } 263062306a36Sopenharmony_ci if (test_clear_buffer_dirty(bh)) { 263162306a36Sopenharmony_ci mark_buffer_async_write(bh); 263262306a36Sopenharmony_ci } else { 263362306a36Sopenharmony_ci unlock_buffer(bh); 263462306a36Sopenharmony_ci } 263562306a36Sopenharmony_ci } while ((bh = bh->b_this_page) != head); 263662306a36Sopenharmony_ci 263762306a36Sopenharmony_ci if (checked) { 263862306a36Sopenharmony_ci error = journal_end(&th); 263962306a36Sopenharmony_ci reiserfs_write_unlock(s); 264062306a36Sopenharmony_ci if (error) 264162306a36Sopenharmony_ci goto fail; 264262306a36Sopenharmony_ci } 264362306a36Sopenharmony_ci BUG_ON(PageWriteback(page)); 264462306a36Sopenharmony_ci set_page_writeback(page); 264562306a36Sopenharmony_ci unlock_page(page); 264662306a36Sopenharmony_ci 264762306a36Sopenharmony_ci /* 264862306a36Sopenharmony_ci * since any buffer might be the only dirty buffer on the page, 264962306a36Sopenharmony_ci * the first submit_bh can bring the page out of writeback. 265062306a36Sopenharmony_ci * be careful with the buffers. 265162306a36Sopenharmony_ci */ 265262306a36Sopenharmony_ci do { 265362306a36Sopenharmony_ci struct buffer_head *next = bh->b_this_page; 265462306a36Sopenharmony_ci if (buffer_async_write(bh)) { 265562306a36Sopenharmony_ci submit_bh(REQ_OP_WRITE, bh); 265662306a36Sopenharmony_ci nr++; 265762306a36Sopenharmony_ci } 265862306a36Sopenharmony_ci put_bh(bh); 265962306a36Sopenharmony_ci bh = next; 266062306a36Sopenharmony_ci } while (bh != head); 266162306a36Sopenharmony_ci 266262306a36Sopenharmony_ci error = 0; 266362306a36Sopenharmony_cidone: 266462306a36Sopenharmony_ci if (nr == 0) { 266562306a36Sopenharmony_ci /* 266662306a36Sopenharmony_ci * if this page only had a direct item, it is very possible for 266762306a36Sopenharmony_ci * no io to be required without there being an error. Or, 266862306a36Sopenharmony_ci * someone else could have locked them and sent them down the 266962306a36Sopenharmony_ci * pipe without locking the page 267062306a36Sopenharmony_ci */ 267162306a36Sopenharmony_ci bh = head; 267262306a36Sopenharmony_ci do { 267362306a36Sopenharmony_ci if (!buffer_uptodate(bh)) { 267462306a36Sopenharmony_ci partial = 1; 267562306a36Sopenharmony_ci break; 267662306a36Sopenharmony_ci } 267762306a36Sopenharmony_ci bh = bh->b_this_page; 267862306a36Sopenharmony_ci } while (bh != head); 267962306a36Sopenharmony_ci if (!partial) 268062306a36Sopenharmony_ci SetPageUptodate(page); 268162306a36Sopenharmony_ci end_page_writeback(page); 268262306a36Sopenharmony_ci } 268362306a36Sopenharmony_ci return error; 268462306a36Sopenharmony_ci 268562306a36Sopenharmony_cifail: 268662306a36Sopenharmony_ci /* 268762306a36Sopenharmony_ci * catches various errors, we need to make sure any valid dirty blocks 268862306a36Sopenharmony_ci * get to the media. The page is currently locked and not marked for 268962306a36Sopenharmony_ci * writeback 269062306a36Sopenharmony_ci */ 269162306a36Sopenharmony_ci ClearPageUptodate(page); 269262306a36Sopenharmony_ci bh = head; 269362306a36Sopenharmony_ci do { 269462306a36Sopenharmony_ci get_bh(bh); 269562306a36Sopenharmony_ci if (buffer_mapped(bh) && buffer_dirty(bh) && bh->b_blocknr) { 269662306a36Sopenharmony_ci lock_buffer(bh); 269762306a36Sopenharmony_ci mark_buffer_async_write(bh); 269862306a36Sopenharmony_ci } else { 269962306a36Sopenharmony_ci /* 270062306a36Sopenharmony_ci * clear any dirty bits that might have come from 270162306a36Sopenharmony_ci * getting attached to a dirty page 270262306a36Sopenharmony_ci */ 270362306a36Sopenharmony_ci clear_buffer_dirty(bh); 270462306a36Sopenharmony_ci } 270562306a36Sopenharmony_ci bh = bh->b_this_page; 270662306a36Sopenharmony_ci } while (bh != head); 270762306a36Sopenharmony_ci SetPageError(page); 270862306a36Sopenharmony_ci BUG_ON(PageWriteback(page)); 270962306a36Sopenharmony_ci set_page_writeback(page); 271062306a36Sopenharmony_ci unlock_page(page); 271162306a36Sopenharmony_ci do { 271262306a36Sopenharmony_ci struct buffer_head *next = bh->b_this_page; 271362306a36Sopenharmony_ci if (buffer_async_write(bh)) { 271462306a36Sopenharmony_ci clear_buffer_dirty(bh); 271562306a36Sopenharmony_ci submit_bh(REQ_OP_WRITE, bh); 271662306a36Sopenharmony_ci nr++; 271762306a36Sopenharmony_ci } 271862306a36Sopenharmony_ci put_bh(bh); 271962306a36Sopenharmony_ci bh = next; 272062306a36Sopenharmony_ci } while (bh != head); 272162306a36Sopenharmony_ci goto done; 272262306a36Sopenharmony_ci} 272362306a36Sopenharmony_ci 272462306a36Sopenharmony_cistatic int reiserfs_read_folio(struct file *f, struct folio *folio) 272562306a36Sopenharmony_ci{ 272662306a36Sopenharmony_ci return block_read_full_folio(folio, reiserfs_get_block); 272762306a36Sopenharmony_ci} 272862306a36Sopenharmony_ci 272962306a36Sopenharmony_cistatic int reiserfs_writepage(struct page *page, struct writeback_control *wbc) 273062306a36Sopenharmony_ci{ 273162306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 273262306a36Sopenharmony_ci reiserfs_wait_on_write_block(inode->i_sb); 273362306a36Sopenharmony_ci return reiserfs_write_full_page(page, wbc); 273462306a36Sopenharmony_ci} 273562306a36Sopenharmony_ci 273662306a36Sopenharmony_cistatic void reiserfs_truncate_failed_write(struct inode *inode) 273762306a36Sopenharmony_ci{ 273862306a36Sopenharmony_ci truncate_inode_pages(inode->i_mapping, inode->i_size); 273962306a36Sopenharmony_ci reiserfs_truncate_file(inode, 0); 274062306a36Sopenharmony_ci} 274162306a36Sopenharmony_ci 274262306a36Sopenharmony_cistatic int reiserfs_write_begin(struct file *file, 274362306a36Sopenharmony_ci struct address_space *mapping, 274462306a36Sopenharmony_ci loff_t pos, unsigned len, 274562306a36Sopenharmony_ci struct page **pagep, void **fsdata) 274662306a36Sopenharmony_ci{ 274762306a36Sopenharmony_ci struct inode *inode; 274862306a36Sopenharmony_ci struct page *page; 274962306a36Sopenharmony_ci pgoff_t index; 275062306a36Sopenharmony_ci int ret; 275162306a36Sopenharmony_ci int old_ref = 0; 275262306a36Sopenharmony_ci 275362306a36Sopenharmony_ci inode = mapping->host; 275462306a36Sopenharmony_ci index = pos >> PAGE_SHIFT; 275562306a36Sopenharmony_ci page = grab_cache_page_write_begin(mapping, index); 275662306a36Sopenharmony_ci if (!page) 275762306a36Sopenharmony_ci return -ENOMEM; 275862306a36Sopenharmony_ci *pagep = page; 275962306a36Sopenharmony_ci 276062306a36Sopenharmony_ci reiserfs_wait_on_write_block(inode->i_sb); 276162306a36Sopenharmony_ci fix_tail_page_for_writing(page); 276262306a36Sopenharmony_ci if (reiserfs_transaction_running(inode->i_sb)) { 276362306a36Sopenharmony_ci struct reiserfs_transaction_handle *th; 276462306a36Sopenharmony_ci th = (struct reiserfs_transaction_handle *)current-> 276562306a36Sopenharmony_ci journal_info; 276662306a36Sopenharmony_ci BUG_ON(!th->t_refcount); 276762306a36Sopenharmony_ci BUG_ON(!th->t_trans_id); 276862306a36Sopenharmony_ci old_ref = th->t_refcount; 276962306a36Sopenharmony_ci th->t_refcount++; 277062306a36Sopenharmony_ci } 277162306a36Sopenharmony_ci ret = __block_write_begin(page, pos, len, reiserfs_get_block); 277262306a36Sopenharmony_ci if (ret && reiserfs_transaction_running(inode->i_sb)) { 277362306a36Sopenharmony_ci struct reiserfs_transaction_handle *th = current->journal_info; 277462306a36Sopenharmony_ci /* 277562306a36Sopenharmony_ci * this gets a little ugly. If reiserfs_get_block returned an 277662306a36Sopenharmony_ci * error and left a transacstion running, we've got to close 277762306a36Sopenharmony_ci * it, and we've got to free handle if it was a persistent 277862306a36Sopenharmony_ci * transaction. 277962306a36Sopenharmony_ci * 278062306a36Sopenharmony_ci * But, if we had nested into an existing transaction, we need 278162306a36Sopenharmony_ci * to just drop the ref count on the handle. 278262306a36Sopenharmony_ci * 278362306a36Sopenharmony_ci * If old_ref == 0, the transaction is from reiserfs_get_block, 278462306a36Sopenharmony_ci * and it was a persistent trans. Otherwise, it was nested 278562306a36Sopenharmony_ci * above. 278662306a36Sopenharmony_ci */ 278762306a36Sopenharmony_ci if (th->t_refcount > old_ref) { 278862306a36Sopenharmony_ci if (old_ref) 278962306a36Sopenharmony_ci th->t_refcount--; 279062306a36Sopenharmony_ci else { 279162306a36Sopenharmony_ci int err; 279262306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 279362306a36Sopenharmony_ci err = reiserfs_end_persistent_transaction(th); 279462306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 279562306a36Sopenharmony_ci if (err) 279662306a36Sopenharmony_ci ret = err; 279762306a36Sopenharmony_ci } 279862306a36Sopenharmony_ci } 279962306a36Sopenharmony_ci } 280062306a36Sopenharmony_ci if (ret) { 280162306a36Sopenharmony_ci unlock_page(page); 280262306a36Sopenharmony_ci put_page(page); 280362306a36Sopenharmony_ci /* Truncate allocated blocks */ 280462306a36Sopenharmony_ci reiserfs_truncate_failed_write(inode); 280562306a36Sopenharmony_ci } 280662306a36Sopenharmony_ci return ret; 280762306a36Sopenharmony_ci} 280862306a36Sopenharmony_ci 280962306a36Sopenharmony_ciint __reiserfs_write_begin(struct page *page, unsigned from, unsigned len) 281062306a36Sopenharmony_ci{ 281162306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 281262306a36Sopenharmony_ci int ret; 281362306a36Sopenharmony_ci int old_ref = 0; 281462306a36Sopenharmony_ci int depth; 281562306a36Sopenharmony_ci 281662306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(inode->i_sb); 281762306a36Sopenharmony_ci reiserfs_wait_on_write_block(inode->i_sb); 281862306a36Sopenharmony_ci reiserfs_write_lock_nested(inode->i_sb, depth); 281962306a36Sopenharmony_ci 282062306a36Sopenharmony_ci fix_tail_page_for_writing(page); 282162306a36Sopenharmony_ci if (reiserfs_transaction_running(inode->i_sb)) { 282262306a36Sopenharmony_ci struct reiserfs_transaction_handle *th; 282362306a36Sopenharmony_ci th = (struct reiserfs_transaction_handle *)current-> 282462306a36Sopenharmony_ci journal_info; 282562306a36Sopenharmony_ci BUG_ON(!th->t_refcount); 282662306a36Sopenharmony_ci BUG_ON(!th->t_trans_id); 282762306a36Sopenharmony_ci old_ref = th->t_refcount; 282862306a36Sopenharmony_ci th->t_refcount++; 282962306a36Sopenharmony_ci } 283062306a36Sopenharmony_ci 283162306a36Sopenharmony_ci ret = __block_write_begin(page, from, len, reiserfs_get_block); 283262306a36Sopenharmony_ci if (ret && reiserfs_transaction_running(inode->i_sb)) { 283362306a36Sopenharmony_ci struct reiserfs_transaction_handle *th = current->journal_info; 283462306a36Sopenharmony_ci /* 283562306a36Sopenharmony_ci * this gets a little ugly. If reiserfs_get_block returned an 283662306a36Sopenharmony_ci * error and left a transacstion running, we've got to close 283762306a36Sopenharmony_ci * it, and we've got to free handle if it was a persistent 283862306a36Sopenharmony_ci * transaction. 283962306a36Sopenharmony_ci * 284062306a36Sopenharmony_ci * But, if we had nested into an existing transaction, we need 284162306a36Sopenharmony_ci * to just drop the ref count on the handle. 284262306a36Sopenharmony_ci * 284362306a36Sopenharmony_ci * If old_ref == 0, the transaction is from reiserfs_get_block, 284462306a36Sopenharmony_ci * and it was a persistent trans. Otherwise, it was nested 284562306a36Sopenharmony_ci * above. 284662306a36Sopenharmony_ci */ 284762306a36Sopenharmony_ci if (th->t_refcount > old_ref) { 284862306a36Sopenharmony_ci if (old_ref) 284962306a36Sopenharmony_ci th->t_refcount--; 285062306a36Sopenharmony_ci else { 285162306a36Sopenharmony_ci int err; 285262306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 285362306a36Sopenharmony_ci err = reiserfs_end_persistent_transaction(th); 285462306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 285562306a36Sopenharmony_ci if (err) 285662306a36Sopenharmony_ci ret = err; 285762306a36Sopenharmony_ci } 285862306a36Sopenharmony_ci } 285962306a36Sopenharmony_ci } 286062306a36Sopenharmony_ci return ret; 286162306a36Sopenharmony_ci 286262306a36Sopenharmony_ci} 286362306a36Sopenharmony_ci 286462306a36Sopenharmony_cistatic sector_t reiserfs_aop_bmap(struct address_space *as, sector_t block) 286562306a36Sopenharmony_ci{ 286662306a36Sopenharmony_ci return generic_block_bmap(as, block, reiserfs_bmap); 286762306a36Sopenharmony_ci} 286862306a36Sopenharmony_ci 286962306a36Sopenharmony_cistatic int reiserfs_write_end(struct file *file, struct address_space *mapping, 287062306a36Sopenharmony_ci loff_t pos, unsigned len, unsigned copied, 287162306a36Sopenharmony_ci struct page *page, void *fsdata) 287262306a36Sopenharmony_ci{ 287362306a36Sopenharmony_ci struct folio *folio = page_folio(page); 287462306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 287562306a36Sopenharmony_ci int ret = 0; 287662306a36Sopenharmony_ci int update_sd = 0; 287762306a36Sopenharmony_ci struct reiserfs_transaction_handle *th; 287862306a36Sopenharmony_ci unsigned start; 287962306a36Sopenharmony_ci bool locked = false; 288062306a36Sopenharmony_ci 288162306a36Sopenharmony_ci reiserfs_wait_on_write_block(inode->i_sb); 288262306a36Sopenharmony_ci if (reiserfs_transaction_running(inode->i_sb)) 288362306a36Sopenharmony_ci th = current->journal_info; 288462306a36Sopenharmony_ci else 288562306a36Sopenharmony_ci th = NULL; 288662306a36Sopenharmony_ci 288762306a36Sopenharmony_ci start = pos & (PAGE_SIZE - 1); 288862306a36Sopenharmony_ci if (unlikely(copied < len)) { 288962306a36Sopenharmony_ci if (!folio_test_uptodate(folio)) 289062306a36Sopenharmony_ci copied = 0; 289162306a36Sopenharmony_ci 289262306a36Sopenharmony_ci folio_zero_new_buffers(folio, start + copied, start + len); 289362306a36Sopenharmony_ci } 289462306a36Sopenharmony_ci flush_dcache_folio(folio); 289562306a36Sopenharmony_ci 289662306a36Sopenharmony_ci reiserfs_commit_page(inode, page, start, start + copied); 289762306a36Sopenharmony_ci 289862306a36Sopenharmony_ci /* 289962306a36Sopenharmony_ci * generic_commit_write does this for us, but does not update the 290062306a36Sopenharmony_ci * transaction tracking stuff when the size changes. So, we have 290162306a36Sopenharmony_ci * to do the i_size updates here. 290262306a36Sopenharmony_ci */ 290362306a36Sopenharmony_ci if (pos + copied > inode->i_size) { 290462306a36Sopenharmony_ci struct reiserfs_transaction_handle myth; 290562306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 290662306a36Sopenharmony_ci locked = true; 290762306a36Sopenharmony_ci /* 290862306a36Sopenharmony_ci * If the file have grown beyond the border where it 290962306a36Sopenharmony_ci * can have a tail, unmark it as needing a tail 291062306a36Sopenharmony_ci * packing 291162306a36Sopenharmony_ci */ 291262306a36Sopenharmony_ci if ((have_large_tails(inode->i_sb) 291362306a36Sopenharmony_ci && inode->i_size > i_block_size(inode) * 4) 291462306a36Sopenharmony_ci || (have_small_tails(inode->i_sb) 291562306a36Sopenharmony_ci && inode->i_size > i_block_size(inode))) 291662306a36Sopenharmony_ci REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; 291762306a36Sopenharmony_ci 291862306a36Sopenharmony_ci ret = journal_begin(&myth, inode->i_sb, 1); 291962306a36Sopenharmony_ci if (ret) 292062306a36Sopenharmony_ci goto journal_error; 292162306a36Sopenharmony_ci 292262306a36Sopenharmony_ci reiserfs_update_inode_transaction(inode); 292362306a36Sopenharmony_ci inode->i_size = pos + copied; 292462306a36Sopenharmony_ci /* 292562306a36Sopenharmony_ci * this will just nest into our transaction. It's important 292662306a36Sopenharmony_ci * to use mark_inode_dirty so the inode gets pushed around on 292762306a36Sopenharmony_ci * the dirty lists, and so that O_SYNC works as expected 292862306a36Sopenharmony_ci */ 292962306a36Sopenharmony_ci mark_inode_dirty(inode); 293062306a36Sopenharmony_ci reiserfs_update_sd(&myth, inode); 293162306a36Sopenharmony_ci update_sd = 1; 293262306a36Sopenharmony_ci ret = journal_end(&myth); 293362306a36Sopenharmony_ci if (ret) 293462306a36Sopenharmony_ci goto journal_error; 293562306a36Sopenharmony_ci } 293662306a36Sopenharmony_ci if (th) { 293762306a36Sopenharmony_ci if (!locked) { 293862306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 293962306a36Sopenharmony_ci locked = true; 294062306a36Sopenharmony_ci } 294162306a36Sopenharmony_ci if (!update_sd) 294262306a36Sopenharmony_ci mark_inode_dirty(inode); 294362306a36Sopenharmony_ci ret = reiserfs_end_persistent_transaction(th); 294462306a36Sopenharmony_ci if (ret) 294562306a36Sopenharmony_ci goto out; 294662306a36Sopenharmony_ci } 294762306a36Sopenharmony_ci 294862306a36Sopenharmony_ciout: 294962306a36Sopenharmony_ci if (locked) 295062306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 295162306a36Sopenharmony_ci unlock_page(page); 295262306a36Sopenharmony_ci put_page(page); 295362306a36Sopenharmony_ci 295462306a36Sopenharmony_ci if (pos + len > inode->i_size) 295562306a36Sopenharmony_ci reiserfs_truncate_failed_write(inode); 295662306a36Sopenharmony_ci 295762306a36Sopenharmony_ci return ret == 0 ? copied : ret; 295862306a36Sopenharmony_ci 295962306a36Sopenharmony_cijournal_error: 296062306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 296162306a36Sopenharmony_ci locked = false; 296262306a36Sopenharmony_ci if (th) { 296362306a36Sopenharmony_ci if (!update_sd) 296462306a36Sopenharmony_ci reiserfs_update_sd(th, inode); 296562306a36Sopenharmony_ci ret = reiserfs_end_persistent_transaction(th); 296662306a36Sopenharmony_ci } 296762306a36Sopenharmony_ci goto out; 296862306a36Sopenharmony_ci} 296962306a36Sopenharmony_ci 297062306a36Sopenharmony_ciint reiserfs_commit_write(struct file *f, struct page *page, 297162306a36Sopenharmony_ci unsigned from, unsigned to) 297262306a36Sopenharmony_ci{ 297362306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 297462306a36Sopenharmony_ci loff_t pos = ((loff_t) page->index << PAGE_SHIFT) + to; 297562306a36Sopenharmony_ci int ret = 0; 297662306a36Sopenharmony_ci int update_sd = 0; 297762306a36Sopenharmony_ci struct reiserfs_transaction_handle *th = NULL; 297862306a36Sopenharmony_ci int depth; 297962306a36Sopenharmony_ci 298062306a36Sopenharmony_ci depth = reiserfs_write_unlock_nested(inode->i_sb); 298162306a36Sopenharmony_ci reiserfs_wait_on_write_block(inode->i_sb); 298262306a36Sopenharmony_ci reiserfs_write_lock_nested(inode->i_sb, depth); 298362306a36Sopenharmony_ci 298462306a36Sopenharmony_ci if (reiserfs_transaction_running(inode->i_sb)) { 298562306a36Sopenharmony_ci th = current->journal_info; 298662306a36Sopenharmony_ci } 298762306a36Sopenharmony_ci reiserfs_commit_page(inode, page, from, to); 298862306a36Sopenharmony_ci 298962306a36Sopenharmony_ci /* 299062306a36Sopenharmony_ci * generic_commit_write does this for us, but does not update the 299162306a36Sopenharmony_ci * transaction tracking stuff when the size changes. So, we have 299262306a36Sopenharmony_ci * to do the i_size updates here. 299362306a36Sopenharmony_ci */ 299462306a36Sopenharmony_ci if (pos > inode->i_size) { 299562306a36Sopenharmony_ci struct reiserfs_transaction_handle myth; 299662306a36Sopenharmony_ci /* 299762306a36Sopenharmony_ci * If the file have grown beyond the border where it 299862306a36Sopenharmony_ci * can have a tail, unmark it as needing a tail 299962306a36Sopenharmony_ci * packing 300062306a36Sopenharmony_ci */ 300162306a36Sopenharmony_ci if ((have_large_tails(inode->i_sb) 300262306a36Sopenharmony_ci && inode->i_size > i_block_size(inode) * 4) 300362306a36Sopenharmony_ci || (have_small_tails(inode->i_sb) 300462306a36Sopenharmony_ci && inode->i_size > i_block_size(inode))) 300562306a36Sopenharmony_ci REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; 300662306a36Sopenharmony_ci 300762306a36Sopenharmony_ci ret = journal_begin(&myth, inode->i_sb, 1); 300862306a36Sopenharmony_ci if (ret) 300962306a36Sopenharmony_ci goto journal_error; 301062306a36Sopenharmony_ci 301162306a36Sopenharmony_ci reiserfs_update_inode_transaction(inode); 301262306a36Sopenharmony_ci inode->i_size = pos; 301362306a36Sopenharmony_ci /* 301462306a36Sopenharmony_ci * this will just nest into our transaction. It's important 301562306a36Sopenharmony_ci * to use mark_inode_dirty so the inode gets pushed around 301662306a36Sopenharmony_ci * on the dirty lists, and so that O_SYNC works as expected 301762306a36Sopenharmony_ci */ 301862306a36Sopenharmony_ci mark_inode_dirty(inode); 301962306a36Sopenharmony_ci reiserfs_update_sd(&myth, inode); 302062306a36Sopenharmony_ci update_sd = 1; 302162306a36Sopenharmony_ci ret = journal_end(&myth); 302262306a36Sopenharmony_ci if (ret) 302362306a36Sopenharmony_ci goto journal_error; 302462306a36Sopenharmony_ci } 302562306a36Sopenharmony_ci if (th) { 302662306a36Sopenharmony_ci if (!update_sd) 302762306a36Sopenharmony_ci mark_inode_dirty(inode); 302862306a36Sopenharmony_ci ret = reiserfs_end_persistent_transaction(th); 302962306a36Sopenharmony_ci if (ret) 303062306a36Sopenharmony_ci goto out; 303162306a36Sopenharmony_ci } 303262306a36Sopenharmony_ci 303362306a36Sopenharmony_ciout: 303462306a36Sopenharmony_ci return ret; 303562306a36Sopenharmony_ci 303662306a36Sopenharmony_cijournal_error: 303762306a36Sopenharmony_ci if (th) { 303862306a36Sopenharmony_ci if (!update_sd) 303962306a36Sopenharmony_ci reiserfs_update_sd(th, inode); 304062306a36Sopenharmony_ci ret = reiserfs_end_persistent_transaction(th); 304162306a36Sopenharmony_ci } 304262306a36Sopenharmony_ci 304362306a36Sopenharmony_ci return ret; 304462306a36Sopenharmony_ci} 304562306a36Sopenharmony_ci 304662306a36Sopenharmony_civoid sd_attrs_to_i_attrs(__u16 sd_attrs, struct inode *inode) 304762306a36Sopenharmony_ci{ 304862306a36Sopenharmony_ci if (reiserfs_attrs(inode->i_sb)) { 304962306a36Sopenharmony_ci if (sd_attrs & REISERFS_SYNC_FL) 305062306a36Sopenharmony_ci inode->i_flags |= S_SYNC; 305162306a36Sopenharmony_ci else 305262306a36Sopenharmony_ci inode->i_flags &= ~S_SYNC; 305362306a36Sopenharmony_ci if (sd_attrs & REISERFS_IMMUTABLE_FL) 305462306a36Sopenharmony_ci inode->i_flags |= S_IMMUTABLE; 305562306a36Sopenharmony_ci else 305662306a36Sopenharmony_ci inode->i_flags &= ~S_IMMUTABLE; 305762306a36Sopenharmony_ci if (sd_attrs & REISERFS_APPEND_FL) 305862306a36Sopenharmony_ci inode->i_flags |= S_APPEND; 305962306a36Sopenharmony_ci else 306062306a36Sopenharmony_ci inode->i_flags &= ~S_APPEND; 306162306a36Sopenharmony_ci if (sd_attrs & REISERFS_NOATIME_FL) 306262306a36Sopenharmony_ci inode->i_flags |= S_NOATIME; 306362306a36Sopenharmony_ci else 306462306a36Sopenharmony_ci inode->i_flags &= ~S_NOATIME; 306562306a36Sopenharmony_ci if (sd_attrs & REISERFS_NOTAIL_FL) 306662306a36Sopenharmony_ci REISERFS_I(inode)->i_flags |= i_nopack_mask; 306762306a36Sopenharmony_ci else 306862306a36Sopenharmony_ci REISERFS_I(inode)->i_flags &= ~i_nopack_mask; 306962306a36Sopenharmony_ci } 307062306a36Sopenharmony_ci} 307162306a36Sopenharmony_ci 307262306a36Sopenharmony_ci/* 307362306a36Sopenharmony_ci * decide if this buffer needs to stay around for data logging or ordered 307462306a36Sopenharmony_ci * write purposes 307562306a36Sopenharmony_ci */ 307662306a36Sopenharmony_cistatic int invalidate_folio_can_drop(struct inode *inode, struct buffer_head *bh) 307762306a36Sopenharmony_ci{ 307862306a36Sopenharmony_ci int ret = 1; 307962306a36Sopenharmony_ci struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb); 308062306a36Sopenharmony_ci 308162306a36Sopenharmony_ci lock_buffer(bh); 308262306a36Sopenharmony_ci spin_lock(&j->j_dirty_buffers_lock); 308362306a36Sopenharmony_ci if (!buffer_mapped(bh)) { 308462306a36Sopenharmony_ci goto free_jh; 308562306a36Sopenharmony_ci } 308662306a36Sopenharmony_ci /* 308762306a36Sopenharmony_ci * the page is locked, and the only places that log a data buffer 308862306a36Sopenharmony_ci * also lock the page. 308962306a36Sopenharmony_ci */ 309062306a36Sopenharmony_ci if (reiserfs_file_data_log(inode)) { 309162306a36Sopenharmony_ci /* 309262306a36Sopenharmony_ci * very conservative, leave the buffer pinned if 309362306a36Sopenharmony_ci * anyone might need it. 309462306a36Sopenharmony_ci */ 309562306a36Sopenharmony_ci if (buffer_journaled(bh) || buffer_journal_dirty(bh)) { 309662306a36Sopenharmony_ci ret = 0; 309762306a36Sopenharmony_ci } 309862306a36Sopenharmony_ci } else if (buffer_dirty(bh)) { 309962306a36Sopenharmony_ci struct reiserfs_journal_list *jl; 310062306a36Sopenharmony_ci struct reiserfs_jh *jh = bh->b_private; 310162306a36Sopenharmony_ci 310262306a36Sopenharmony_ci /* 310362306a36Sopenharmony_ci * why is this safe? 310462306a36Sopenharmony_ci * reiserfs_setattr updates i_size in the on disk 310562306a36Sopenharmony_ci * stat data before allowing vmtruncate to be called. 310662306a36Sopenharmony_ci * 310762306a36Sopenharmony_ci * If buffer was put onto the ordered list for this 310862306a36Sopenharmony_ci * transaction, we know for sure either this transaction 310962306a36Sopenharmony_ci * or an older one already has updated i_size on disk, 311062306a36Sopenharmony_ci * and this ordered data won't be referenced in the file 311162306a36Sopenharmony_ci * if we crash. 311262306a36Sopenharmony_ci * 311362306a36Sopenharmony_ci * if the buffer was put onto the ordered list for an older 311462306a36Sopenharmony_ci * transaction, we need to leave it around 311562306a36Sopenharmony_ci */ 311662306a36Sopenharmony_ci if (jh && (jl = jh->jl) 311762306a36Sopenharmony_ci && jl != SB_JOURNAL(inode->i_sb)->j_current_jl) 311862306a36Sopenharmony_ci ret = 0; 311962306a36Sopenharmony_ci } 312062306a36Sopenharmony_cifree_jh: 312162306a36Sopenharmony_ci if (ret && bh->b_private) { 312262306a36Sopenharmony_ci reiserfs_free_jh(bh); 312362306a36Sopenharmony_ci } 312462306a36Sopenharmony_ci spin_unlock(&j->j_dirty_buffers_lock); 312562306a36Sopenharmony_ci unlock_buffer(bh); 312662306a36Sopenharmony_ci return ret; 312762306a36Sopenharmony_ci} 312862306a36Sopenharmony_ci 312962306a36Sopenharmony_ci/* clm -- taken from fs/buffer.c:block_invalidate_folio */ 313062306a36Sopenharmony_cistatic void reiserfs_invalidate_folio(struct folio *folio, size_t offset, 313162306a36Sopenharmony_ci size_t length) 313262306a36Sopenharmony_ci{ 313362306a36Sopenharmony_ci struct buffer_head *head, *bh, *next; 313462306a36Sopenharmony_ci struct inode *inode = folio->mapping->host; 313562306a36Sopenharmony_ci unsigned int curr_off = 0; 313662306a36Sopenharmony_ci unsigned int stop = offset + length; 313762306a36Sopenharmony_ci int partial_page = (offset || length < folio_size(folio)); 313862306a36Sopenharmony_ci int ret = 1; 313962306a36Sopenharmony_ci 314062306a36Sopenharmony_ci BUG_ON(!folio_test_locked(folio)); 314162306a36Sopenharmony_ci 314262306a36Sopenharmony_ci if (!partial_page) 314362306a36Sopenharmony_ci folio_clear_checked(folio); 314462306a36Sopenharmony_ci 314562306a36Sopenharmony_ci head = folio_buffers(folio); 314662306a36Sopenharmony_ci if (!head) 314762306a36Sopenharmony_ci goto out; 314862306a36Sopenharmony_ci 314962306a36Sopenharmony_ci bh = head; 315062306a36Sopenharmony_ci do { 315162306a36Sopenharmony_ci unsigned int next_off = curr_off + bh->b_size; 315262306a36Sopenharmony_ci next = bh->b_this_page; 315362306a36Sopenharmony_ci 315462306a36Sopenharmony_ci if (next_off > stop) 315562306a36Sopenharmony_ci goto out; 315662306a36Sopenharmony_ci 315762306a36Sopenharmony_ci /* 315862306a36Sopenharmony_ci * is this block fully invalidated? 315962306a36Sopenharmony_ci */ 316062306a36Sopenharmony_ci if (offset <= curr_off) { 316162306a36Sopenharmony_ci if (invalidate_folio_can_drop(inode, bh)) 316262306a36Sopenharmony_ci reiserfs_unmap_buffer(bh); 316362306a36Sopenharmony_ci else 316462306a36Sopenharmony_ci ret = 0; 316562306a36Sopenharmony_ci } 316662306a36Sopenharmony_ci curr_off = next_off; 316762306a36Sopenharmony_ci bh = next; 316862306a36Sopenharmony_ci } while (bh != head); 316962306a36Sopenharmony_ci 317062306a36Sopenharmony_ci /* 317162306a36Sopenharmony_ci * We release buffers only if the entire page is being invalidated. 317262306a36Sopenharmony_ci * The get_block cached value has been unconditionally invalidated, 317362306a36Sopenharmony_ci * so real IO is not possible anymore. 317462306a36Sopenharmony_ci */ 317562306a36Sopenharmony_ci if (!partial_page && ret) { 317662306a36Sopenharmony_ci ret = filemap_release_folio(folio, 0); 317762306a36Sopenharmony_ci /* maybe should BUG_ON(!ret); - neilb */ 317862306a36Sopenharmony_ci } 317962306a36Sopenharmony_ciout: 318062306a36Sopenharmony_ci return; 318162306a36Sopenharmony_ci} 318262306a36Sopenharmony_ci 318362306a36Sopenharmony_cistatic bool reiserfs_dirty_folio(struct address_space *mapping, 318462306a36Sopenharmony_ci struct folio *folio) 318562306a36Sopenharmony_ci{ 318662306a36Sopenharmony_ci if (reiserfs_file_data_log(mapping->host)) { 318762306a36Sopenharmony_ci folio_set_checked(folio); 318862306a36Sopenharmony_ci return filemap_dirty_folio(mapping, folio); 318962306a36Sopenharmony_ci } 319062306a36Sopenharmony_ci return block_dirty_folio(mapping, folio); 319162306a36Sopenharmony_ci} 319262306a36Sopenharmony_ci 319362306a36Sopenharmony_ci/* 319462306a36Sopenharmony_ci * Returns true if the folio's buffers were dropped. The folio is locked. 319562306a36Sopenharmony_ci * 319662306a36Sopenharmony_ci * Takes j_dirty_buffers_lock to protect the b_assoc_buffers list_heads 319762306a36Sopenharmony_ci * in the buffers at folio_buffers(folio). 319862306a36Sopenharmony_ci * 319962306a36Sopenharmony_ci * even in -o notail mode, we can't be sure an old mount without -o notail 320062306a36Sopenharmony_ci * didn't create files with tails. 320162306a36Sopenharmony_ci */ 320262306a36Sopenharmony_cistatic bool reiserfs_release_folio(struct folio *folio, gfp_t unused_gfp_flags) 320362306a36Sopenharmony_ci{ 320462306a36Sopenharmony_ci struct inode *inode = folio->mapping->host; 320562306a36Sopenharmony_ci struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb); 320662306a36Sopenharmony_ci struct buffer_head *head; 320762306a36Sopenharmony_ci struct buffer_head *bh; 320862306a36Sopenharmony_ci bool ret = true; 320962306a36Sopenharmony_ci 321062306a36Sopenharmony_ci WARN_ON(folio_test_checked(folio)); 321162306a36Sopenharmony_ci spin_lock(&j->j_dirty_buffers_lock); 321262306a36Sopenharmony_ci head = folio_buffers(folio); 321362306a36Sopenharmony_ci bh = head; 321462306a36Sopenharmony_ci do { 321562306a36Sopenharmony_ci if (bh->b_private) { 321662306a36Sopenharmony_ci if (!buffer_dirty(bh) && !buffer_locked(bh)) { 321762306a36Sopenharmony_ci reiserfs_free_jh(bh); 321862306a36Sopenharmony_ci } else { 321962306a36Sopenharmony_ci ret = false; 322062306a36Sopenharmony_ci break; 322162306a36Sopenharmony_ci } 322262306a36Sopenharmony_ci } 322362306a36Sopenharmony_ci bh = bh->b_this_page; 322462306a36Sopenharmony_ci } while (bh != head); 322562306a36Sopenharmony_ci if (ret) 322662306a36Sopenharmony_ci ret = try_to_free_buffers(folio); 322762306a36Sopenharmony_ci spin_unlock(&j->j_dirty_buffers_lock); 322862306a36Sopenharmony_ci return ret; 322962306a36Sopenharmony_ci} 323062306a36Sopenharmony_ci 323162306a36Sopenharmony_ci/* 323262306a36Sopenharmony_ci * We thank Mingming Cao for helping us understand in great detail what 323362306a36Sopenharmony_ci * to do in this section of the code. 323462306a36Sopenharmony_ci */ 323562306a36Sopenharmony_cistatic ssize_t reiserfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) 323662306a36Sopenharmony_ci{ 323762306a36Sopenharmony_ci struct file *file = iocb->ki_filp; 323862306a36Sopenharmony_ci struct inode *inode = file->f_mapping->host; 323962306a36Sopenharmony_ci size_t count = iov_iter_count(iter); 324062306a36Sopenharmony_ci ssize_t ret; 324162306a36Sopenharmony_ci 324262306a36Sopenharmony_ci ret = blockdev_direct_IO(iocb, inode, iter, 324362306a36Sopenharmony_ci reiserfs_get_blocks_direct_io); 324462306a36Sopenharmony_ci 324562306a36Sopenharmony_ci /* 324662306a36Sopenharmony_ci * In case of error extending write may have instantiated a few 324762306a36Sopenharmony_ci * blocks outside i_size. Trim these off again. 324862306a36Sopenharmony_ci */ 324962306a36Sopenharmony_ci if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) { 325062306a36Sopenharmony_ci loff_t isize = i_size_read(inode); 325162306a36Sopenharmony_ci loff_t end = iocb->ki_pos + count; 325262306a36Sopenharmony_ci 325362306a36Sopenharmony_ci if ((end > isize) && inode_newsize_ok(inode, isize) == 0) { 325462306a36Sopenharmony_ci truncate_setsize(inode, isize); 325562306a36Sopenharmony_ci reiserfs_vfs_truncate_file(inode); 325662306a36Sopenharmony_ci } 325762306a36Sopenharmony_ci } 325862306a36Sopenharmony_ci 325962306a36Sopenharmony_ci return ret; 326062306a36Sopenharmony_ci} 326162306a36Sopenharmony_ci 326262306a36Sopenharmony_ciint reiserfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 326362306a36Sopenharmony_ci struct iattr *attr) 326462306a36Sopenharmony_ci{ 326562306a36Sopenharmony_ci struct inode *inode = d_inode(dentry); 326662306a36Sopenharmony_ci unsigned int ia_valid; 326762306a36Sopenharmony_ci int error; 326862306a36Sopenharmony_ci 326962306a36Sopenharmony_ci error = setattr_prepare(&nop_mnt_idmap, dentry, attr); 327062306a36Sopenharmony_ci if (error) 327162306a36Sopenharmony_ci return error; 327262306a36Sopenharmony_ci 327362306a36Sopenharmony_ci /* must be turned off for recursive notify_change calls */ 327462306a36Sopenharmony_ci ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); 327562306a36Sopenharmony_ci 327662306a36Sopenharmony_ci if (is_quota_modification(&nop_mnt_idmap, inode, attr)) { 327762306a36Sopenharmony_ci error = dquot_initialize(inode); 327862306a36Sopenharmony_ci if (error) 327962306a36Sopenharmony_ci return error; 328062306a36Sopenharmony_ci } 328162306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 328262306a36Sopenharmony_ci if (attr->ia_valid & ATTR_SIZE) { 328362306a36Sopenharmony_ci /* 328462306a36Sopenharmony_ci * version 2 items will be caught by the s_maxbytes check 328562306a36Sopenharmony_ci * done for us in vmtruncate 328662306a36Sopenharmony_ci */ 328762306a36Sopenharmony_ci if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 && 328862306a36Sopenharmony_ci attr->ia_size > MAX_NON_LFS) { 328962306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 329062306a36Sopenharmony_ci error = -EFBIG; 329162306a36Sopenharmony_ci goto out; 329262306a36Sopenharmony_ci } 329362306a36Sopenharmony_ci 329462306a36Sopenharmony_ci inode_dio_wait(inode); 329562306a36Sopenharmony_ci 329662306a36Sopenharmony_ci /* fill in hole pointers in the expanding truncate case. */ 329762306a36Sopenharmony_ci if (attr->ia_size > inode->i_size) { 329862306a36Sopenharmony_ci loff_t pos = attr->ia_size; 329962306a36Sopenharmony_ci 330062306a36Sopenharmony_ci if ((pos & (inode->i_sb->s_blocksize - 1)) == 0) 330162306a36Sopenharmony_ci pos++; 330262306a36Sopenharmony_ci error = generic_cont_expand_simple(inode, pos); 330362306a36Sopenharmony_ci if (REISERFS_I(inode)->i_prealloc_count > 0) { 330462306a36Sopenharmony_ci int err; 330562306a36Sopenharmony_ci struct reiserfs_transaction_handle th; 330662306a36Sopenharmony_ci /* we're changing at most 2 bitmaps, inode + super */ 330762306a36Sopenharmony_ci err = journal_begin(&th, inode->i_sb, 4); 330862306a36Sopenharmony_ci if (!err) { 330962306a36Sopenharmony_ci reiserfs_discard_prealloc(&th, inode); 331062306a36Sopenharmony_ci err = journal_end(&th); 331162306a36Sopenharmony_ci } 331262306a36Sopenharmony_ci if (err) 331362306a36Sopenharmony_ci error = err; 331462306a36Sopenharmony_ci } 331562306a36Sopenharmony_ci if (error) { 331662306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 331762306a36Sopenharmony_ci goto out; 331862306a36Sopenharmony_ci } 331962306a36Sopenharmony_ci /* 332062306a36Sopenharmony_ci * file size is changed, ctime and mtime are 332162306a36Sopenharmony_ci * to be updated 332262306a36Sopenharmony_ci */ 332362306a36Sopenharmony_ci attr->ia_valid |= (ATTR_MTIME | ATTR_CTIME); 332462306a36Sopenharmony_ci } 332562306a36Sopenharmony_ci } 332662306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 332762306a36Sopenharmony_ci 332862306a36Sopenharmony_ci if ((((attr->ia_valid & ATTR_UID) && (from_kuid(&init_user_ns, attr->ia_uid) & ~0xffff)) || 332962306a36Sopenharmony_ci ((attr->ia_valid & ATTR_GID) && (from_kgid(&init_user_ns, attr->ia_gid) & ~0xffff))) && 333062306a36Sopenharmony_ci (get_inode_sd_version(inode) == STAT_DATA_V1)) { 333162306a36Sopenharmony_ci /* stat data of format v3.5 has 16 bit uid and gid */ 333262306a36Sopenharmony_ci error = -EINVAL; 333362306a36Sopenharmony_ci goto out; 333462306a36Sopenharmony_ci } 333562306a36Sopenharmony_ci 333662306a36Sopenharmony_ci if ((ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, inode->i_uid)) || 333762306a36Sopenharmony_ci (ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, inode->i_gid))) { 333862306a36Sopenharmony_ci struct reiserfs_transaction_handle th; 333962306a36Sopenharmony_ci int jbegin_count = 334062306a36Sopenharmony_ci 2 * 334162306a36Sopenharmony_ci (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) + 334262306a36Sopenharmony_ci REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) + 334362306a36Sopenharmony_ci 2; 334462306a36Sopenharmony_ci 334562306a36Sopenharmony_ci error = reiserfs_chown_xattrs(inode, attr); 334662306a36Sopenharmony_ci 334762306a36Sopenharmony_ci if (error) 334862306a36Sopenharmony_ci return error; 334962306a36Sopenharmony_ci 335062306a36Sopenharmony_ci /* 335162306a36Sopenharmony_ci * (user+group)*(old+new) structure - we count quota 335262306a36Sopenharmony_ci * info and , inode write (sb, inode) 335362306a36Sopenharmony_ci */ 335462306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 335562306a36Sopenharmony_ci error = journal_begin(&th, inode->i_sb, jbegin_count); 335662306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 335762306a36Sopenharmony_ci if (error) 335862306a36Sopenharmony_ci goto out; 335962306a36Sopenharmony_ci error = dquot_transfer(&nop_mnt_idmap, inode, attr); 336062306a36Sopenharmony_ci reiserfs_write_lock(inode->i_sb); 336162306a36Sopenharmony_ci if (error) { 336262306a36Sopenharmony_ci journal_end(&th); 336362306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 336462306a36Sopenharmony_ci goto out; 336562306a36Sopenharmony_ci } 336662306a36Sopenharmony_ci 336762306a36Sopenharmony_ci /* 336862306a36Sopenharmony_ci * Update corresponding info in inode so that everything 336962306a36Sopenharmony_ci * is in one transaction 337062306a36Sopenharmony_ci */ 337162306a36Sopenharmony_ci if (attr->ia_valid & ATTR_UID) 337262306a36Sopenharmony_ci inode->i_uid = attr->ia_uid; 337362306a36Sopenharmony_ci if (attr->ia_valid & ATTR_GID) 337462306a36Sopenharmony_ci inode->i_gid = attr->ia_gid; 337562306a36Sopenharmony_ci mark_inode_dirty(inode); 337662306a36Sopenharmony_ci error = journal_end(&th); 337762306a36Sopenharmony_ci reiserfs_write_unlock(inode->i_sb); 337862306a36Sopenharmony_ci if (error) 337962306a36Sopenharmony_ci goto out; 338062306a36Sopenharmony_ci } 338162306a36Sopenharmony_ci 338262306a36Sopenharmony_ci if ((attr->ia_valid & ATTR_SIZE) && 338362306a36Sopenharmony_ci attr->ia_size != i_size_read(inode)) { 338462306a36Sopenharmony_ci error = inode_newsize_ok(inode, attr->ia_size); 338562306a36Sopenharmony_ci if (!error) { 338662306a36Sopenharmony_ci /* 338762306a36Sopenharmony_ci * Could race against reiserfs_file_release 338862306a36Sopenharmony_ci * if called from NFS, so take tailpack mutex. 338962306a36Sopenharmony_ci */ 339062306a36Sopenharmony_ci mutex_lock(&REISERFS_I(inode)->tailpack); 339162306a36Sopenharmony_ci truncate_setsize(inode, attr->ia_size); 339262306a36Sopenharmony_ci reiserfs_truncate_file(inode, 1); 339362306a36Sopenharmony_ci mutex_unlock(&REISERFS_I(inode)->tailpack); 339462306a36Sopenharmony_ci } 339562306a36Sopenharmony_ci } 339662306a36Sopenharmony_ci 339762306a36Sopenharmony_ci if (!error) { 339862306a36Sopenharmony_ci setattr_copy(&nop_mnt_idmap, inode, attr); 339962306a36Sopenharmony_ci mark_inode_dirty(inode); 340062306a36Sopenharmony_ci } 340162306a36Sopenharmony_ci 340262306a36Sopenharmony_ci if (!error && reiserfs_posixacl(inode->i_sb)) { 340362306a36Sopenharmony_ci if (attr->ia_valid & ATTR_MODE) 340462306a36Sopenharmony_ci error = reiserfs_acl_chmod(dentry); 340562306a36Sopenharmony_ci } 340662306a36Sopenharmony_ci 340762306a36Sopenharmony_ciout: 340862306a36Sopenharmony_ci return error; 340962306a36Sopenharmony_ci} 341062306a36Sopenharmony_ci 341162306a36Sopenharmony_ciconst struct address_space_operations reiserfs_address_space_operations = { 341262306a36Sopenharmony_ci .writepage = reiserfs_writepage, 341362306a36Sopenharmony_ci .read_folio = reiserfs_read_folio, 341462306a36Sopenharmony_ci .readahead = reiserfs_readahead, 341562306a36Sopenharmony_ci .release_folio = reiserfs_release_folio, 341662306a36Sopenharmony_ci .invalidate_folio = reiserfs_invalidate_folio, 341762306a36Sopenharmony_ci .write_begin = reiserfs_write_begin, 341862306a36Sopenharmony_ci .write_end = reiserfs_write_end, 341962306a36Sopenharmony_ci .bmap = reiserfs_aop_bmap, 342062306a36Sopenharmony_ci .direct_IO = reiserfs_direct_IO, 342162306a36Sopenharmony_ci .dirty_folio = reiserfs_dirty_folio, 342262306a36Sopenharmony_ci}; 3423