11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README 31da177e4SLinus Torvalds */ 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds #include <linux/time.h> 61da177e4SLinus Torvalds #include <linux/reiserfs_fs.h> 71da177e4SLinus Torvalds #include <linux/reiserfs_acl.h> 81da177e4SLinus Torvalds #include <linux/reiserfs_xattr.h> 91da177e4SLinus Torvalds #include <linux/smp_lock.h> 101da177e4SLinus Torvalds #include <asm/uaccess.h> 111da177e4SLinus Torvalds #include <linux/pagemap.h> 121da177e4SLinus Torvalds #include <linux/swap.h> 131da177e4SLinus Torvalds #include <linux/writeback.h> 141da177e4SLinus Torvalds #include <linux/blkdev.h> 151da177e4SLinus Torvalds #include <linux/buffer_head.h> 161da177e4SLinus Torvalds #include <linux/quotaops.h> 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds /* 191da177e4SLinus Torvalds ** We pack the tails of files on file close, not at the time they are written. 201da177e4SLinus Torvalds ** This implies an unnecessary copy of the tail and an unnecessary indirect item 211da177e4SLinus Torvalds ** insertion/balancing, for files that are written in one write. 221da177e4SLinus Torvalds ** It avoids unnecessary tail packings (balances) for files that are written in 231da177e4SLinus Torvalds ** multiple writes and are small enough to have tails. 241da177e4SLinus Torvalds ** 251da177e4SLinus Torvalds ** file_release is called by the VFS layer when the file is closed. If 261da177e4SLinus Torvalds ** this is the last open file descriptor, and the file 271da177e4SLinus Torvalds ** small enough to have a tail, and the tail is currently in an 281da177e4SLinus Torvalds ** unformatted node, the tail is converted back into a direct item. 291da177e4SLinus Torvalds ** 301da177e4SLinus Torvalds ** We use reiserfs_truncate_file to pack the tail, since it already has 311da177e4SLinus Torvalds ** all the conditions coded. 321da177e4SLinus Torvalds */ 331da177e4SLinus Torvalds static int reiserfs_file_release(struct inode *inode, struct file *filp) 341da177e4SLinus Torvalds { 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 371da177e4SLinus Torvalds int err; 381da177e4SLinus Torvalds int jbegin_failure = 0; 391da177e4SLinus Torvalds 4014a61442SEric Sesterhenn BUG_ON(!S_ISREG(inode->i_mode)); 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds /* fast out for when nothing needs to be done */ 431da177e4SLinus Torvalds if ((atomic_read(&inode->i_count) > 1 || 441da177e4SLinus Torvalds !(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) || 451da177e4SLinus Torvalds !tail_has_to_be_packed(inode)) && 461da177e4SLinus Torvalds REISERFS_I(inode)->i_prealloc_count <= 0) { 471da177e4SLinus Torvalds return 0; 481da177e4SLinus Torvalds } 491da177e4SLinus Torvalds 501b1dcc1bSJes Sorensen mutex_lock(&inode->i_mutex); 51*de14569fSVladimir Saveliev 52*de14569fSVladimir Saveliev mutex_lock(&(REISERFS_I(inode)->i_mmap)); 53*de14569fSVladimir Saveliev if (REISERFS_I(inode)->i_flags & i_ever_mapped) 54*de14569fSVladimir Saveliev REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; 55*de14569fSVladimir Saveliev 56b5f3953cSChris Mason reiserfs_write_lock(inode->i_sb); 571da177e4SLinus Torvalds /* freeing preallocation only involves relogging blocks that 581da177e4SLinus Torvalds * are already in the current transaction. preallocation gets 591da177e4SLinus Torvalds * freed at the end of each transaction, so it is impossible for 601da177e4SLinus Torvalds * us to log any additional blocks (including quota blocks) 611da177e4SLinus Torvalds */ 621da177e4SLinus Torvalds err = journal_begin(&th, inode->i_sb, 1); 631da177e4SLinus Torvalds if (err) { 641da177e4SLinus Torvalds /* uh oh, we can't allow the inode to go away while there 651da177e4SLinus Torvalds * is still preallocation blocks pending. Try to join the 661da177e4SLinus Torvalds * aborted transaction 671da177e4SLinus Torvalds */ 681da177e4SLinus Torvalds jbegin_failure = err; 691da177e4SLinus Torvalds err = journal_join_abort(&th, inode->i_sb, 1); 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds if (err) { 721da177e4SLinus Torvalds /* hmpf, our choices here aren't good. We can pin the inode 731da177e4SLinus Torvalds * which will disallow unmount from every happening, we can 741da177e4SLinus Torvalds * do nothing, which will corrupt random memory on unmount, 751da177e4SLinus Torvalds * or we can forcibly remove the file from the preallocation 761da177e4SLinus Torvalds * list, which will leak blocks on disk. Lets pin the inode 771da177e4SLinus Torvalds * and let the admin know what is going on. 781da177e4SLinus Torvalds */ 791da177e4SLinus Torvalds igrab(inode); 80bd4c625cSLinus Torvalds reiserfs_warning(inode->i_sb, 81bd4c625cSLinus Torvalds "pinning inode %lu because the " 82533221fbSAlexey Dobriyan "preallocation can't be freed", 83533221fbSAlexey Dobriyan inode->i_ino); 841da177e4SLinus Torvalds goto out; 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds } 871da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds #ifdef REISERFS_PREALLOCATE 901da177e4SLinus Torvalds reiserfs_discard_prealloc(&th, inode); 911da177e4SLinus Torvalds #endif 921da177e4SLinus Torvalds err = journal_end(&th, inode->i_sb, 1); 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds /* copy back the error code from journal_begin */ 951da177e4SLinus Torvalds if (!err) 961da177e4SLinus Torvalds err = jbegin_failure; 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds if (!err && atomic_read(&inode->i_count) <= 1 && 991da177e4SLinus Torvalds (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) && 1001da177e4SLinus Torvalds tail_has_to_be_packed(inode)) { 1011da177e4SLinus Torvalds /* if regular file is released by last holder and it has been 1021da177e4SLinus Torvalds appended (we append by unformatted node only) or its direct 1031da177e4SLinus Torvalds item(s) had to be converted, then it may have to be 1041da177e4SLinus Torvalds indirect2direct converted */ 1051da177e4SLinus Torvalds err = reiserfs_truncate_file(inode, 0); 1061da177e4SLinus Torvalds } 1071da177e4SLinus Torvalds out: 108*de14569fSVladimir Saveliev mutex_unlock(&(REISERFS_I(inode)->i_mmap)); 1091b1dcc1bSJes Sorensen mutex_unlock(&inode->i_mutex); 1101da177e4SLinus Torvalds reiserfs_write_unlock(inode->i_sb); 1111da177e4SLinus Torvalds return err; 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds 114*de14569fSVladimir Saveliev static int reiserfs_file_mmap(struct file *file, struct vm_area_struct *vma) 115*de14569fSVladimir Saveliev { 116*de14569fSVladimir Saveliev struct inode *inode; 117*de14569fSVladimir Saveliev 118*de14569fSVladimir Saveliev inode = file->f_path.dentry->d_inode; 119*de14569fSVladimir Saveliev mutex_lock(&(REISERFS_I(inode)->i_mmap)); 120*de14569fSVladimir Saveliev REISERFS_I(inode)->i_flags |= i_ever_mapped; 121*de14569fSVladimir Saveliev mutex_unlock(&(REISERFS_I(inode)->i_mmap)); 122*de14569fSVladimir Saveliev 123*de14569fSVladimir Saveliev return generic_file_mmap(file, vma); 124*de14569fSVladimir Saveliev } 125*de14569fSVladimir Saveliev 126bd4c625cSLinus Torvalds static void reiserfs_vfs_truncate_file(struct inode *inode) 127bd4c625cSLinus Torvalds { 1281da177e4SLinus Torvalds reiserfs_truncate_file(inode, 1); 1291da177e4SLinus Torvalds } 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds /* Sync a reiserfs file. */ 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds /* 1341da177e4SLinus Torvalds * FIXME: sync_mapping_buffers() never has anything to sync. Can 1351da177e4SLinus Torvalds * be removed... 1361da177e4SLinus Torvalds */ 1371da177e4SLinus Torvalds 138bd4c625cSLinus Torvalds static int reiserfs_sync_file(struct file *p_s_filp, 139bd4c625cSLinus Torvalds struct dentry *p_s_dentry, int datasync) 140bd4c625cSLinus Torvalds { 1411da177e4SLinus Torvalds struct inode *p_s_inode = p_s_dentry->d_inode; 1421da177e4SLinus Torvalds int n_err; 1431da177e4SLinus Torvalds int barrier_done; 1441da177e4SLinus Torvalds 14514a61442SEric Sesterhenn BUG_ON(!S_ISREG(p_s_inode->i_mode)); 1461da177e4SLinus Torvalds n_err = sync_mapping_buffers(p_s_inode->i_mapping); 1471da177e4SLinus Torvalds reiserfs_write_lock(p_s_inode->i_sb); 1481da177e4SLinus Torvalds barrier_done = reiserfs_commit_for_inode(p_s_inode); 1491da177e4SLinus Torvalds reiserfs_write_unlock(p_s_inode->i_sb); 15025736b1cSChris Mason if (barrier_done != 1 && reiserfs_barrier_flush(p_s_inode->i_sb)) 1511da177e4SLinus Torvalds blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL); 1521da177e4SLinus Torvalds if (barrier_done < 0) 1531da177e4SLinus Torvalds return barrier_done; 1541da177e4SLinus Torvalds return (n_err < 0) ? -EIO : 0; 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds /* I really do not want to play with memory shortage right now, so 1581da177e4SLinus Torvalds to simplify the code, we are not going to write more than this much pages at 1591da177e4SLinus Torvalds a time. This still should considerably improve performance compared to 4k 1601da177e4SLinus Torvalds at a time case. This is 32 pages of 4k size. */ 1611da177e4SLinus Torvalds #define REISERFS_WRITE_PAGES_AT_A_TIME (128 * 1024) / PAGE_CACHE_SIZE 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds /* Allocates blocks for a file to fulfil write request. 1641da177e4SLinus Torvalds Maps all unmapped but prepared pages from the list. 1651da177e4SLinus Torvalds Updates metadata with newly allocated blocknumbers as needed */ 166bd4c625cSLinus Torvalds static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handle *th, struct inode *inode, /* Inode we work with */ 1671da177e4SLinus Torvalds loff_t pos, /* Writing position */ 1681da177e4SLinus Torvalds int num_pages, /* number of pages write going 1691da177e4SLinus Torvalds to touch */ 1701da177e4SLinus Torvalds int write_bytes, /* amount of bytes to write */ 1711da177e4SLinus Torvalds struct page **prepared_pages, /* array of 1721da177e4SLinus Torvalds prepared pages 1731da177e4SLinus Torvalds */ 1741da177e4SLinus Torvalds int blocks_to_allocate /* Amount of blocks we 1751da177e4SLinus Torvalds need to allocate to 1761da177e4SLinus Torvalds fit the data into file 1771da177e4SLinus Torvalds */ 1781da177e4SLinus Torvalds ) 1791da177e4SLinus Torvalds { 1801da177e4SLinus Torvalds struct cpu_key key; // cpu key of item that we are going to deal with 1811da177e4SLinus Torvalds struct item_head *ih; // pointer to item head that we are going to deal with 1821da177e4SLinus Torvalds struct buffer_head *bh; // Buffer head that contains items that we are going to deal with 1833e8962beSAl Viro __le32 *item; // pointer to item we are going to deal with 1841da177e4SLinus Torvalds INITIALIZE_PATH(path); // path to item, that we are going to deal with. 1851da177e4SLinus Torvalds b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored. 1861da177e4SLinus Torvalds reiserfs_blocknr_hint_t hint; // hint structure for block allocator. 1871da177e4SLinus Torvalds size_t res; // return value of various functions that we call. 1881da177e4SLinus Torvalds int curr_block; // current block used to keep track of unmapped blocks. 1891da177e4SLinus Torvalds int i; // loop counter 1901da177e4SLinus Torvalds int itempos; // position in item 1911da177e4SLinus Torvalds unsigned int from = (pos & (PAGE_CACHE_SIZE - 1)); // writing position in 1921da177e4SLinus Torvalds // first page 1931da177e4SLinus Torvalds unsigned int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1; /* last modified byte offset in last page */ 1941da177e4SLinus Torvalds __u64 hole_size; // amount of blocks for a file hole, if it needed to be created. 1951da177e4SLinus Torvalds int modifying_this_item = 0; // Flag for items traversal code to keep track 1961da177e4SLinus Torvalds // of the fact that we already prepared 1971da177e4SLinus Torvalds // current block for journal 1981da177e4SLinus Torvalds int will_prealloc = 0; 199bd4c625cSLinus Torvalds RFALSE(!blocks_to_allocate, 200bd4c625cSLinus Torvalds "green-9004: tried to allocate zero blocks?"); 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds /* only preallocate if this is a small write */ 2031da177e4SLinus Torvalds if (REISERFS_I(inode)->i_prealloc_count || 2041da177e4SLinus Torvalds (!(write_bytes & (inode->i_sb->s_blocksize - 1)) && 2051da177e4SLinus Torvalds blocks_to_allocate < 2061da177e4SLinus Torvalds REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize)) 207bd4c625cSLinus Torvalds will_prealloc = 208bd4c625cSLinus Torvalds REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize; 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds allocated_blocks = kmalloc((blocks_to_allocate + will_prealloc) * 2111da177e4SLinus Torvalds sizeof(b_blocknr_t), GFP_NOFS); 212e5dd259fSDiego Calleja if (!allocated_blocks) 213e5dd259fSDiego Calleja return -ENOMEM; 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds /* First we compose a key to point at the writing position, we want to do 2161da177e4SLinus Torvalds that outside of any locking region. */ 2171da177e4SLinus Torvalds make_cpu_key(&key, inode, pos + 1, TYPE_ANY, 3 /*key length */ ); 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds /* If we came here, it means we absolutely need to open a transaction, 2201da177e4SLinus Torvalds since we need to allocate some blocks */ 2211da177e4SLinus Torvalds reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that. 222556a2a45SJan Kara res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb)); // Wish I know if this number enough 2231da177e4SLinus Torvalds if (res) 2241da177e4SLinus Torvalds goto error_exit; 2251da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds /* Look for the in-tree position of our write, need path for block allocator */ 2281da177e4SLinus Torvalds res = search_for_position_by_key(inode->i_sb, &key, &path); 2291da177e4SLinus Torvalds if (res == IO_ERROR) { 2301da177e4SLinus Torvalds res = -EIO; 2311da177e4SLinus Torvalds goto error_exit; 2321da177e4SLinus Torvalds } 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds /* Allocate blocks */ 2351da177e4SLinus Torvalds /* First fill in "hint" structure for block allocator */ 2361da177e4SLinus Torvalds hint.th = th; // transaction handle. 2371da177e4SLinus Torvalds hint.path = &path; // Path, so that block allocator can determine packing locality or whatever it needs to determine. 2381da177e4SLinus Torvalds hint.inode = inode; // Inode is needed by block allocator too. 2391da177e4SLinus Torvalds hint.search_start = 0; // We have no hint on where to search free blocks for block allocator. 2401da177e4SLinus Torvalds hint.key = key.on_disk_key; // on disk key of file. 2411da177e4SLinus Torvalds hint.block = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9); // Number of disk blocks this file occupies already. 2421da177e4SLinus Torvalds hint.formatted_node = 0; // We are allocating blocks for unformatted node. 2431da177e4SLinus Torvalds hint.preallocate = will_prealloc; 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds /* Call block allocator to allocate blocks */ 246bd4c625cSLinus Torvalds res = 247bd4c625cSLinus Torvalds reiserfs_allocate_blocknrs(&hint, allocated_blocks, 248bd4c625cSLinus Torvalds blocks_to_allocate, blocks_to_allocate); 2491da177e4SLinus Torvalds if (res != CARRY_ON) { 2501da177e4SLinus Torvalds if (res == NO_DISK_SPACE) { 2511da177e4SLinus Torvalds /* We flush the transaction in case of no space. This way some 2521da177e4SLinus Torvalds blocks might become free */ 2531da177e4SLinus Torvalds SB_JOURNAL(inode->i_sb)->j_must_wait = 1; 2541da177e4SLinus Torvalds res = restart_transaction(th, inode, &path); 2551da177e4SLinus Torvalds if (res) 2561da177e4SLinus Torvalds goto error_exit; 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds /* We might have scheduled, so search again */ 259bd4c625cSLinus Torvalds res = 260bd4c625cSLinus Torvalds search_for_position_by_key(inode->i_sb, &key, 261bd4c625cSLinus Torvalds &path); 2621da177e4SLinus Torvalds if (res == IO_ERROR) { 2631da177e4SLinus Torvalds res = -EIO; 2641da177e4SLinus Torvalds goto error_exit; 2651da177e4SLinus Torvalds } 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds /* update changed info for hint structure. */ 268bd4c625cSLinus Torvalds res = 269bd4c625cSLinus Torvalds reiserfs_allocate_blocknrs(&hint, allocated_blocks, 270bd4c625cSLinus Torvalds blocks_to_allocate, 271bd4c625cSLinus Torvalds blocks_to_allocate); 2721da177e4SLinus Torvalds if (res != CARRY_ON) { 2730ad74ffaSJan Kara res = res == QUOTA_EXCEEDED ? -EDQUOT : -ENOSPC; 2741da177e4SLinus Torvalds pathrelse(&path); 2751da177e4SLinus Torvalds goto error_exit; 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds } else { 2780ad74ffaSJan Kara res = res == QUOTA_EXCEEDED ? -EDQUOT : -ENOSPC; 2791da177e4SLinus Torvalds pathrelse(&path); 2801da177e4SLinus Torvalds goto error_exit; 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds #ifdef __BIG_ENDIAN 2841da177e4SLinus Torvalds // Too bad, I have not found any way to convert a given region from 2851da177e4SLinus Torvalds // cpu format to little endian format 2861da177e4SLinus Torvalds { 2871da177e4SLinus Torvalds int i; 2881da177e4SLinus Torvalds for (i = 0; i < blocks_to_allocate; i++) 2891da177e4SLinus Torvalds allocated_blocks[i] = cpu_to_le32(allocated_blocks[i]); 2901da177e4SLinus Torvalds } 2911da177e4SLinus Torvalds #endif 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds /* Blocks allocating well might have scheduled and tree might have changed, 2941da177e4SLinus Torvalds let's search the tree again */ 2951da177e4SLinus Torvalds /* find where in the tree our write should go */ 2961da177e4SLinus Torvalds res = search_for_position_by_key(inode->i_sb, &key, &path); 2971da177e4SLinus Torvalds if (res == IO_ERROR) { 2981da177e4SLinus Torvalds res = -EIO; 2991da177e4SLinus Torvalds goto error_exit_free_blocks; 3001da177e4SLinus Torvalds } 3011da177e4SLinus Torvalds 3021da177e4SLinus Torvalds bh = get_last_bh(&path); // Get a bufferhead for last element in path. 3031da177e4SLinus Torvalds ih = get_ih(&path); // Get a pointer to last item head in path. 3041da177e4SLinus Torvalds item = get_item(&path); // Get a pointer to last item in path 3051da177e4SLinus Torvalds 3061da177e4SLinus Torvalds /* Let's see what we have found */ 3071da177e4SLinus Torvalds if (res != POSITION_FOUND) { /* position not found, this means that we 3081da177e4SLinus Torvalds might need to append file with holes 3091da177e4SLinus Torvalds first */ 3101da177e4SLinus Torvalds // Since we are writing past the file's end, we need to find out if 3111da177e4SLinus Torvalds // there is a hole that needs to be inserted before our writing 3121da177e4SLinus Torvalds // position, and how many blocks it is going to cover (we need to 3131da177e4SLinus Torvalds // populate pointers to file blocks representing the hole with zeros) 3141da177e4SLinus Torvalds 3151da177e4SLinus Torvalds { 3161da177e4SLinus Torvalds int item_offset = 1; 3171da177e4SLinus Torvalds /* 3181da177e4SLinus Torvalds * if ih is stat data, its offset is 0 and we don't want to 3191da177e4SLinus Torvalds * add 1 to pos in the hole_size calculation 3201da177e4SLinus Torvalds */ 3211da177e4SLinus Torvalds if (is_statdata_le_ih(ih)) 3221da177e4SLinus Torvalds item_offset = 0; 3231da177e4SLinus Torvalds hole_size = (pos + item_offset - 324bd4c625cSLinus Torvalds (le_key_k_offset 325bd4c625cSLinus Torvalds (get_inode_item_key_version(inode), 326bd4c625cSLinus Torvalds &(ih->ih_key)) + op_bytes_number(ih, 327bd4c625cSLinus Torvalds inode-> 328bd4c625cSLinus Torvalds i_sb-> 329bd4c625cSLinus Torvalds s_blocksize))) 330bd4c625cSLinus Torvalds >> inode->i_sb->s_blocksize_bits; 3311da177e4SLinus Torvalds } 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds if (hole_size > 0) { 3341da177e4SLinus Torvalds int to_paste = min_t(__u64, hole_size, MAX_ITEM_LEN(inode->i_sb->s_blocksize) / UNFM_P_SIZE); // How much data to insert first time. 3351da177e4SLinus Torvalds /* area filled with zeroes, to supply as list of zero blocknumbers 3361da177e4SLinus Torvalds We allocate it outside of loop just in case loop would spin for 3371da177e4SLinus Torvalds several iterations. */ 33801afb213SYan Burman char *zeros = kzalloc(to_paste * UNFM_P_SIZE, GFP_ATOMIC); // We cannot insert more than MAX_ITEM_LEN bytes anyway. 3391da177e4SLinus Torvalds if (!zeros) { 3401da177e4SLinus Torvalds res = -ENOMEM; 3411da177e4SLinus Torvalds goto error_exit_free_blocks; 3421da177e4SLinus Torvalds } 3431da177e4SLinus Torvalds do { 344bd4c625cSLinus Torvalds to_paste = 345bd4c625cSLinus Torvalds min_t(__u64, hole_size, 346bd4c625cSLinus Torvalds MAX_ITEM_LEN(inode->i_sb-> 347bd4c625cSLinus Torvalds s_blocksize) / 348bd4c625cSLinus Torvalds UNFM_P_SIZE); 3491da177e4SLinus Torvalds if (is_indirect_le_ih(ih)) { 3501da177e4SLinus Torvalds /* Ok, there is existing indirect item already. Need to append it */ 3511da177e4SLinus Torvalds /* Calculate position past inserted item */ 352bd4c625cSLinus Torvalds make_cpu_key(&key, inode, 353bd4c625cSLinus Torvalds le_key_k_offset 354bd4c625cSLinus Torvalds (get_inode_item_key_version 355bd4c625cSLinus Torvalds (inode), 356bd4c625cSLinus Torvalds &(ih->ih_key)) + 357bd4c625cSLinus Torvalds op_bytes_number(ih, 358bd4c625cSLinus Torvalds inode-> 359bd4c625cSLinus Torvalds i_sb-> 360bd4c625cSLinus Torvalds s_blocksize), 361bd4c625cSLinus Torvalds TYPE_INDIRECT, 3); 362bd4c625cSLinus Torvalds res = 363bd4c625cSLinus Torvalds reiserfs_paste_into_item(th, &path, 364bd4c625cSLinus Torvalds &key, 365bd4c625cSLinus Torvalds inode, 366bd4c625cSLinus Torvalds (char *) 367bd4c625cSLinus Torvalds zeros, 368bd4c625cSLinus Torvalds UNFM_P_SIZE 369bd4c625cSLinus Torvalds * 370bd4c625cSLinus Torvalds to_paste); 3711da177e4SLinus Torvalds if (res) { 3721da177e4SLinus Torvalds kfree(zeros); 3731da177e4SLinus Torvalds goto error_exit_free_blocks; 3741da177e4SLinus Torvalds } 3751da177e4SLinus Torvalds } else if (is_statdata_le_ih(ih)) { 3761da177e4SLinus Torvalds /* No existing item, create it */ 3771da177e4SLinus Torvalds /* item head for new item */ 3781da177e4SLinus Torvalds struct item_head ins_ih; 3791da177e4SLinus Torvalds 3801da177e4SLinus Torvalds /* create a key for our new item */ 381bd4c625cSLinus Torvalds make_cpu_key(&key, inode, 1, 382bd4c625cSLinus Torvalds TYPE_INDIRECT, 3); 3831da177e4SLinus Torvalds 3841da177e4SLinus Torvalds /* Create new item head for our new item */ 385bd4c625cSLinus Torvalds make_le_item_head(&ins_ih, &key, 386bd4c625cSLinus Torvalds key.version, 1, 387bd4c625cSLinus Torvalds TYPE_INDIRECT, 388bd4c625cSLinus Torvalds to_paste * 389bd4c625cSLinus Torvalds UNFM_P_SIZE, 3901da177e4SLinus Torvalds 0 /* free space */ ); 3911da177e4SLinus Torvalds 3921da177e4SLinus Torvalds /* Find where such item should live in the tree */ 393bd4c625cSLinus Torvalds res = 394bd4c625cSLinus Torvalds search_item(inode->i_sb, &key, 395bd4c625cSLinus Torvalds &path); 3961da177e4SLinus Torvalds if (res != ITEM_NOT_FOUND) { 3971da177e4SLinus Torvalds /* item should not exist, otherwise we have error */ 3981da177e4SLinus Torvalds if (res != -ENOSPC) { 399bd4c625cSLinus Torvalds reiserfs_warning(inode-> 400bd4c625cSLinus Torvalds i_sb, 4011da177e4SLinus Torvalds "green-9008: search_by_key (%K) returned %d", 402bd4c625cSLinus Torvalds &key, 403bd4c625cSLinus Torvalds res); 4041da177e4SLinus Torvalds } 4051da177e4SLinus Torvalds res = -EIO; 4061da177e4SLinus Torvalds kfree(zeros); 4071da177e4SLinus Torvalds goto error_exit_free_blocks; 4081da177e4SLinus Torvalds } 409bd4c625cSLinus Torvalds res = 410bd4c625cSLinus Torvalds reiserfs_insert_item(th, &path, 411bd4c625cSLinus Torvalds &key, &ins_ih, 412bd4c625cSLinus Torvalds inode, 413bd4c625cSLinus Torvalds (char *)zeros); 4141da177e4SLinus Torvalds } else { 415bd4c625cSLinus Torvalds reiserfs_panic(inode->i_sb, 416bd4c625cSLinus Torvalds "green-9011: Unexpected key type %K\n", 417bd4c625cSLinus Torvalds &key); 4181da177e4SLinus Torvalds } 4191da177e4SLinus Torvalds if (res) { 4201da177e4SLinus Torvalds kfree(zeros); 4211da177e4SLinus Torvalds goto error_exit_free_blocks; 4221da177e4SLinus Torvalds } 4231da177e4SLinus Torvalds /* Now we want to check if transaction is too full, and if it is 4241da177e4SLinus Torvalds we restart it. This will also free the path. */ 425bd4c625cSLinus Torvalds if (journal_transaction_should_end 426bd4c625cSLinus Torvalds (th, th->t_blocks_allocated)) { 427c5574768SVladimir V. Saveliev inode->i_size = cpu_key_k_offset(&key) + 428c5574768SVladimir V. Saveliev (to_paste << inode->i_blkbits); 429bd4c625cSLinus Torvalds res = 430bd4c625cSLinus Torvalds restart_transaction(th, inode, 431bd4c625cSLinus Torvalds &path); 4321da177e4SLinus Torvalds if (res) { 4331da177e4SLinus Torvalds pathrelse(&path); 4341da177e4SLinus Torvalds kfree(zeros); 4351da177e4SLinus Torvalds goto error_exit; 4361da177e4SLinus Torvalds } 4371da177e4SLinus Torvalds } 4381da177e4SLinus Torvalds 4391da177e4SLinus Torvalds /* Well, need to recalculate path and stuff */ 440bd4c625cSLinus Torvalds set_cpu_key_k_offset(&key, 441bd4c625cSLinus Torvalds cpu_key_k_offset(&key) + 442bd4c625cSLinus Torvalds (to_paste << inode-> 443bd4c625cSLinus Torvalds i_blkbits)); 444bd4c625cSLinus Torvalds res = 445bd4c625cSLinus Torvalds search_for_position_by_key(inode->i_sb, 446bd4c625cSLinus Torvalds &key, &path); 4471da177e4SLinus Torvalds if (res == IO_ERROR) { 4481da177e4SLinus Torvalds res = -EIO; 4491da177e4SLinus Torvalds kfree(zeros); 4501da177e4SLinus Torvalds goto error_exit_free_blocks; 4511da177e4SLinus Torvalds } 4521da177e4SLinus Torvalds bh = get_last_bh(&path); 4531da177e4SLinus Torvalds ih = get_ih(&path); 4541da177e4SLinus Torvalds item = get_item(&path); 4551da177e4SLinus Torvalds hole_size -= to_paste; 4561da177e4SLinus Torvalds } while (hole_size); 4571da177e4SLinus Torvalds kfree(zeros); 4581da177e4SLinus Torvalds } 4591da177e4SLinus Torvalds } 4601da177e4SLinus Torvalds // Go through existing indirect items first 4611da177e4SLinus Torvalds // replace all zeroes with blocknumbers from list 4621da177e4SLinus Torvalds // Note that if no corresponding item was found, by previous search, 4631da177e4SLinus Torvalds // it means there are no existing in-tree representation for file area 4641da177e4SLinus Torvalds // we are going to overwrite, so there is nothing to scan through for holes. 465bd4c625cSLinus Torvalds for (curr_block = 0, itempos = path.pos_in_item; 466bd4c625cSLinus Torvalds curr_block < blocks_to_allocate && res == POSITION_FOUND;) { 4671da177e4SLinus Torvalds retry: 4681da177e4SLinus Torvalds 4691da177e4SLinus Torvalds if (itempos >= ih_item_len(ih) / UNFM_P_SIZE) { 4701da177e4SLinus Torvalds /* We run out of data in this indirect item, let's look for another 4711da177e4SLinus Torvalds one. */ 4721da177e4SLinus Torvalds /* First if we are already modifying current item, log it */ 4731da177e4SLinus Torvalds if (modifying_this_item) { 4741da177e4SLinus Torvalds journal_mark_dirty(th, inode->i_sb, bh); 4751da177e4SLinus Torvalds modifying_this_item = 0; 4761da177e4SLinus Torvalds } 4771da177e4SLinus Torvalds /* Then set the key to look for a new indirect item (offset of old 4781da177e4SLinus Torvalds item is added to old item length */ 479bd4c625cSLinus Torvalds set_cpu_key_k_offset(&key, 480bd4c625cSLinus Torvalds le_key_k_offset 481bd4c625cSLinus Torvalds (get_inode_item_key_version(inode), 482bd4c625cSLinus Torvalds &(ih->ih_key)) + 483bd4c625cSLinus Torvalds op_bytes_number(ih, 484bd4c625cSLinus Torvalds inode->i_sb-> 485bd4c625cSLinus Torvalds s_blocksize)); 4861da177e4SLinus Torvalds /* Search ofor position of new key in the tree. */ 487bd4c625cSLinus Torvalds res = 488bd4c625cSLinus Torvalds search_for_position_by_key(inode->i_sb, &key, 489bd4c625cSLinus Torvalds &path); 4901da177e4SLinus Torvalds if (res == IO_ERROR) { 4911da177e4SLinus Torvalds res = -EIO; 4921da177e4SLinus Torvalds goto error_exit_free_blocks; 4931da177e4SLinus Torvalds } 4941da177e4SLinus Torvalds bh = get_last_bh(&path); 4951da177e4SLinus Torvalds ih = get_ih(&path); 4961da177e4SLinus Torvalds item = get_item(&path); 4971da177e4SLinus Torvalds itempos = path.pos_in_item; 4981da177e4SLinus Torvalds continue; // loop to check all kinds of conditions and so on. 4991da177e4SLinus Torvalds } 5001da177e4SLinus Torvalds /* Ok, we have correct position in item now, so let's see if it is 5011da177e4SLinus Torvalds representing file hole (blocknumber is zero) and fill it if needed */ 5021da177e4SLinus Torvalds if (!item[itempos]) { 5031da177e4SLinus Torvalds /* Ok, a hole. Now we need to check if we already prepared this 5041da177e4SLinus Torvalds block to be journaled */ 5051da177e4SLinus Torvalds while (!modifying_this_item) { // loop until succeed 5061da177e4SLinus Torvalds /* Well, this item is not journaled yet, so we must prepare 5071da177e4SLinus Torvalds it for journal first, before we can change it */ 5081da177e4SLinus Torvalds struct item_head tmp_ih; // We copy item head of found item, 5091da177e4SLinus Torvalds // here to detect if fs changed under 5101da177e4SLinus Torvalds // us while we were preparing for 5111da177e4SLinus Torvalds // journal. 5121da177e4SLinus Torvalds int fs_gen; // We store fs generation here to find if someone 5131da177e4SLinus Torvalds // changes fs under our feet 5141da177e4SLinus Torvalds 5151da177e4SLinus Torvalds copy_item_head(&tmp_ih, ih); // Remember itemhead 5161da177e4SLinus Torvalds fs_gen = get_generation(inode->i_sb); // remember fs generation 5171da177e4SLinus Torvalds reiserfs_prepare_for_journal(inode->i_sb, bh, 1); // Prepare a buffer within which indirect item is stored for changing. 518bd4c625cSLinus Torvalds if (fs_changed(fs_gen, inode->i_sb) 519bd4c625cSLinus Torvalds && item_moved(&tmp_ih, &path)) { 5201da177e4SLinus Torvalds // Sigh, fs was changed under us, we need to look for new 5211da177e4SLinus Torvalds // location of item we are working with 5221da177e4SLinus Torvalds 5231da177e4SLinus Torvalds /* unmark prepaerd area as journaled and search for it's 5241da177e4SLinus Torvalds new position */ 525bd4c625cSLinus Torvalds reiserfs_restore_prepared_buffer(inode-> 526bd4c625cSLinus Torvalds i_sb, 527bd4c625cSLinus Torvalds bh); 528bd4c625cSLinus Torvalds res = 529bd4c625cSLinus Torvalds search_for_position_by_key(inode-> 530bd4c625cSLinus Torvalds i_sb, 531bd4c625cSLinus Torvalds &key, 532bd4c625cSLinus Torvalds &path); 5331da177e4SLinus Torvalds if (res == IO_ERROR) { 5341da177e4SLinus Torvalds res = -EIO; 5351da177e4SLinus Torvalds goto error_exit_free_blocks; 5361da177e4SLinus Torvalds } 5371da177e4SLinus Torvalds bh = get_last_bh(&path); 5381da177e4SLinus Torvalds ih = get_ih(&path); 5391da177e4SLinus Torvalds item = get_item(&path); 5401da177e4SLinus Torvalds itempos = path.pos_in_item; 5411da177e4SLinus Torvalds goto retry; 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds modifying_this_item = 1; 5441da177e4SLinus Torvalds } 5451da177e4SLinus Torvalds item[itempos] = allocated_blocks[curr_block]; // Assign new block 5461da177e4SLinus Torvalds curr_block++; 5471da177e4SLinus Torvalds } 5481da177e4SLinus Torvalds itempos++; 5491da177e4SLinus Torvalds } 5501da177e4SLinus Torvalds 5511da177e4SLinus Torvalds if (modifying_this_item) { // We need to log last-accessed block, if it 5521da177e4SLinus Torvalds // was modified, but not logged yet. 5531da177e4SLinus Torvalds journal_mark_dirty(th, inode->i_sb, bh); 5541da177e4SLinus Torvalds } 5551da177e4SLinus Torvalds 5561da177e4SLinus Torvalds if (curr_block < blocks_to_allocate) { 5571da177e4SLinus Torvalds // Oh, well need to append to indirect item, or to create indirect item 5581da177e4SLinus Torvalds // if there weren't any 5591da177e4SLinus Torvalds if (is_indirect_le_ih(ih)) { 5601da177e4SLinus Torvalds // Existing indirect item - append. First calculate key for append 5611da177e4SLinus Torvalds // position. We do not need to recalculate path as it should 5621da177e4SLinus Torvalds // already point to correct place. 563bd4c625cSLinus Torvalds make_cpu_key(&key, inode, 564bd4c625cSLinus Torvalds le_key_k_offset(get_inode_item_key_version 565bd4c625cSLinus Torvalds (inode), 566bd4c625cSLinus Torvalds &(ih->ih_key)) + 567bd4c625cSLinus Torvalds op_bytes_number(ih, 568bd4c625cSLinus Torvalds inode->i_sb->s_blocksize), 569bd4c625cSLinus Torvalds TYPE_INDIRECT, 3); 570bd4c625cSLinus Torvalds res = 571bd4c625cSLinus Torvalds reiserfs_paste_into_item(th, &path, &key, inode, 572bd4c625cSLinus Torvalds (char *)(allocated_blocks + 573bd4c625cSLinus Torvalds curr_block), 574bd4c625cSLinus Torvalds UNFM_P_SIZE * 575bd4c625cSLinus Torvalds (blocks_to_allocate - 576bd4c625cSLinus Torvalds curr_block)); 5771da177e4SLinus Torvalds if (res) { 5781da177e4SLinus Torvalds goto error_exit_free_blocks; 5791da177e4SLinus Torvalds } 5801da177e4SLinus Torvalds } else if (is_statdata_le_ih(ih)) { 5811da177e4SLinus Torvalds // Last found item was statdata. That means we need to create indirect item. 5821da177e4SLinus Torvalds struct item_head ins_ih; /* itemhead for new item */ 5831da177e4SLinus Torvalds 5841da177e4SLinus Torvalds /* create a key for our new item */ 5851da177e4SLinus Torvalds make_cpu_key(&key, inode, 1, TYPE_INDIRECT, 3); // Position one, 5861da177e4SLinus Torvalds // because that's 5871da177e4SLinus Torvalds // where first 5881da177e4SLinus Torvalds // indirect item 5891da177e4SLinus Torvalds // begins 5901da177e4SLinus Torvalds /* Create new item head for our new item */ 591bd4c625cSLinus Torvalds make_le_item_head(&ins_ih, &key, key.version, 1, 592bd4c625cSLinus Torvalds TYPE_INDIRECT, 593bd4c625cSLinus Torvalds (blocks_to_allocate - 594bd4c625cSLinus Torvalds curr_block) * UNFM_P_SIZE, 5951da177e4SLinus Torvalds 0 /* free space */ ); 5961da177e4SLinus Torvalds /* Find where such item should live in the tree */ 5971da177e4SLinus Torvalds res = search_item(inode->i_sb, &key, &path); 5981da177e4SLinus Torvalds if (res != ITEM_NOT_FOUND) { 5991da177e4SLinus Torvalds /* Well, if we have found such item already, or some error 6001da177e4SLinus Torvalds occured, we need to warn user and return error */ 6011da177e4SLinus Torvalds if (res != -ENOSPC) { 6021da177e4SLinus Torvalds reiserfs_warning(inode->i_sb, 6031da177e4SLinus Torvalds "green-9009: search_by_key (%K) " 604bd4c625cSLinus Torvalds "returned %d", &key, 605bd4c625cSLinus Torvalds res); 6061da177e4SLinus Torvalds } 6071da177e4SLinus Torvalds res = -EIO; 6081da177e4SLinus Torvalds goto error_exit_free_blocks; 6091da177e4SLinus Torvalds } 6101da177e4SLinus Torvalds /* Insert item into the tree with the data as its body */ 611bd4c625cSLinus Torvalds res = 612bd4c625cSLinus Torvalds reiserfs_insert_item(th, &path, &key, &ins_ih, 613bd4c625cSLinus Torvalds inode, 614bd4c625cSLinus Torvalds (char *)(allocated_blocks + 615bd4c625cSLinus Torvalds curr_block)); 6161da177e4SLinus Torvalds } else { 617bd4c625cSLinus Torvalds reiserfs_panic(inode->i_sb, 618bd4c625cSLinus Torvalds "green-9010: unexpected item type for key %K\n", 619bd4c625cSLinus Torvalds &key); 6201da177e4SLinus Torvalds } 6211da177e4SLinus Torvalds } 6221da177e4SLinus Torvalds // the caller is responsible for closing the transaction 6231da177e4SLinus Torvalds // unless we return an error, they are also responsible for logging 6241da177e4SLinus Torvalds // the inode. 6251da177e4SLinus Torvalds // 6261da177e4SLinus Torvalds pathrelse(&path); 6271da177e4SLinus Torvalds /* 6281da177e4SLinus Torvalds * cleanup prellocation from previous writes 6291da177e4SLinus Torvalds * if this is a partial block write 6301da177e4SLinus Torvalds */ 6311da177e4SLinus Torvalds if (write_bytes & (inode->i_sb->s_blocksize - 1)) 6321da177e4SLinus Torvalds reiserfs_discard_prealloc(th, inode); 6331da177e4SLinus Torvalds reiserfs_write_unlock(inode->i_sb); 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds // go through all the pages/buffers and map the buffers to newly allocated 6361da177e4SLinus Torvalds // blocks (so that system knows where to write these pages later). 6371da177e4SLinus Torvalds curr_block = 0; 6381da177e4SLinus Torvalds for (i = 0; i < num_pages; i++) { 6391da177e4SLinus Torvalds struct page *page = prepared_pages[i]; //current page 6401da177e4SLinus Torvalds struct buffer_head *head = page_buffers(page); // first buffer for a page 6411da177e4SLinus Torvalds int block_start, block_end; // in-page offsets for buffers. 6421da177e4SLinus Torvalds 6431da177e4SLinus Torvalds if (!page_buffers(page)) 644bd4c625cSLinus Torvalds reiserfs_panic(inode->i_sb, 645bd4c625cSLinus Torvalds "green-9005: No buffers for prepared page???"); 6461da177e4SLinus Torvalds 6471da177e4SLinus Torvalds /* For each buffer in page */ 6481da177e4SLinus Torvalds for (bh = head, block_start = 0; bh != head || !block_start; 6491da177e4SLinus Torvalds block_start = block_end, bh = bh->b_this_page) { 6501da177e4SLinus Torvalds if (!bh) 651bd4c625cSLinus Torvalds reiserfs_panic(inode->i_sb, 652bd4c625cSLinus Torvalds "green-9006: Allocated but absent buffer for a page?"); 6531da177e4SLinus Torvalds block_end = block_start + inode->i_sb->s_blocksize; 6541da177e4SLinus Torvalds if (i == 0 && block_end <= from) 6551da177e4SLinus Torvalds /* if this buffer is before requested data to map, skip it */ 6561da177e4SLinus Torvalds continue; 6571da177e4SLinus Torvalds if (i == num_pages - 1 && block_start >= to) 6581da177e4SLinus Torvalds /* If this buffer is after requested data to map, abort 6591da177e4SLinus Torvalds processing of current page */ 6601da177e4SLinus Torvalds break; 6611da177e4SLinus Torvalds 6621da177e4SLinus Torvalds if (!buffer_mapped(bh)) { // Ok, unmapped buffer, need to map it 663bd4c625cSLinus Torvalds map_bh(bh, inode->i_sb, 664bd4c625cSLinus Torvalds le32_to_cpu(allocated_blocks 665bd4c625cSLinus Torvalds [curr_block])); 6661da177e4SLinus Torvalds curr_block++; 6671da177e4SLinus Torvalds set_buffer_new(bh); 6681da177e4SLinus Torvalds } 6691da177e4SLinus Torvalds } 6701da177e4SLinus Torvalds } 6711da177e4SLinus Torvalds 672bd4c625cSLinus Torvalds RFALSE(curr_block > blocks_to_allocate, 673bd4c625cSLinus Torvalds "green-9007: Used too many blocks? weird"); 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds kfree(allocated_blocks); 6761da177e4SLinus Torvalds return 0; 6771da177e4SLinus Torvalds 6781da177e4SLinus Torvalds // Need to deal with transaction here. 6791da177e4SLinus Torvalds error_exit_free_blocks: 6801da177e4SLinus Torvalds pathrelse(&path); 6811da177e4SLinus Torvalds // free blocks 6821da177e4SLinus Torvalds for (i = 0; i < blocks_to_allocate; i++) 683bd4c625cSLinus Torvalds reiserfs_free_block(th, inode, le32_to_cpu(allocated_blocks[i]), 684bd4c625cSLinus Torvalds 1); 6851da177e4SLinus Torvalds 6861da177e4SLinus Torvalds error_exit: 6871da177e4SLinus Torvalds if (th->t_trans_id) { 6881da177e4SLinus Torvalds int err; 6891da177e4SLinus Torvalds // update any changes we made to blk count 6909f03783cSChris Mason mark_inode_dirty(inode); 691bd4c625cSLinus Torvalds err = 692bd4c625cSLinus Torvalds journal_end(th, inode->i_sb, 693bd4c625cSLinus Torvalds JOURNAL_PER_BALANCE_CNT * 3 + 1 + 694bd4c625cSLinus Torvalds 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb)); 6951da177e4SLinus Torvalds if (err) 6961da177e4SLinus Torvalds res = err; 6971da177e4SLinus Torvalds } 6981da177e4SLinus Torvalds reiserfs_write_unlock(inode->i_sb); 6991da177e4SLinus Torvalds kfree(allocated_blocks); 7001da177e4SLinus Torvalds 7011da177e4SLinus Torvalds return res; 7021da177e4SLinus Torvalds } 7031da177e4SLinus Torvalds 7041da177e4SLinus Torvalds /* Unlock pages prepared by reiserfs_prepare_file_region_for_write */ 7051da177e4SLinus Torvalds static void reiserfs_unprepare_pages(struct page **prepared_pages, /* list of locked pages */ 706bd4c625cSLinus Torvalds size_t num_pages /* amount of pages */ ) 707bd4c625cSLinus Torvalds { 7081da177e4SLinus Torvalds int i; // loop counter 7091da177e4SLinus Torvalds 7101da177e4SLinus Torvalds for (i = 0; i < num_pages; i++) { 7111da177e4SLinus Torvalds struct page *page = prepared_pages[i]; 7121da177e4SLinus Torvalds 7131da177e4SLinus Torvalds try_to_free_buffers(page); 7141da177e4SLinus Torvalds unlock_page(page); 7151da177e4SLinus Torvalds page_cache_release(page); 7161da177e4SLinus Torvalds } 7171da177e4SLinus Torvalds } 7181da177e4SLinus Torvalds 7191da177e4SLinus Torvalds /* This function will copy data from userspace to specified pages within 7201da177e4SLinus Torvalds supplied byte range */ 721bd4c625cSLinus Torvalds static int reiserfs_copy_from_user_to_file_region(loff_t pos, /* In-file position */ 7221da177e4SLinus Torvalds int num_pages, /* Number of pages affected */ 7231da177e4SLinus Torvalds int write_bytes, /* Amount of bytes to write */ 7241da177e4SLinus Torvalds struct page **prepared_pages, /* pointer to 7251da177e4SLinus Torvalds array to 7261da177e4SLinus Torvalds prepared pages 7271da177e4SLinus Torvalds */ 7281da177e4SLinus Torvalds const char __user * buf /* Pointer to user-supplied 7291da177e4SLinus Torvalds data */ 7301da177e4SLinus Torvalds ) 7311da177e4SLinus Torvalds { 7321da177e4SLinus Torvalds long page_fault = 0; // status of copy_from_user. 7331da177e4SLinus Torvalds int i; // loop counter. 7341da177e4SLinus Torvalds int offset; // offset in page 7351da177e4SLinus Torvalds 736bd4c625cSLinus Torvalds for (i = 0, offset = (pos & (PAGE_CACHE_SIZE - 1)); i < num_pages; 737bd4c625cSLinus Torvalds i++, offset = 0) { 7381da177e4SLinus Torvalds size_t count = min_t(size_t, PAGE_CACHE_SIZE - offset, write_bytes); // How much of bytes to write to this page 7391da177e4SLinus Torvalds struct page *page = prepared_pages[i]; // Current page we process. 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds fault_in_pages_readable(buf, count); 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds /* Copy data from userspace to the current page */ 7441da177e4SLinus Torvalds kmap(page); 7451da177e4SLinus Torvalds page_fault = __copy_from_user(page_address(page) + offset, buf, count); // Copy the data. 7461da177e4SLinus Torvalds /* Flush processor's dcache for this page */ 7471da177e4SLinus Torvalds flush_dcache_page(page); 7481da177e4SLinus Torvalds kunmap(page); 7491da177e4SLinus Torvalds buf += count; 7501da177e4SLinus Torvalds write_bytes -= count; 7511da177e4SLinus Torvalds 7521da177e4SLinus Torvalds if (page_fault) 7531da177e4SLinus Torvalds break; // Was there a fault? abort. 7541da177e4SLinus Torvalds } 7551da177e4SLinus Torvalds 7561da177e4SLinus Torvalds return page_fault ? -EFAULT : 0; 7571da177e4SLinus Torvalds } 7581da177e4SLinus Torvalds 7591da177e4SLinus Torvalds /* taken fs/buffer.c:__block_commit_write */ 7601da177e4SLinus Torvalds int reiserfs_commit_page(struct inode *inode, struct page *page, 7611da177e4SLinus Torvalds unsigned from, unsigned to) 7621da177e4SLinus Torvalds { 7631da177e4SLinus Torvalds unsigned block_start, block_end; 7641da177e4SLinus Torvalds int partial = 0; 7651da177e4SLinus Torvalds unsigned blocksize; 7661da177e4SLinus Torvalds struct buffer_head *bh, *head; 7671da177e4SLinus Torvalds unsigned long i_size_index = inode->i_size >> PAGE_CACHE_SHIFT; 7681da177e4SLinus Torvalds int new; 7691da177e4SLinus Torvalds int logit = reiserfs_file_data_log(inode); 7701da177e4SLinus Torvalds struct super_block *s = inode->i_sb; 7711da177e4SLinus Torvalds int bh_per_page = PAGE_CACHE_SIZE / s->s_blocksize; 7721da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 7731da177e4SLinus Torvalds int ret = 0; 7741da177e4SLinus Torvalds 7751da177e4SLinus Torvalds th.t_trans_id = 0; 7761da177e4SLinus Torvalds blocksize = 1 << inode->i_blkbits; 7771da177e4SLinus Torvalds 7781da177e4SLinus Torvalds if (logit) { 7791da177e4SLinus Torvalds reiserfs_write_lock(s); 7801da177e4SLinus Torvalds ret = journal_begin(&th, s, bh_per_page + 1); 7811da177e4SLinus Torvalds if (ret) 7821da177e4SLinus Torvalds goto drop_write_lock; 7831da177e4SLinus Torvalds reiserfs_update_inode_transaction(inode); 7841da177e4SLinus Torvalds } 7851da177e4SLinus Torvalds for (bh = head = page_buffers(page), block_start = 0; 7861da177e4SLinus Torvalds bh != head || !block_start; 787bd4c625cSLinus Torvalds block_start = block_end, bh = bh->b_this_page) { 7881da177e4SLinus Torvalds 7891da177e4SLinus Torvalds new = buffer_new(bh); 7901da177e4SLinus Torvalds clear_buffer_new(bh); 7911da177e4SLinus Torvalds block_end = block_start + blocksize; 7921da177e4SLinus Torvalds if (block_end <= from || block_start >= to) { 7931da177e4SLinus Torvalds if (!buffer_uptodate(bh)) 7941da177e4SLinus Torvalds partial = 1; 7951da177e4SLinus Torvalds } else { 7961da177e4SLinus Torvalds set_buffer_uptodate(bh); 7971da177e4SLinus Torvalds if (logit) { 7981da177e4SLinus Torvalds reiserfs_prepare_for_journal(s, bh, 1); 7991da177e4SLinus Torvalds journal_mark_dirty(&th, s, bh); 8001da177e4SLinus Torvalds } else if (!buffer_dirty(bh)) { 8011da177e4SLinus Torvalds mark_buffer_dirty(bh); 8021da177e4SLinus Torvalds /* do data=ordered on any page past the end 8031da177e4SLinus Torvalds * of file and any buffer marked BH_New. 8041da177e4SLinus Torvalds */ 8051da177e4SLinus Torvalds if (reiserfs_data_ordered(inode->i_sb) && 8061da177e4SLinus Torvalds (new || page->index >= i_size_index)) { 8071da177e4SLinus Torvalds reiserfs_add_ordered_list(inode, bh); 8081da177e4SLinus Torvalds } 8091da177e4SLinus Torvalds } 8101da177e4SLinus Torvalds } 8111da177e4SLinus Torvalds } 8121da177e4SLinus Torvalds if (logit) { 8131da177e4SLinus Torvalds ret = journal_end(&th, s, bh_per_page + 1); 8141da177e4SLinus Torvalds drop_write_lock: 8151da177e4SLinus Torvalds reiserfs_write_unlock(s); 8161da177e4SLinus Torvalds } 8171da177e4SLinus Torvalds /* 8181da177e4SLinus Torvalds * If this is a partial write which happened to make all buffers 8191da177e4SLinus Torvalds * uptodate then we can optimize away a bogus readpage() for 8201da177e4SLinus Torvalds * the next read(). Here we 'discover' whether the page went 8211da177e4SLinus Torvalds * uptodate as a result of this (potentially partial) write. 8221da177e4SLinus Torvalds */ 8231da177e4SLinus Torvalds if (!partial) 8241da177e4SLinus Torvalds SetPageUptodate(page); 8251da177e4SLinus Torvalds return ret; 8261da177e4SLinus Torvalds } 8271da177e4SLinus Torvalds 8281da177e4SLinus Torvalds /* Submit pages for write. This was separated from actual file copying 8291da177e4SLinus Torvalds because we might want to allocate block numbers in-between. 8301da177e4SLinus Torvalds This function assumes that caller will adjust file size to correct value. */ 831bd4c625cSLinus Torvalds static int reiserfs_submit_file_region_for_write(struct reiserfs_transaction_handle *th, struct inode *inode, loff_t pos, /* Writing position offset */ 8321da177e4SLinus Torvalds size_t num_pages, /* Number of pages to write */ 8331da177e4SLinus Torvalds size_t write_bytes, /* number of bytes to write */ 8341da177e4SLinus Torvalds struct page **prepared_pages /* list of pages */ 8351da177e4SLinus Torvalds ) 8361da177e4SLinus Torvalds { 8371da177e4SLinus Torvalds int status; // return status of block_commit_write. 8381da177e4SLinus Torvalds int retval = 0; // Return value we are going to return. 8391da177e4SLinus Torvalds int i; // loop counter 8401da177e4SLinus Torvalds int offset; // Writing offset in page. 8411da177e4SLinus Torvalds int orig_write_bytes = write_bytes; 8421da177e4SLinus Torvalds int sd_update = 0; 8431da177e4SLinus Torvalds 844bd4c625cSLinus Torvalds for (i = 0, offset = (pos & (PAGE_CACHE_SIZE - 1)); i < num_pages; 845bd4c625cSLinus Torvalds i++, offset = 0) { 8461da177e4SLinus Torvalds int count = min_t(int, PAGE_CACHE_SIZE - offset, write_bytes); // How much of bytes to write to this page 8471da177e4SLinus Torvalds struct page *page = prepared_pages[i]; // Current page we process. 8481da177e4SLinus Torvalds 849bd4c625cSLinus Torvalds status = 850bd4c625cSLinus Torvalds reiserfs_commit_page(inode, page, offset, offset + count); 8511da177e4SLinus Torvalds if (status) 8521da177e4SLinus Torvalds retval = status; // To not overcomplicate matters We are going to 8531da177e4SLinus Torvalds // submit all the pages even if there was error. 8541da177e4SLinus Torvalds // we only remember error status to report it on 8551da177e4SLinus Torvalds // exit. 8561da177e4SLinus Torvalds write_bytes -= count; 8571da177e4SLinus Torvalds } 8581da177e4SLinus Torvalds /* now that we've gotten all the ordered buffers marked dirty, 8591da177e4SLinus Torvalds * we can safely update i_size and close any running transaction 8601da177e4SLinus Torvalds */ 8611da177e4SLinus Torvalds if (pos + orig_write_bytes > inode->i_size) { 8621da177e4SLinus Torvalds inode->i_size = pos + orig_write_bytes; // Set new size 8631da177e4SLinus Torvalds /* If the file have grown so much that tail packing is no 8641da177e4SLinus Torvalds * longer possible, reset "need to pack" flag */ 8651da177e4SLinus Torvalds if ((have_large_tails(inode->i_sb) && 8661da177e4SLinus Torvalds inode->i_size > i_block_size(inode) * 4) || 8671da177e4SLinus Torvalds (have_small_tails(inode->i_sb) && 8681da177e4SLinus Torvalds inode->i_size > i_block_size(inode))) 8691da177e4SLinus Torvalds REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; 8701da177e4SLinus Torvalds else if ((have_large_tails(inode->i_sb) && 8711da177e4SLinus Torvalds inode->i_size < i_block_size(inode) * 4) || 8721da177e4SLinus Torvalds (have_small_tails(inode->i_sb) && 8731da177e4SLinus Torvalds inode->i_size < i_block_size(inode))) 8741da177e4SLinus Torvalds REISERFS_I(inode)->i_flags |= i_pack_on_close_mask; 8751da177e4SLinus Torvalds 8761da177e4SLinus Torvalds if (th->t_trans_id) { 8771da177e4SLinus Torvalds reiserfs_write_lock(inode->i_sb); 8789f03783cSChris Mason // this sets the proper flags for O_SYNC to trigger a commit 8799f03783cSChris Mason mark_inode_dirty(inode); 8801da177e4SLinus Torvalds reiserfs_write_unlock(inode->i_sb); 88173ce5934SHisashi Hifumi } else { 88273ce5934SHisashi Hifumi reiserfs_write_lock(inode->i_sb); 88373ce5934SHisashi Hifumi reiserfs_update_inode_transaction(inode); 8849f03783cSChris Mason mark_inode_dirty(inode); 88573ce5934SHisashi Hifumi reiserfs_write_unlock(inode->i_sb); 88673ce5934SHisashi Hifumi } 8871da177e4SLinus Torvalds 8881da177e4SLinus Torvalds sd_update = 1; 8891da177e4SLinus Torvalds } 8901da177e4SLinus Torvalds if (th->t_trans_id) { 8911da177e4SLinus Torvalds reiserfs_write_lock(inode->i_sb); 8921da177e4SLinus Torvalds if (!sd_update) 8939f03783cSChris Mason mark_inode_dirty(inode); 8941da177e4SLinus Torvalds status = journal_end(th, th->t_super, th->t_blocks_allocated); 8951da177e4SLinus Torvalds if (status) 8961da177e4SLinus Torvalds retval = status; 8971da177e4SLinus Torvalds reiserfs_write_unlock(inode->i_sb); 8981da177e4SLinus Torvalds } 8991da177e4SLinus Torvalds th->t_trans_id = 0; 9001da177e4SLinus Torvalds 9011da177e4SLinus Torvalds /* 9021da177e4SLinus Torvalds * we have to unlock the pages after updating i_size, otherwise 9031da177e4SLinus Torvalds * we race with writepage 9041da177e4SLinus Torvalds */ 9051da177e4SLinus Torvalds for (i = 0; i < num_pages; i++) { 9061da177e4SLinus Torvalds struct page *page = prepared_pages[i]; 9071da177e4SLinus Torvalds unlock_page(page); 9081da177e4SLinus Torvalds mark_page_accessed(page); 9091da177e4SLinus Torvalds page_cache_release(page); 9101da177e4SLinus Torvalds } 9111da177e4SLinus Torvalds return retval; 9121da177e4SLinus Torvalds } 9131da177e4SLinus Torvalds 9141da177e4SLinus Torvalds /* Look if passed writing region is going to touch file's tail 9151da177e4SLinus Torvalds (if it is present). And if it is, convert the tail to unformatted node */ 9161da177e4SLinus Torvalds static int reiserfs_check_for_tail_and_convert(struct inode *inode, /* inode to deal with */ 9171da177e4SLinus Torvalds loff_t pos, /* Writing position */ 9181da177e4SLinus Torvalds int write_bytes /* amount of bytes to write */ 9191da177e4SLinus Torvalds ) 9201da177e4SLinus Torvalds { 9211da177e4SLinus Torvalds INITIALIZE_PATH(path); // needed for search_for_position 9221da177e4SLinus Torvalds struct cpu_key key; // Key that would represent last touched writing byte. 9231da177e4SLinus Torvalds struct item_head *ih; // item header of found block; 9241da177e4SLinus Torvalds int res; // Return value of various functions we call. 9251da177e4SLinus Torvalds int cont_expand_offset; // We will put offset for generic_cont_expand here 9261da177e4SLinus Torvalds // This can be int just because tails are created 9271da177e4SLinus Torvalds // only for small files. 9281da177e4SLinus Torvalds 9291da177e4SLinus Torvalds /* this embodies a dependency on a particular tail policy */ 9301da177e4SLinus Torvalds if (inode->i_size >= inode->i_sb->s_blocksize * 4) { 9311da177e4SLinus Torvalds /* such a big files do not have tails, so we won't bother ourselves 9321da177e4SLinus Torvalds to look for tails, simply return */ 9331da177e4SLinus Torvalds return 0; 9341da177e4SLinus Torvalds } 9351da177e4SLinus Torvalds 9361da177e4SLinus Torvalds reiserfs_write_lock(inode->i_sb); 9371da177e4SLinus Torvalds /* find the item containing the last byte to be written, or if 9381da177e4SLinus Torvalds * writing past the end of the file then the last item of the 9391da177e4SLinus Torvalds * file (and then we check its type). */ 940bd4c625cSLinus Torvalds make_cpu_key(&key, inode, pos + write_bytes + 1, TYPE_ANY, 941bd4c625cSLinus Torvalds 3 /*key length */ ); 9421da177e4SLinus Torvalds res = search_for_position_by_key(inode->i_sb, &key, &path); 9431da177e4SLinus Torvalds if (res == IO_ERROR) { 9441da177e4SLinus Torvalds reiserfs_write_unlock(inode->i_sb); 9451da177e4SLinus Torvalds return -EIO; 9461da177e4SLinus Torvalds } 9471da177e4SLinus Torvalds ih = get_ih(&path); 9481da177e4SLinus Torvalds res = 0; 9491da177e4SLinus Torvalds if (is_direct_le_ih(ih)) { 9501da177e4SLinus Torvalds /* Ok, closest item is file tail (tails are stored in "direct" 9511da177e4SLinus Torvalds * items), so we need to unpack it. */ 9521da177e4SLinus Torvalds /* To not overcomplicate matters, we just call generic_cont_expand 9531da177e4SLinus Torvalds which will in turn call other stuff and finally will boil down to 9541da177e4SLinus Torvalds reiserfs_get_block() that would do necessary conversion. */ 955bd4c625cSLinus Torvalds cont_expand_offset = 956bd4c625cSLinus Torvalds le_key_k_offset(get_inode_item_key_version(inode), 957bd4c625cSLinus Torvalds &(ih->ih_key)); 9581da177e4SLinus Torvalds pathrelse(&path); 9591da177e4SLinus Torvalds res = generic_cont_expand(inode, cont_expand_offset); 9601da177e4SLinus Torvalds } else 9611da177e4SLinus Torvalds pathrelse(&path); 9621da177e4SLinus Torvalds 9631da177e4SLinus Torvalds reiserfs_write_unlock(inode->i_sb); 9641da177e4SLinus Torvalds return res; 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds 9671da177e4SLinus Torvalds /* This function locks pages starting from @pos for @inode. 9681da177e4SLinus Torvalds @num_pages pages are locked and stored in 9691da177e4SLinus Torvalds @prepared_pages array. Also buffers are allocated for these pages. 9701da177e4SLinus Torvalds First and last page of the region is read if it is overwritten only 9711da177e4SLinus Torvalds partially. If last page did not exist before write (file hole or file 9721da177e4SLinus Torvalds append), it is zeroed, then. 9731da177e4SLinus Torvalds Returns number of unallocated blocks that should be allocated to cover 9741da177e4SLinus Torvalds new file data.*/ 975bd4c625cSLinus Torvalds static int reiserfs_prepare_file_region_for_write(struct inode *inode 976bd4c625cSLinus Torvalds /* Inode of the file */ , 9771da177e4SLinus Torvalds loff_t pos, /* position in the file */ 9781da177e4SLinus Torvalds size_t num_pages, /* number of pages to 9791da177e4SLinus Torvalds prepare */ 9801da177e4SLinus Torvalds size_t write_bytes, /* Amount of bytes to be 9811da177e4SLinus Torvalds overwritten from 9821da177e4SLinus Torvalds @pos */ 9831da177e4SLinus Torvalds struct page **prepared_pages /* pointer to array 9841da177e4SLinus Torvalds where to store 9851da177e4SLinus Torvalds prepared pages */ 9861da177e4SLinus Torvalds ) 9871da177e4SLinus Torvalds { 9881da177e4SLinus Torvalds int res = 0; // Return values of different functions we call. 9891da177e4SLinus Torvalds unsigned long index = pos >> PAGE_CACHE_SHIFT; // Offset in file in pages. 9901da177e4SLinus Torvalds int from = (pos & (PAGE_CACHE_SIZE - 1)); // Writing offset in first page 9911da177e4SLinus Torvalds int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1; 9921da177e4SLinus Torvalds /* offset of last modified byte in last 9931da177e4SLinus Torvalds page */ 9941da177e4SLinus Torvalds struct address_space *mapping = inode->i_mapping; // Pages are mapped here. 9951da177e4SLinus Torvalds int i; // Simple counter 9961da177e4SLinus Torvalds int blocks = 0; /* Return value (blocks that should be allocated) */ 9971da177e4SLinus Torvalds struct buffer_head *bh, *head; // Current bufferhead and first bufferhead 9981da177e4SLinus Torvalds // of a page. 9991da177e4SLinus Torvalds unsigned block_start, block_end; // Starting and ending offsets of current 10001da177e4SLinus Torvalds // buffer in the page. 10011da177e4SLinus Torvalds struct buffer_head *wait[2], **wait_bh = wait; // Buffers for page, if 10021da177e4SLinus Torvalds // Page appeared to be not up 10031da177e4SLinus Torvalds // to date. Note how we have 10041da177e4SLinus Torvalds // at most 2 buffers, this is 10051da177e4SLinus Torvalds // because we at most may 10061da177e4SLinus Torvalds // partially overwrite two 10071da177e4SLinus Torvalds // buffers for one page. One at // the beginning of write area 10081da177e4SLinus Torvalds // and one at the end. 10091da177e4SLinus Torvalds // Everything inthe middle gets // overwritten totally. 10101da177e4SLinus Torvalds 10111da177e4SLinus Torvalds struct cpu_key key; // cpu key of item that we are going to deal with 10121da177e4SLinus Torvalds struct item_head *ih = NULL; // pointer to item head that we are going to deal with 10131da177e4SLinus Torvalds struct buffer_head *itembuf = NULL; // Buffer head that contains items that we are going to deal with 10141da177e4SLinus Torvalds INITIALIZE_PATH(path); // path to item, that we are going to deal with. 10153e8962beSAl Viro __le32 *item = NULL; // pointer to item we are going to deal with 10161da177e4SLinus Torvalds int item_pos = -1; /* Position in indirect item */ 10171da177e4SLinus Torvalds 10181da177e4SLinus Torvalds if (num_pages < 1) { 10191da177e4SLinus Torvalds reiserfs_warning(inode->i_sb, 10201da177e4SLinus Torvalds "green-9001: reiserfs_prepare_file_region_for_write " 10211da177e4SLinus Torvalds "called with zero number of pages to process"); 10221da177e4SLinus Torvalds return -EFAULT; 10231da177e4SLinus Torvalds } 10241da177e4SLinus Torvalds 10251da177e4SLinus Torvalds /* We have 2 loops for pages. In first loop we grab and lock the pages, so 10261da177e4SLinus Torvalds that nobody would touch these until we release the pages. Then 10271da177e4SLinus Torvalds we'd start to deal with mapping buffers to blocks. */ 10281da177e4SLinus Torvalds for (i = 0; i < num_pages; i++) { 10291da177e4SLinus Torvalds prepared_pages[i] = grab_cache_page(mapping, index + i); // locks the page 10301da177e4SLinus Torvalds if (!prepared_pages[i]) { 10311da177e4SLinus Torvalds res = -ENOMEM; 10321da177e4SLinus Torvalds goto failed_page_grabbing; 10331da177e4SLinus Torvalds } 10341da177e4SLinus Torvalds if (!page_has_buffers(prepared_pages[i])) 1035bd4c625cSLinus Torvalds create_empty_buffers(prepared_pages[i], 1036bd4c625cSLinus Torvalds inode->i_sb->s_blocksize, 0); 10371da177e4SLinus Torvalds } 10381da177e4SLinus Torvalds 10391da177e4SLinus Torvalds /* Let's count amount of blocks for a case where all the blocks 10401da177e4SLinus Torvalds overwritten are new (we will substract already allocated blocks later) */ 10411da177e4SLinus Torvalds if (num_pages > 2) 10421da177e4SLinus Torvalds /* These are full-overwritten pages so we count all the blocks in 10431da177e4SLinus Torvalds these pages are counted as needed to be allocated */ 1044bd4c625cSLinus Torvalds blocks = 1045bd4c625cSLinus Torvalds (num_pages - 2) << (PAGE_CACHE_SHIFT - inode->i_blkbits); 10461da177e4SLinus Torvalds 10471da177e4SLinus Torvalds /* count blocks needed for first page (possibly partially written) */ 1048bd4c625cSLinus Torvalds blocks += ((PAGE_CACHE_SIZE - from) >> inode->i_blkbits) + !!(from & (inode->i_sb->s_blocksize - 1)); /* roundup */ 10491da177e4SLinus Torvalds 10501da177e4SLinus Torvalds /* Now we account for last page. If last page == first page (we 10511da177e4SLinus Torvalds overwrite only one page), we substract all the blocks past the 10521da177e4SLinus Torvalds last writing position in a page out of already calculated number 10531da177e4SLinus Torvalds of blocks */ 10541da177e4SLinus Torvalds blocks += ((num_pages > 1) << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 10551da177e4SLinus Torvalds ((PAGE_CACHE_SIZE - to) >> inode->i_blkbits); 10561da177e4SLinus Torvalds /* Note how we do not roundup here since partial blocks still 10571da177e4SLinus Torvalds should be allocated */ 10581da177e4SLinus Torvalds 10591da177e4SLinus Torvalds /* Now if all the write area lies past the file end, no point in 10601da177e4SLinus Torvalds maping blocks, since there is none, so we just zero out remaining 10611da177e4SLinus Torvalds parts of first and last pages in write area (if needed) */ 10621da177e4SLinus Torvalds if ((pos & ~((loff_t) PAGE_CACHE_SIZE - 1)) > inode->i_size) { 10631da177e4SLinus Torvalds if (from != 0) { /* First page needs to be partially zeroed */ 10641da177e4SLinus Torvalds char *kaddr = kmap_atomic(prepared_pages[0], KM_USER0); 10651da177e4SLinus Torvalds memset(kaddr, 0, from); 10661da177e4SLinus Torvalds kunmap_atomic(kaddr, KM_USER0); 1067de21c57bSAlexey Dobriyan flush_dcache_page(prepared_pages[0]); 10681da177e4SLinus Torvalds } 10691da177e4SLinus Torvalds if (to != PAGE_CACHE_SIZE) { /* Last page needs to be partially zeroed */ 1070bd4c625cSLinus Torvalds char *kaddr = 1071bd4c625cSLinus Torvalds kmap_atomic(prepared_pages[num_pages - 1], 1072bd4c625cSLinus Torvalds KM_USER0); 10731da177e4SLinus Torvalds memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); 10741da177e4SLinus Torvalds kunmap_atomic(kaddr, KM_USER0); 1075de21c57bSAlexey Dobriyan flush_dcache_page(prepared_pages[num_pages - 1]); 10761da177e4SLinus Torvalds } 10771da177e4SLinus Torvalds 10781da177e4SLinus Torvalds /* Since all blocks are new - use already calculated value */ 10791da177e4SLinus Torvalds return blocks; 10801da177e4SLinus Torvalds } 10811da177e4SLinus Torvalds 10821da177e4SLinus Torvalds /* Well, since we write somewhere into the middle of a file, there is 10831da177e4SLinus Torvalds possibility we are writing over some already allocated blocks, so 10841da177e4SLinus Torvalds let's map these blocks and substract number of such blocks out of blocks 10851da177e4SLinus Torvalds we need to allocate (calculated above) */ 10861da177e4SLinus Torvalds /* Mask write position to start on blocksize, we do it out of the 10871da177e4SLinus Torvalds loop for performance reasons */ 10881da177e4SLinus Torvalds pos &= ~((loff_t) inode->i_sb->s_blocksize - 1); 10891da177e4SLinus Torvalds /* Set cpu key to the starting position in a file (on left block boundary) */ 1090bd4c625cSLinus Torvalds make_cpu_key(&key, inode, 1091bd4c625cSLinus Torvalds 1 + ((pos) & ~((loff_t) inode->i_sb->s_blocksize - 1)), 1092bd4c625cSLinus Torvalds TYPE_ANY, 3 /*key length */ ); 10931da177e4SLinus Torvalds 10941da177e4SLinus Torvalds reiserfs_write_lock(inode->i_sb); // We need that for at least search_by_key() 10951da177e4SLinus Torvalds for (i = 0; i < num_pages; i++) { 10961da177e4SLinus Torvalds 10971da177e4SLinus Torvalds head = page_buffers(prepared_pages[i]); 10981da177e4SLinus Torvalds /* For each buffer in the page */ 10991da177e4SLinus Torvalds for (bh = head, block_start = 0; bh != head || !block_start; 11001da177e4SLinus Torvalds block_start = block_end, bh = bh->b_this_page) { 11011da177e4SLinus Torvalds if (!bh) 1102bd4c625cSLinus Torvalds reiserfs_panic(inode->i_sb, 1103bd4c625cSLinus Torvalds "green-9002: Allocated but absent buffer for a page?"); 11041da177e4SLinus Torvalds /* Find where this buffer ends */ 11051da177e4SLinus Torvalds block_end = block_start + inode->i_sb->s_blocksize; 11061da177e4SLinus Torvalds if (i == 0 && block_end <= from) 11071da177e4SLinus Torvalds /* if this buffer is before requested data to map, skip it */ 11081da177e4SLinus Torvalds continue; 11091da177e4SLinus Torvalds 11101da177e4SLinus Torvalds if (i == num_pages - 1 && block_start >= to) { 11111da177e4SLinus Torvalds /* If this buffer is after requested data to map, abort 11121da177e4SLinus Torvalds processing of current page */ 11131da177e4SLinus Torvalds break; 11141da177e4SLinus Torvalds } 11151da177e4SLinus Torvalds 11161da177e4SLinus Torvalds if (buffer_mapped(bh) && bh->b_blocknr != 0) { 11171da177e4SLinus Torvalds /* This is optimisation for a case where buffer is mapped 11181da177e4SLinus Torvalds and have blocknumber assigned. In case significant amount 11191da177e4SLinus Torvalds of such buffers are present, we may avoid some amount 11201da177e4SLinus Torvalds of search_by_key calls. 11211da177e4SLinus Torvalds Probably it would be possible to move parts of this code 11221da177e4SLinus Torvalds out of BKL, but I afraid that would overcomplicate code 11231da177e4SLinus Torvalds without any noticeable benefit. 11241da177e4SLinus Torvalds */ 11251da177e4SLinus Torvalds item_pos++; 11261da177e4SLinus Torvalds /* Update the key */ 1127bd4c625cSLinus Torvalds set_cpu_key_k_offset(&key, 1128bd4c625cSLinus Torvalds cpu_key_k_offset(&key) + 1129bd4c625cSLinus Torvalds inode->i_sb->s_blocksize); 11301da177e4SLinus Torvalds blocks--; // Decrease the amount of blocks that need to be 11311da177e4SLinus Torvalds // allocated 11321da177e4SLinus Torvalds continue; // Go to the next buffer 11331da177e4SLinus Torvalds } 11341da177e4SLinus Torvalds 11351da177e4SLinus Torvalds if (!itembuf || /* if first iteration */ 1136bd4c625cSLinus Torvalds item_pos >= ih_item_len(ih) / UNFM_P_SIZE) { /* or if we progressed past the 11371da177e4SLinus Torvalds current unformatted_item */ 11381da177e4SLinus Torvalds /* Try to find next item */ 1139bd4c625cSLinus Torvalds res = 1140bd4c625cSLinus Torvalds search_for_position_by_key(inode->i_sb, 1141bd4c625cSLinus Torvalds &key, &path); 11421da177e4SLinus Torvalds /* Abort if no more items */ 11431da177e4SLinus Torvalds if (res != POSITION_FOUND) { 11441da177e4SLinus Torvalds /* make sure later loops don't use this item */ 11451da177e4SLinus Torvalds itembuf = NULL; 11461da177e4SLinus Torvalds item = NULL; 11471da177e4SLinus Torvalds break; 11481da177e4SLinus Torvalds } 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvalds /* Update information about current indirect item */ 11511da177e4SLinus Torvalds itembuf = get_last_bh(&path); 11521da177e4SLinus Torvalds ih = get_ih(&path); 11531da177e4SLinus Torvalds item = get_item(&path); 11541da177e4SLinus Torvalds item_pos = path.pos_in_item; 11551da177e4SLinus Torvalds 1156bd4c625cSLinus Torvalds RFALSE(!is_indirect_le_ih(ih), 1157bd4c625cSLinus Torvalds "green-9003: indirect item expected"); 11581da177e4SLinus Torvalds } 11591da177e4SLinus Torvalds 11601da177e4SLinus Torvalds /* See if there is some block associated with the file 11611da177e4SLinus Torvalds at that position, map the buffer to this block */ 11621da177e4SLinus Torvalds if (get_block_num(item, item_pos)) { 1163bd4c625cSLinus Torvalds map_bh(bh, inode->i_sb, 1164bd4c625cSLinus Torvalds get_block_num(item, item_pos)); 11651da177e4SLinus Torvalds blocks--; // Decrease the amount of blocks that need to be 11661da177e4SLinus Torvalds // allocated 11671da177e4SLinus Torvalds } 11681da177e4SLinus Torvalds item_pos++; 11691da177e4SLinus Torvalds /* Update the key */ 1170bd4c625cSLinus Torvalds set_cpu_key_k_offset(&key, 1171bd4c625cSLinus Torvalds cpu_key_k_offset(&key) + 1172bd4c625cSLinus Torvalds inode->i_sb->s_blocksize); 11731da177e4SLinus Torvalds } 11741da177e4SLinus Torvalds } 11751da177e4SLinus Torvalds pathrelse(&path); // Free the path 11761da177e4SLinus Torvalds reiserfs_write_unlock(inode->i_sb); 11771da177e4SLinus Torvalds 11781da177e4SLinus Torvalds /* Now zero out unmappend buffers for the first and last pages of 11791da177e4SLinus Torvalds write area or issue read requests if page is mapped. */ 11801da177e4SLinus Torvalds /* First page, see if it is not uptodate */ 11811da177e4SLinus Torvalds if (!PageUptodate(prepared_pages[0])) { 11821da177e4SLinus Torvalds head = page_buffers(prepared_pages[0]); 11831da177e4SLinus Torvalds 11841da177e4SLinus Torvalds /* For each buffer in page */ 11851da177e4SLinus Torvalds for (bh = head, block_start = 0; bh != head || !block_start; 11861da177e4SLinus Torvalds block_start = block_end, bh = bh->b_this_page) { 11871da177e4SLinus Torvalds 11881da177e4SLinus Torvalds if (!bh) 1189bd4c625cSLinus Torvalds reiserfs_panic(inode->i_sb, 1190bd4c625cSLinus Torvalds "green-9002: Allocated but absent buffer for a page?"); 11911da177e4SLinus Torvalds /* Find where this buffer ends */ 11921da177e4SLinus Torvalds block_end = block_start + inode->i_sb->s_blocksize; 11931da177e4SLinus Torvalds if (block_end <= from) 11941da177e4SLinus Torvalds /* if this buffer is before requested data to map, skip it */ 11951da177e4SLinus Torvalds continue; 11961da177e4SLinus Torvalds if (block_start < from) { /* Aha, our partial buffer */ 11971da177e4SLinus Torvalds if (buffer_mapped(bh)) { /* If it is mapped, we need to 11981da177e4SLinus Torvalds issue READ request for it to 11991da177e4SLinus Torvalds not loose data */ 12001da177e4SLinus Torvalds ll_rw_block(READ, 1, &bh); 12011da177e4SLinus Torvalds *wait_bh++ = bh; 12021da177e4SLinus Torvalds } else { /* Not mapped, zero it */ 1203bd4c625cSLinus Torvalds char *kaddr = 1204bd4c625cSLinus Torvalds kmap_atomic(prepared_pages[0], 1205bd4c625cSLinus Torvalds KM_USER0); 1206bd4c625cSLinus Torvalds memset(kaddr + block_start, 0, 1207bd4c625cSLinus Torvalds from - block_start); 12081da177e4SLinus Torvalds kunmap_atomic(kaddr, KM_USER0); 1209de21c57bSAlexey Dobriyan flush_dcache_page(prepared_pages[0]); 12101da177e4SLinus Torvalds set_buffer_uptodate(bh); 12111da177e4SLinus Torvalds } 12121da177e4SLinus Torvalds } 12131da177e4SLinus Torvalds } 12141da177e4SLinus Torvalds } 12151da177e4SLinus Torvalds 12161da177e4SLinus Torvalds /* Last page, see if it is not uptodate, or if the last page is past the end of the file. */ 12171da177e4SLinus Torvalds if (!PageUptodate(prepared_pages[num_pages - 1]) || 1218bd4c625cSLinus Torvalds ((pos + write_bytes) >> PAGE_CACHE_SHIFT) > 1219bd4c625cSLinus Torvalds (inode->i_size >> PAGE_CACHE_SHIFT)) { 12201da177e4SLinus Torvalds head = page_buffers(prepared_pages[num_pages - 1]); 12211da177e4SLinus Torvalds 12221da177e4SLinus Torvalds /* for each buffer in page */ 12231da177e4SLinus Torvalds for (bh = head, block_start = 0; bh != head || !block_start; 12241da177e4SLinus Torvalds block_start = block_end, bh = bh->b_this_page) { 12251da177e4SLinus Torvalds 12261da177e4SLinus Torvalds if (!bh) 1227bd4c625cSLinus Torvalds reiserfs_panic(inode->i_sb, 1228bd4c625cSLinus Torvalds "green-9002: Allocated but absent buffer for a page?"); 12291da177e4SLinus Torvalds /* Find where this buffer ends */ 12301da177e4SLinus Torvalds block_end = block_start + inode->i_sb->s_blocksize; 12311da177e4SLinus Torvalds if (block_start >= to) 12321da177e4SLinus Torvalds /* if this buffer is after requested data to map, skip it */ 12331da177e4SLinus Torvalds break; 12341da177e4SLinus Torvalds if (block_end > to) { /* Aha, our partial buffer */ 12351da177e4SLinus Torvalds if (buffer_mapped(bh)) { /* If it is mapped, we need to 12361da177e4SLinus Torvalds issue READ request for it to 12371da177e4SLinus Torvalds not loose data */ 12381da177e4SLinus Torvalds ll_rw_block(READ, 1, &bh); 12391da177e4SLinus Torvalds *wait_bh++ = bh; 12401da177e4SLinus Torvalds } else { /* Not mapped, zero it */ 1241bd4c625cSLinus Torvalds char *kaddr = 1242bd4c625cSLinus Torvalds kmap_atomic(prepared_pages 1243bd4c625cSLinus Torvalds [num_pages - 1], 1244bd4c625cSLinus Torvalds KM_USER0); 12451da177e4SLinus Torvalds memset(kaddr + to, 0, block_end - to); 12461da177e4SLinus Torvalds kunmap_atomic(kaddr, KM_USER0); 1247de21c57bSAlexey Dobriyan flush_dcache_page(prepared_pages[num_pages - 1]); 12481da177e4SLinus Torvalds set_buffer_uptodate(bh); 12491da177e4SLinus Torvalds } 12501da177e4SLinus Torvalds } 12511da177e4SLinus Torvalds } 12521da177e4SLinus Torvalds } 12531da177e4SLinus Torvalds 12541da177e4SLinus Torvalds /* Wait for read requests we made to happen, if necessary */ 12551da177e4SLinus Torvalds while (wait_bh > wait) { 12561da177e4SLinus Torvalds wait_on_buffer(*--wait_bh); 12571da177e4SLinus Torvalds if (!buffer_uptodate(*wait_bh)) { 12581da177e4SLinus Torvalds res = -EIO; 12591da177e4SLinus Torvalds goto failed_read; 12601da177e4SLinus Torvalds } 12611da177e4SLinus Torvalds } 12621da177e4SLinus Torvalds 12631da177e4SLinus Torvalds return blocks; 12641da177e4SLinus Torvalds failed_page_grabbing: 12651da177e4SLinus Torvalds num_pages = i; 12661da177e4SLinus Torvalds failed_read: 12671da177e4SLinus Torvalds reiserfs_unprepare_pages(prepared_pages, num_pages); 12681da177e4SLinus Torvalds return res; 12691da177e4SLinus Torvalds } 12701da177e4SLinus Torvalds 12711da177e4SLinus Torvalds /* Write @count bytes at position @ppos in a file indicated by @file 12721da177e4SLinus Torvalds from the buffer @buf. 12731da177e4SLinus Torvalds 12741da177e4SLinus Torvalds generic_file_write() is only appropriate for filesystems that are not seeking to optimize performance and want 12751da177e4SLinus Torvalds something simple that works. It is not for serious use by general purpose filesystems, excepting the one that it was 12761da177e4SLinus Torvalds written for (ext2/3). This is for several reasons: 12771da177e4SLinus Torvalds 12781da177e4SLinus Torvalds * It has no understanding of any filesystem specific optimizations. 12791da177e4SLinus Torvalds 12801da177e4SLinus Torvalds * It enters the filesystem repeatedly for each page that is written. 12811da177e4SLinus Torvalds 12821da177e4SLinus Torvalds * It depends on reiserfs_get_block() function which if implemented by reiserfs performs costly search_by_key 12831da177e4SLinus Torvalds * operation for each page it is supplied with. By contrast reiserfs_file_write() feeds as much as possible at a time 12841da177e4SLinus Torvalds * to reiserfs which allows for fewer tree traversals. 12851da177e4SLinus Torvalds 12861da177e4SLinus Torvalds * Each indirect pointer insertion takes a lot of cpu, because it involves memory moves inside of blocks. 12871da177e4SLinus Torvalds 12881da177e4SLinus Torvalds * Asking the block allocation code for blocks one at a time is slightly less efficient. 12891da177e4SLinus Torvalds 12901da177e4SLinus Torvalds All of these reasons for not using only generic file write were understood back when reiserfs was first miscoded to 12911da177e4SLinus Torvalds use it, but we were in a hurry to make code freeze, and so it couldn't be revised then. This new code should make 12921da177e4SLinus Torvalds things right finally. 12931da177e4SLinus Torvalds 12941da177e4SLinus Torvalds Future Features: providing search_by_key with hints. 12951da177e4SLinus Torvalds 12961da177e4SLinus Torvalds */ 12971da177e4SLinus Torvalds static ssize_t reiserfs_file_write(struct file *file, /* the file we are going to write into */ 12981da177e4SLinus Torvalds const char __user * buf, /* pointer to user supplied data 12991da177e4SLinus Torvalds (in userspace) */ 13001da177e4SLinus Torvalds size_t count, /* amount of bytes to write */ 13011da177e4SLinus Torvalds loff_t * ppos /* pointer to position in file that we start writing at. Should be updated to 1302bd4c625cSLinus Torvalds * new current position before returning. */ 1303bd4c625cSLinus Torvalds ) 13041da177e4SLinus Torvalds { 13051da177e4SLinus Torvalds size_t already_written = 0; // Number of bytes already written to the file. 13061da177e4SLinus Torvalds loff_t pos; // Current position in the file. 13071da177e4SLinus Torvalds ssize_t res; // return value of various functions that we call. 13081da177e4SLinus Torvalds int err = 0; 13091fc5adbdSJosef Sipek struct inode *inode = file->f_path.dentry->d_inode; // Inode of the file that we are writing to. 13101da177e4SLinus Torvalds /* To simplify coding at this time, we store 13111da177e4SLinus Torvalds locked pages in array for now */ 13121da177e4SLinus Torvalds struct page *prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME]; 13131da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 13141da177e4SLinus Torvalds th.t_trans_id = 0; 13151da177e4SLinus Torvalds 1316fa385befSJeff Mahoney /* If a filesystem is converted from 3.5 to 3.6, we'll have v3.5 items 1317fa385befSJeff Mahoney * lying around (most of the disk, in fact). Despite the filesystem 1318fa385befSJeff Mahoney * now being a v3.6 format, the old items still can't support large 1319fa385befSJeff Mahoney * file sizes. Catch this case here, as the rest of the VFS layer is 1320fa385befSJeff Mahoney * oblivious to the different limitations between old and new items. 1321fa385befSJeff Mahoney * reiserfs_setattr catches this for truncates. This chunk is lifted 1322fa385befSJeff Mahoney * from generic_write_checks. */ 1323fa385befSJeff Mahoney if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 && 1324fa385befSJeff Mahoney *ppos + count > MAX_NON_LFS) { 1325fa385befSJeff Mahoney if (*ppos >= MAX_NON_LFS) { 1326fa385befSJeff Mahoney send_sig(SIGXFSZ, current, 0); 1327fa385befSJeff Mahoney return -EFBIG; 1328fa385befSJeff Mahoney } 1329fa385befSJeff Mahoney if (count > MAX_NON_LFS - (unsigned long)*ppos) 1330fa385befSJeff Mahoney count = MAX_NON_LFS - (unsigned long)*ppos; 1331fa385befSJeff Mahoney } 1332fa385befSJeff Mahoney 1333c5574768SVladimir V. Saveliev if (file->f_flags & O_DIRECT) 1334c5574768SVladimir V. Saveliev return do_sync_write(file, buf, count, ppos); 13351da177e4SLinus Torvalds 13361da177e4SLinus Torvalds if (unlikely((ssize_t) count < 0)) 13371da177e4SLinus Torvalds return -EINVAL; 13381da177e4SLinus Torvalds 13391da177e4SLinus Torvalds if (unlikely(!access_ok(VERIFY_READ, buf, count))) 13401da177e4SLinus Torvalds return -EFAULT; 13411da177e4SLinus Torvalds 13421b1dcc1bSJes Sorensen mutex_lock(&inode->i_mutex); // locks the entire file for just us 13431da177e4SLinus Torvalds 13441da177e4SLinus Torvalds pos = *ppos; 13451da177e4SLinus Torvalds 13461da177e4SLinus Torvalds /* Check if we can write to specified region of file, file 13471da177e4SLinus Torvalds is not overly big and this kind of stuff. Adjust pos and 13481da177e4SLinus Torvalds count, if needed */ 13491da177e4SLinus Torvalds res = generic_write_checks(file, &pos, &count, 0); 13501da177e4SLinus Torvalds if (res) 13511da177e4SLinus Torvalds goto out; 13521da177e4SLinus Torvalds 13531da177e4SLinus Torvalds if (count == 0) 13541da177e4SLinus Torvalds goto out; 13551da177e4SLinus Torvalds 13561fc5adbdSJosef Sipek res = remove_suid(file->f_path.dentry); 13571da177e4SLinus Torvalds if (res) 13581da177e4SLinus Torvalds goto out; 13591da177e4SLinus Torvalds 1360870f4817SChristoph Hellwig file_update_time(file); 13611da177e4SLinus Torvalds 13621da177e4SLinus Torvalds // Ok, we are done with all the checks. 13631da177e4SLinus Torvalds 13641da177e4SLinus Torvalds // Now we should start real work 13651da177e4SLinus Torvalds 13661da177e4SLinus Torvalds /* If we are going to write past the file's packed tail or if we are going 13671da177e4SLinus Torvalds to overwrite part of the tail, we need that tail to be converted into 13681da177e4SLinus Torvalds unformatted node */ 13691da177e4SLinus Torvalds res = reiserfs_check_for_tail_and_convert(inode, pos, count); 13701da177e4SLinus Torvalds if (res) 13711da177e4SLinus Torvalds goto out; 13721da177e4SLinus Torvalds 13731da177e4SLinus Torvalds while (count > 0) { 13741da177e4SLinus Torvalds /* This is the main loop in which we running until some error occures 13751da177e4SLinus Torvalds or until we write all of the data. */ 13761da177e4SLinus Torvalds size_t num_pages; /* amount of pages we are going to write this iteration */ 13771da177e4SLinus Torvalds size_t write_bytes; /* amount of bytes to write during this iteration */ 13781da177e4SLinus Torvalds size_t blocks_to_allocate; /* how much blocks we need to allocate for this iteration */ 13791da177e4SLinus Torvalds 13801da177e4SLinus Torvalds /* (pos & (PAGE_CACHE_SIZE-1)) is an idiom for offset into a page of pos */ 13811da177e4SLinus Torvalds num_pages = !!((pos + count) & (PAGE_CACHE_SIZE - 1)) + /* round up partial 13821da177e4SLinus Torvalds pages */ 1383bd4c625cSLinus Torvalds ((count + 1384bd4c625cSLinus Torvalds (pos & (PAGE_CACHE_SIZE - 1))) >> PAGE_CACHE_SHIFT); 13851da177e4SLinus Torvalds /* convert size to amount of 13861da177e4SLinus Torvalds pages */ 13871da177e4SLinus Torvalds reiserfs_write_lock(inode->i_sb); 13881da177e4SLinus Torvalds if (num_pages > REISERFS_WRITE_PAGES_AT_A_TIME 13891da177e4SLinus Torvalds || num_pages > reiserfs_can_fit_pages(inode->i_sb)) { 13901da177e4SLinus Torvalds /* If we were asked to write more data than we want to or if there 13911da177e4SLinus Torvalds is not that much space, then we shorten amount of data to write 13921da177e4SLinus Torvalds for this iteration. */ 1393bd4c625cSLinus Torvalds num_pages = 1394bd4c625cSLinus Torvalds min_t(size_t, REISERFS_WRITE_PAGES_AT_A_TIME, 1395bd4c625cSLinus Torvalds reiserfs_can_fit_pages(inode->i_sb)); 13961da177e4SLinus Torvalds /* Also we should not forget to set size in bytes accordingly */ 13971da177e4SLinus Torvalds write_bytes = (num_pages << PAGE_CACHE_SHIFT) - 13981da177e4SLinus Torvalds (pos & (PAGE_CACHE_SIZE - 1)); 13991da177e4SLinus Torvalds /* If position is not on the 14001da177e4SLinus Torvalds start of the page, we need 14011da177e4SLinus Torvalds to substract the offset 14021da177e4SLinus Torvalds within page */ 14031da177e4SLinus Torvalds } else 14041da177e4SLinus Torvalds write_bytes = count; 14051da177e4SLinus Torvalds 14061da177e4SLinus Torvalds /* reserve the blocks to be allocated later, so that later on 14071da177e4SLinus Torvalds we still have the space to write the blocks to */ 1408bd4c625cSLinus Torvalds reiserfs_claim_blocks_to_be_allocated(inode->i_sb, 1409bd4c625cSLinus Torvalds num_pages << 1410bd4c625cSLinus Torvalds (PAGE_CACHE_SHIFT - 1411bd4c625cSLinus Torvalds inode->i_blkbits)); 14121da177e4SLinus Torvalds reiserfs_write_unlock(inode->i_sb); 14131da177e4SLinus Torvalds 1414127144dfSJan Kara if (!num_pages) { /* If we do not have enough space even for a single page... */ 1415bd4c625cSLinus Torvalds if (pos > 1416bd4c625cSLinus Torvalds inode->i_size + inode->i_sb->s_blocksize - 1417bd4c625cSLinus Torvalds (pos & (inode->i_sb->s_blocksize - 1))) { 1418127144dfSJan Kara res = -ENOSPC; 1419127144dfSJan Kara break; // In case we are writing past the end of the last file block, break. 1420127144dfSJan Kara } 14211da177e4SLinus Torvalds // Otherwise we are possibly overwriting the file, so 14221da177e4SLinus Torvalds // let's set write size to be equal or less than blocksize. 14231da177e4SLinus Torvalds // This way we get it correctly for file holes. 14241da177e4SLinus Torvalds // But overwriting files on absolutelly full volumes would not 14251da177e4SLinus Torvalds // be very efficient. Well, people are not supposed to fill 14261da177e4SLinus Torvalds // 100% of disk space anyway. 1427bd4c625cSLinus Torvalds write_bytes = 1428bd4c625cSLinus Torvalds min_t(size_t, count, 1429bd4c625cSLinus Torvalds inode->i_sb->s_blocksize - 1430bd4c625cSLinus Torvalds (pos & (inode->i_sb->s_blocksize - 1))); 14311da177e4SLinus Torvalds num_pages = 1; 14321da177e4SLinus Torvalds // No blocks were claimed before, so do it now. 1433bd4c625cSLinus Torvalds reiserfs_claim_blocks_to_be_allocated(inode->i_sb, 1434bd4c625cSLinus Torvalds 1 << 1435bd4c625cSLinus Torvalds (PAGE_CACHE_SHIFT 1436bd4c625cSLinus Torvalds - 1437bd4c625cSLinus Torvalds inode-> 1438bd4c625cSLinus Torvalds i_blkbits)); 14391da177e4SLinus Torvalds } 14401da177e4SLinus Torvalds 14411da177e4SLinus Torvalds /* Prepare for writing into the region, read in all the 14421da177e4SLinus Torvalds partially overwritten pages, if needed. And lock the pages, 14431da177e4SLinus Torvalds so that nobody else can access these until we are done. 14441da177e4SLinus Torvalds We get number of actual blocks needed as a result. */ 1445c499ec24SVladimir V. Saveliev res = reiserfs_prepare_file_region_for_write(inode, pos, 1446bd4c625cSLinus Torvalds num_pages, 1447bd4c625cSLinus Torvalds write_bytes, 1448bd4c625cSLinus Torvalds prepared_pages); 1449c499ec24SVladimir V. Saveliev if (res < 0) { 1450bd4c625cSLinus Torvalds reiserfs_release_claimed_blocks(inode->i_sb, 1451bd4c625cSLinus Torvalds num_pages << 1452bd4c625cSLinus Torvalds (PAGE_CACHE_SHIFT - 1453bd4c625cSLinus Torvalds inode->i_blkbits)); 14541da177e4SLinus Torvalds break; 14551da177e4SLinus Torvalds } 14561da177e4SLinus Torvalds 1457c499ec24SVladimir V. Saveliev blocks_to_allocate = res; 1458c499ec24SVladimir V. Saveliev 14591da177e4SLinus Torvalds /* First we correct our estimate of how many blocks we need */ 1460bd4c625cSLinus Torvalds reiserfs_release_claimed_blocks(inode->i_sb, 1461bd4c625cSLinus Torvalds (num_pages << 1462bd4c625cSLinus Torvalds (PAGE_CACHE_SHIFT - 1463bd4c625cSLinus Torvalds inode->i_sb-> 1464bd4c625cSLinus Torvalds s_blocksize_bits)) - 1465bd4c625cSLinus Torvalds blocks_to_allocate); 14661da177e4SLinus Torvalds 14671da177e4SLinus Torvalds if (blocks_to_allocate > 0) { /*We only allocate blocks if we need to */ 14681da177e4SLinus Torvalds /* Fill in all the possible holes and append the file if needed */ 1469bd4c625cSLinus Torvalds res = 1470bd4c625cSLinus Torvalds reiserfs_allocate_blocks_for_region(&th, inode, pos, 1471bd4c625cSLinus Torvalds num_pages, 1472bd4c625cSLinus Torvalds write_bytes, 1473bd4c625cSLinus Torvalds prepared_pages, 1474bd4c625cSLinus Torvalds blocks_to_allocate); 14751da177e4SLinus Torvalds } 14761da177e4SLinus Torvalds 14771da177e4SLinus Torvalds /* well, we have allocated the blocks, so it is time to free 14781da177e4SLinus Torvalds the reservation we made earlier. */ 1479bd4c625cSLinus Torvalds reiserfs_release_claimed_blocks(inode->i_sb, 1480bd4c625cSLinus Torvalds blocks_to_allocate); 14811da177e4SLinus Torvalds if (res) { 14821da177e4SLinus Torvalds reiserfs_unprepare_pages(prepared_pages, num_pages); 14831da177e4SLinus Torvalds break; 14841da177e4SLinus Torvalds } 14851da177e4SLinus Torvalds 14861da177e4SLinus Torvalds /* NOTE that allocating blocks and filling blocks can be done in reverse order 14871da177e4SLinus Torvalds and probably we would do that just to get rid of garbage in files after a 14881da177e4SLinus Torvalds crash */ 14891da177e4SLinus Torvalds 14901da177e4SLinus Torvalds /* Copy data from user-supplied buffer to file's pages */ 1491bd4c625cSLinus Torvalds res = 1492bd4c625cSLinus Torvalds reiserfs_copy_from_user_to_file_region(pos, num_pages, 1493bd4c625cSLinus Torvalds write_bytes, 1494bd4c625cSLinus Torvalds prepared_pages, buf); 14951da177e4SLinus Torvalds if (res) { 14961da177e4SLinus Torvalds reiserfs_unprepare_pages(prepared_pages, num_pages); 14971da177e4SLinus Torvalds break; 14981da177e4SLinus Torvalds } 14991da177e4SLinus Torvalds 15001da177e4SLinus Torvalds /* Send the pages to disk and unlock them. */ 1501bd4c625cSLinus Torvalds res = 1502bd4c625cSLinus Torvalds reiserfs_submit_file_region_for_write(&th, inode, pos, 1503bd4c625cSLinus Torvalds num_pages, 1504bd4c625cSLinus Torvalds write_bytes, 1505bd4c625cSLinus Torvalds prepared_pages); 15061da177e4SLinus Torvalds if (res) 15071da177e4SLinus Torvalds break; 15081da177e4SLinus Torvalds 15091da177e4SLinus Torvalds already_written += write_bytes; 15101da177e4SLinus Torvalds buf += write_bytes; 15111da177e4SLinus Torvalds *ppos = pos += write_bytes; 15121da177e4SLinus Torvalds count -= write_bytes; 151359308602SAlexander Zarochentsev balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages); 15141da177e4SLinus Torvalds } 15151da177e4SLinus Torvalds 15161da177e4SLinus Torvalds /* this is only true on error */ 15171da177e4SLinus Torvalds if (th.t_trans_id) { 15181da177e4SLinus Torvalds reiserfs_write_lock(inode->i_sb); 15191da177e4SLinus Torvalds err = journal_end(&th, th.t_super, th.t_blocks_allocated); 15201da177e4SLinus Torvalds reiserfs_write_unlock(inode->i_sb); 15211da177e4SLinus Torvalds if (err) { 15221da177e4SLinus Torvalds res = err; 15231da177e4SLinus Torvalds goto out; 15241da177e4SLinus Torvalds } 15251da177e4SLinus Torvalds } 15261da177e4SLinus Torvalds 1527619d5d8aSJeff Mahoney if (likely(res >= 0) && 1528619d5d8aSJeff Mahoney (unlikely((file->f_flags & O_SYNC) || IS_SYNC(inode)))) 1529619d5d8aSJeff Mahoney res = generic_osync_inode(inode, file->f_mapping, 1530bd4c625cSLinus Torvalds OSYNC_METADATA | OSYNC_DATA); 15311da177e4SLinus Torvalds 15321b1dcc1bSJes Sorensen mutex_unlock(&inode->i_mutex); 15331da177e4SLinus Torvalds reiserfs_async_progress_wait(inode->i_sb); 15341da177e4SLinus Torvalds return (already_written != 0) ? already_written : res; 15351da177e4SLinus Torvalds 15361da177e4SLinus Torvalds out: 15371b1dcc1bSJes Sorensen mutex_unlock(&inode->i_mutex); // unlock the file on exit. 15381da177e4SLinus Torvalds return res; 15391da177e4SLinus Torvalds } 15401da177e4SLinus Torvalds 15414b6f5d20SArjan van de Ven const struct file_operations reiserfs_file_operations = { 1542027445c3SBadari Pulavarty .read = do_sync_read, 15431da177e4SLinus Torvalds .write = reiserfs_file_write, 15441da177e4SLinus Torvalds .ioctl = reiserfs_ioctl, 154552b499c4SDavid Howells #ifdef CONFIG_COMPAT 154652b499c4SDavid Howells .compat_ioctl = reiserfs_compat_ioctl, 154752b499c4SDavid Howells #endif 1548*de14569fSVladimir Saveliev .mmap = reiserfs_file_mmap, 15495a2618e6SJeff Mahoney .open = generic_file_open, 15501da177e4SLinus Torvalds .release = reiserfs_file_release, 15511da177e4SLinus Torvalds .fsync = reiserfs_sync_file, 15521da177e4SLinus Torvalds .sendfile = generic_file_sendfile, 15531da177e4SLinus Torvalds .aio_read = generic_file_aio_read, 15549637f28fSAlexey Dobriyan .aio_write = generic_file_aio_write, 15555274f052SJens Axboe .splice_read = generic_file_splice_read, 15565274f052SJens Axboe .splice_write = generic_file_splice_write, 15571da177e4SLinus Torvalds }; 15581da177e4SLinus Torvalds 15591da177e4SLinus Torvalds struct inode_operations reiserfs_file_inode_operations = { 15601da177e4SLinus Torvalds .truncate = reiserfs_vfs_truncate_file, 15611da177e4SLinus Torvalds .setattr = reiserfs_setattr, 15621da177e4SLinus Torvalds .setxattr = reiserfs_setxattr, 15631da177e4SLinus Torvalds .getxattr = reiserfs_getxattr, 15641da177e4SLinus Torvalds .listxattr = reiserfs_listxattr, 15651da177e4SLinus Torvalds .removexattr = reiserfs_removexattr, 15661da177e4SLinus Torvalds .permission = reiserfs_permission, 15671da177e4SLinus Torvalds }; 1568