X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Freiserfs%2Finode.c;h=402ba643fab7568886af06fd7dff370de3b0a7fe;hb=2c66a62d2d9e2315e6e748b96643f7f141c4d017;hp=6aded3b8941bdde1924a43e6f6b46636af5376f5;hpb=86090fcac5e27b630656fe3d963a6b80e26dac44;p=linux-2.6.git diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 6aded3b89..402ba643f 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -4,7 +4,10 @@ #include #include +#include #include +#include +#include #include #include #include @@ -13,6 +16,8 @@ #include #include #include +#include +#include extern int reiserfs_default_io_size; /* default io size devuned in super.c */ @@ -36,10 +41,13 @@ void reiserfs_delete_inode (struct inode * inode) reiserfs_write_lock(inode->i_sb); + DQUOT_FREE_INODE(inode); /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */ if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */ down (&inode->i_sem); + reiserfs_delete_xattrs (inode); + journal_begin(&th, inode->i_sb, jbegin_count) ; reiserfs_update_inode_transaction(inode) ; @@ -642,7 +650,7 @@ start_trans: repeat = _allocate_block(th, block, inode, &allocated_block_nr, &path, create); - if (repeat == NO_DISK_SPACE) { + if (repeat == NO_DISK_SPACE || repeat == QUOTA_EXCEEDED) { /* restart the transaction to give the journal a chance to free ** some blocks. releases the path, so we have to go back to ** research if we succeed on the second try @@ -651,10 +659,13 @@ start_trans: restart_transaction(th, inode, &path) ; repeat = _allocate_block(th, block, inode, &allocated_block_nr, NULL, create); - if (repeat != NO_DISK_SPACE) { + if (repeat != NO_DISK_SPACE && repeat != QUOTA_EXCEEDED) { goto research ; } - retval = -ENOSPC; + if (repeat == QUOTA_EXCEEDED) + retval = -EDQUOT; + else + retval = -ENOSPC; goto failure; } @@ -682,7 +693,6 @@ start_trans: put_block_num(item, pos_in_item, allocated_block_nr) ; unfm_ptr = allocated_block_nr; journal_mark_dirty (th, inode->i_sb, bh); - inode->i_blocks += (inode->i_sb->s_blocksize / 512) ; reiserfs_update_sd(th, inode) ; } set_block_dev_mapped(bh_result, unfm_ptr, inode); @@ -729,13 +739,11 @@ start_trans: set_cpu_key_k_offset (&tmp_key, 1); PATH_LAST_POSITION(&path) ++; - retval = reiserfs_insert_item (th, &path, &tmp_key, &tmp_ih, (char *)&unp); + retval = reiserfs_insert_item (th, &path, &tmp_key, &tmp_ih, inode, (char *)&unp); if (retval) { - reiserfs_free_block (th, allocated_block_nr); - goto failure; // retval == -ENOSPC or -EIO or -EEXIST + reiserfs_free_block (th, inode, allocated_block_nr, 1); + goto failure; // retval == -ENOSPC, -EDQUOT or -EIO or -EEXIST } - if (unp) - inode->i_blocks += inode->i_sb->s_blocksize / 512; //mark_tail_converted (inode); } else if (is_direct_le_ih (ih)) { /* direct item has to be converted */ @@ -767,13 +775,13 @@ start_trans: retval = convert_tail_for_hole(inode, bh_result, tail_offset) ; if (retval) { if ( retval != -ENOSPC ) - printk("clm-6004: convert tail failed inode %lu, error %d\n", inode->i_ino, retval) ; + reiserfs_warning (inode->i_sb, "clm-6004: convert tail failed inode %lu, error %d", inode->i_ino, retval) ; if (allocated_block_nr) { /* the bitmap, the super, and the stat data == 3 */ if (!th) th = reiserfs_persistent_transaction(inode->i_sb,3); if (th) - reiserfs_free_block (th, allocated_block_nr); + reiserfs_free_block (th,inode,allocated_block_nr,1); } goto failure ; } @@ -782,7 +790,7 @@ start_trans: retval = direct2indirect (th, inode, &path, unbh, tail_offset); if (retval) { reiserfs_unmap_buffer(unbh); - reiserfs_free_block (th, allocated_block_nr); + reiserfs_free_block (th, inode, allocated_block_nr, 1); goto failure; } /* it is important the set_buffer_uptodate is done after @@ -815,9 +823,6 @@ start_trans: */ mark_buffer_dirty(unbh) ; } - - //inode->i_blocks += inode->i_sb->s_blocksize / 512; - //mark_tail_converted (inode); } else { /* append indirect item with holes if needed, when appending pointer to 'block'-th block use block, which is already @@ -865,24 +870,21 @@ start_trans: only have space for one block */ blocks_needed=max_to_insert?max_to_insert:1; } - retval = reiserfs_paste_into_item (th, &path, &tmp_key, (char *)un, UNFM_P_SIZE * blocks_needed); + retval = reiserfs_paste_into_item (th, &path, &tmp_key, inode, (char *)un, UNFM_P_SIZE * blocks_needed); if (blocks_needed != 1) kfree(un); if (retval) { - reiserfs_free_block (th, allocated_block_nr); + reiserfs_free_block (th, inode, allocated_block_nr, 1); goto failure; } - if (done) { - inode->i_blocks += inode->i_sb->s_blocksize / 512; - } else { + if (!done) { /* We need to mark new file size in case this function will be interrupted/aborted later on. And we may do this only for holes. */ inode->i_size += inode->i_sb->s_blocksize * blocks_needed; } - //mark_tail_converted (inode); } if (done == 1) @@ -910,11 +912,11 @@ start_trans: goto failure; } if (retval == POSITION_FOUND) { - reiserfs_warning ("vs-825: reiserfs_get_block: " - "%K should not be found\n", &key); + reiserfs_warning (inode->i_sb, "vs-825: reiserfs_get_block: " + "%K should not be found", &key); retval = -EEXIST; if (allocated_block_nr) - reiserfs_free_block (th, allocated_block_nr); + reiserfs_free_block (th, inode, allocated_block_nr, 1); pathrelse(&path) ; goto failure; } @@ -944,6 +946,58 @@ reiserfs_readpages(struct file *file, struct address_space *mapping, return mpage_readpages(mapping, pages, nr_pages, reiserfs_get_block); } +/* Compute real number of used bytes by file + * Following three functions can go away when we'll have enough space in stat item + */ +static int real_space_diff(struct inode *inode, int sd_size) +{ + int bytes; + loff_t blocksize = inode->i_sb->s_blocksize ; + + if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) + return sd_size ; + + /* End of file is also in full block with indirect reference, so round + ** up to the next block. + ** + ** there is just no way to know if the tail is actually packed + ** on the file, so we have to assume it isn't. When we pack the + ** tail, we add 4 bytes to pretend there really is an unformatted + ** node pointer + */ + bytes = ((inode->i_size + (blocksize-1)) >> inode->i_sb->s_blocksize_bits) * UNFM_P_SIZE + sd_size; + return bytes ; +} + +static inline loff_t to_real_used_space(struct inode *inode, ulong blocks, + int sd_size) +{ + if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) { + return inode->i_size + (loff_t)(real_space_diff(inode, sd_size)) ; + } + return ((loff_t)real_space_diff(inode, sd_size)) + (((loff_t)blocks) << 9); +} + +/* Compute number of blocks used by file in ReiserFS counting */ +static inline ulong to_fake_used_blocks(struct inode *inode, int sd_size) +{ + loff_t bytes = inode_get_bytes(inode) ; + loff_t real_space = real_space_diff(inode, sd_size) ; + + /* keeps fsck and non-quota versions of reiserfs happy */ + if (S_ISLNK(inode->i_mode) || S_ISDIR(inode->i_mode)) { + bytes += (loff_t)511 ; + } + + /* files from before the quota patch might i_blocks such that + ** bytes < real_space. Deal with that here to prevent it from + ** going negative. + */ + if (bytes < real_space) + return 0 ; + return (bytes - real_space) >> 9; +} + // // BAD: new directories have stat data of new type and all other items // of old type. Version stored in the inode says about body items, so @@ -957,6 +1011,8 @@ static void init_inode (struct inode * inode, struct path * path) struct buffer_head * bh; struct item_head * ih; __u32 rdev; + uid_t uid; + gid_t gid; //int version = ITEM_VERSION_1; bh = PATH_PLAST_BUFFER (path); @@ -972,17 +1028,21 @@ static void init_inode (struct inode * inode, struct path * path) REISERFS_I(inode)->i_prealloc_count = 0; REISERFS_I(inode)->i_trans_id = 0; REISERFS_I(inode)->i_jl = NULL; + REISERFS_I(inode)->i_acl_access = NULL; + REISERFS_I(inode)->i_acl_default = NULL; + init_rwsem (&REISERFS_I(inode)->xattr_sem); if (stat_data_v1 (ih)) { struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); unsigned long blocks; + uid = sd_v1_uid(sd); + gid = sd_v1_gid(sd); + set_inode_item_key_version (inode, KEY_FORMAT_3_5); set_inode_sd_version (inode, STAT_DATA_V1); inode->i_mode = sd_v1_mode(sd); inode->i_nlink = sd_v1_nlink(sd); - inode->i_uid = sd_v1_uid(sd); - inode->i_gid = sd_v1_gid(sd); inode->i_size = sd_v1_size(sd); inode->i_atime.tv_sec = sd_v1_atime(sd); inode->i_mtime.tv_sec = sd_v1_mtime(sd); @@ -1006,6 +1066,14 @@ static void init_inode (struct inode * inode, struct path * path) rdev = sd_v1_rdev(sd); REISERFS_I(inode)->i_first_direct_byte = sd_v1_first_direct_byte(sd); + /* an early bug in the quota code can give us an odd number for the + ** block count. This is incorrect, fix it here. + */ + if (inode->i_blocks & 1) { + inode->i_blocks++ ; + } + inode_set_bytes(inode, to_real_used_space(inode, inode->i_blocks, + SD_V1_SIZE)); /* nopack is initially zero for v1 objects. For v2 objects, nopack is initialised from sd_attrs */ REISERFS_I(inode)->i_flags &= ~i_nopack_mask; @@ -1014,11 +1082,12 @@ static void init_inode (struct inode * inode, struct path * path) // (directories and symlinks) struct stat_data * sd = (struct stat_data *)B_I_PITEM (bh, ih); + uid = sd_v2_uid(sd); + gid = sd_v2_gid(sd); + inode->i_mode = sd_v2_mode(sd); inode->i_nlink = sd_v2_nlink(sd); - inode->i_uid = sd_v2_uid(sd); inode->i_size = sd_v2_size(sd); - inode->i_gid = sd_v2_gid(sd); inode->i_mtime.tv_sec = sd_v2_mtime(sd); inode->i_atime.tv_sec = sd_v2_atime(sd); inode->i_ctime.tv_sec = sd_v2_ctime(sd); @@ -1038,11 +1107,16 @@ static void init_inode (struct inode * inode, struct path * path) set_inode_item_key_version (inode, KEY_FORMAT_3_6); REISERFS_I(inode)->i_first_direct_byte = 0; set_inode_sd_version (inode, STAT_DATA_V2); + inode_set_bytes(inode, to_real_used_space(inode, inode->i_blocks, + SD_V2_SIZE)); /* read persistent inode attributes from sd and initalise generic inode flags from them */ REISERFS_I(inode)->i_attrs = sd_v2_attrs( sd ); sd_attrs_to_i_attrs( sd_v2_attrs( sd ), inode ); } + inode->i_uid = INOXID_UID(uid, gid); + inode->i_gid = INOXID_GID(uid, gid); + inode->i_xid = INOXID_XID(uid, gid, 0); pathrelse (path); if (S_ISREG (inode->i_mode)) { @@ -1053,30 +1127,33 @@ static void init_inode (struct inode * inode, struct path * path) inode->i_op = &reiserfs_dir_inode_operations; inode->i_fop = &reiserfs_dir_operations; } else if (S_ISLNK (inode->i_mode)) { - inode->i_op = &page_symlink_inode_operations; + inode->i_op = &reiserfs_symlink_inode_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations; } else { inode->i_blocks = 0; + inode->i_op = &reiserfs_special_inode_operations; init_special_inode(inode, inode->i_mode, new_decode_dev(rdev)); } } // update new stat data with inode fields -static void inode2sd (void * sd, struct inode * inode) +static void inode2sd (void * sd, struct inode * inode, loff_t size) { struct stat_data * sd_v2 = (struct stat_data *)sd; + uid_t uid = XIDINO_UID(inode->i_uid, inode->i_xid); + gid_t gid = XIDINO_GID(inode->i_gid, inode->i_xid); __u16 flags; + set_sd_v2_uid(sd_v2, uid ); + set_sd_v2_gid(sd_v2, gid ); set_sd_v2_mode(sd_v2, inode->i_mode ); set_sd_v2_nlink(sd_v2, inode->i_nlink ); - set_sd_v2_uid(sd_v2, inode->i_uid ); - set_sd_v2_size(sd_v2, inode->i_size ); - set_sd_v2_gid(sd_v2, inode->i_gid ); + set_sd_v2_size(sd_v2, size ); set_sd_v2_mtime(sd_v2, inode->i_mtime.tv_sec ); set_sd_v2_atime(sd_v2, inode->i_atime.tv_sec ); set_sd_v2_ctime(sd_v2, inode->i_ctime.tv_sec ); - set_sd_v2_blocks(sd_v2, inode->i_blocks ); + set_sd_v2_blocks(sd_v2, to_fake_used_blocks(inode, SD_V2_SIZE)); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) set_sd_v2_rdev(sd_v2, new_encode_dev(inode->i_rdev)); else @@ -1088,7 +1165,7 @@ static void inode2sd (void * sd, struct inode * inode) // used to copy inode's fields to old stat data -static void inode2sd_v1 (void * sd, struct inode * inode) +static void inode2sd_v1 (void * sd, struct inode * inode, loff_t size) { struct stat_data_v1 * sd_v1 = (struct stat_data_v1 *)sd; @@ -1096,7 +1173,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode) set_sd_v1_uid(sd_v1, inode->i_uid ); set_sd_v1_gid(sd_v1, inode->i_gid ); set_sd_v1_nlink(sd_v1, inode->i_nlink ); - set_sd_v1_size(sd_v1, inode->i_size ); + set_sd_v1_size(sd_v1, size ); set_sd_v1_atime(sd_v1, inode->i_atime.tv_sec ); set_sd_v1_ctime(sd_v1, inode->i_ctime.tv_sec ); set_sd_v1_mtime(sd_v1, inode->i_mtime.tv_sec ); @@ -1104,7 +1181,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) set_sd_v1_rdev(sd_v1, new_encode_dev(inode->i_rdev)); else - set_sd_v1_blocks(sd_v1, inode->i_blocks ); + set_sd_v1_blocks(sd_v1, to_fake_used_blocks(inode, SD_V1_SIZE)); // Sigh. i_first_direct_byte is back set_sd_v1_first_direct_byte(sd_v1, REISERFS_I(inode)->i_first_direct_byte); @@ -1114,7 +1191,8 @@ static void inode2sd_v1 (void * sd, struct inode * inode) /* NOTE, you must prepare the buffer head before sending it here, ** and then log it after the call */ -static void update_stat_data (struct path * path, struct inode * inode) +static void update_stat_data (struct path * path, struct inode * inode, + loff_t size) { struct buffer_head * bh; struct item_head * ih; @@ -1128,17 +1206,17 @@ static void update_stat_data (struct path * path, struct inode * inode) if (stat_data_v1 (ih)) { // path points to old stat data - inode2sd_v1 (B_I_PITEM (bh, ih), inode); + inode2sd_v1 (B_I_PITEM (bh, ih), inode, size); } else { - inode2sd (B_I_PITEM (bh, ih), inode); + inode2sd (B_I_PITEM (bh, ih), inode, size); } return; } -void reiserfs_update_sd (struct reiserfs_transaction_handle *th, - struct inode * inode) +void reiserfs_update_sd_size (struct reiserfs_transaction_handle *th, + struct inode * inode, loff_t size) { struct cpu_key key; INITIALIZE_PATH(path); @@ -1154,7 +1232,7 @@ void reiserfs_update_sd (struct reiserfs_transaction_handle *th, /* look for the object's stat data */ retval = search_item (inode->i_sb, &key, &path); if (retval == IO_ERROR) { - reiserfs_warning ("vs-13050: reiserfs_update_sd: " + reiserfs_warning (inode->i_sb, "vs-13050: reiserfs_update_sd: " "i/o failure occurred trying to update %K stat data", &key); return; @@ -1163,11 +1241,11 @@ void reiserfs_update_sd (struct reiserfs_transaction_handle *th, pos = PATH_LAST_POSITION (&path); pathrelse(&path) ; if (inode->i_nlink == 0) { - /*printk ("vs-13050: reiserfs_update_sd: i_nlink == 0, stat data not found\n");*/ + /*reiserfs_warning (inode->i_sb, "vs-13050: reiserfs_update_sd: i_nlink == 0, stat data not found");*/ return; } - reiserfs_warning ("vs-13060: reiserfs_update_sd: " - "stat data of object %k (nlink == %d) not found (pos %d)\n", + reiserfs_warning (inode->i_sb, "vs-13060: reiserfs_update_sd: " + "stat data of object %k (nlink == %d) not found (pos %d)", INODE_PKEY (inode), inode->i_nlink, pos); reiserfs_check_path(&path) ; return; @@ -1188,7 +1266,7 @@ void reiserfs_update_sd (struct reiserfs_transaction_handle *th, } break; } - update_stat_data (&path, inode); + update_stat_data (&path, inode, size); journal_mark_dirty(th, th->t_super, bh) ; pathrelse (&path); return; @@ -1240,9 +1318,9 @@ void reiserfs_read_locked_inode (struct inode * inode, struct reiserfs_iget_args /* look for the object's stat data */ retval = search_item (inode->i_sb, &key, &path_to_sd); if (retval == IO_ERROR) { - reiserfs_warning ("vs-13070: reiserfs_read_locked_inode: " - "i/o failure occurred trying to find stat data of %K\n", - &key); + reiserfs_warning (inode->i_sb, "vs-13070: reiserfs_read_locked_inode: " + "i/o failure occurred trying to find stat data of %K", + &key); reiserfs_make_bad_inode(inode) ; return; } @@ -1272,9 +1350,10 @@ void reiserfs_read_locked_inode (struct inode * inode, struct reiserfs_iget_args during mount (fs/reiserfs/super.c:finish_unfinished()). */ if( ( inode -> i_nlink == 0 ) && ! REISERFS_SB(inode -> i_sb) -> s_is_unlinked_ok ) { - reiserfs_warning( "vs-13075: reiserfs_read_locked_inode: " + reiserfs_warning (inode->i_sb, + "vs-13075: reiserfs_read_locked_inode: " "dead inode read from disk %K. " - "This is likely to be race with knfsd. Ignore\n", + "This is likely to be race with knfsd. Ignore", &key ); reiserfs_make_bad_inode( inode ); } @@ -1377,7 +1456,7 @@ struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 *data, */ if (fhtype > len) { if (fhtype != 6 || len != 5) - printk(KERN_WARNING "nfsd/reiserfs, fhtype=%d, len=%d - odd\n", + reiserfs_warning (sb, "nfsd/reiserfs, fhtype=%d, len=%d - odd", fhtype, len); fhtype = 5; } @@ -1440,8 +1519,9 @@ void reiserfs_write_inode (struct inode * inode, int do_sync) { int jbegin_count = 1 ; if (inode->i_sb->s_flags & MS_RDONLY) { - reiserfs_warning("clm-6005: writing inode %lu on readonly FS\n", - inode->i_ino) ; + reiserfs_warning (inode->i_sb, + "clm-6005: writing inode %lu on readonly FS", + inode->i_ino) ; return ; } /* memory pressure can sometimes initiate write_inode calls with sync == 1, @@ -1471,6 +1551,7 @@ int reiserfs_sync_inode (struct reiserfs_transaction_handle *th, struct inode * /* stat data of new object is inserted already, this inserts the item containing "." and ".." entries */ static int reiserfs_new_directory (struct reiserfs_transaction_handle *th, + struct inode *inode, struct item_head * ih, struct path * path, struct inode * dir) { @@ -1503,25 +1584,26 @@ static int reiserfs_new_directory (struct reiserfs_transaction_handle *th, /* look for place in the tree for new item */ retval = search_item (sb, &key, path); if (retval == IO_ERROR) { - reiserfs_warning ("vs-13080: reiserfs_new_directory: " - "i/o failure occurred creating new directory\n"); + reiserfs_warning (sb, "vs-13080: reiserfs_new_directory: " + "i/o failure occurred creating new directory"); return -EIO; } if (retval == ITEM_FOUND) { pathrelse (path); - reiserfs_warning ("vs-13070: reiserfs_new_directory: " + reiserfs_warning (sb, "vs-13070: reiserfs_new_directory: " "object with this key exists (%k)", &(ih->ih_key)); return -EEXIST; } /* insert item, that is empty directory item */ - return reiserfs_insert_item (th, path, &key, ih, body); + return reiserfs_insert_item (th, path, &key, ih, inode, body); } /* stat data of object has been inserted, this inserts the item containing the body of symlink */ static int reiserfs_new_symlink (struct reiserfs_transaction_handle *th, + struct inode *inode, /* Inode of symlink */ struct item_head * ih, struct path * path, const char * symname, int item_len) { @@ -1539,19 +1621,19 @@ static int reiserfs_new_symlink (struct reiserfs_transaction_handle *th, /* look for place in the tree for new item */ retval = search_item (sb, &key, path); if (retval == IO_ERROR) { - reiserfs_warning ("vs-13080: reiserfs_new_symlinik: " - "i/o failure occurred creating new symlink\n"); + reiserfs_warning (sb, "vs-13080: reiserfs_new_symlinik: " + "i/o failure occurred creating new symlink"); return -EIO; } if (retval == ITEM_FOUND) { pathrelse (path); - reiserfs_warning ("vs-13080: reiserfs_new_symlink: " + reiserfs_warning (sb, "vs-13080: reiserfs_new_symlink: " "object with this key exists (%k)", &(ih->ih_key)); return -EEXIST; } /* insert item, that is body of symlink */ - return reiserfs_insert_item (th, path, &key, ih, symname); + return reiserfs_insert_item (th, path, &key, ih, inode, symname); } @@ -1619,7 +1701,8 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th, inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_size = i_size; - inode->i_blocks = (inode->i_size + 511) >> 9; + inode->i_blocks = 0; + inode->i_bytes = 0; REISERFS_I(inode)->i_first_direct_byte = S_ISLNK(mode) ? 1 : U32_MAX/*NO_BYTES_IN_DIRECT_ITEM*/; @@ -1632,6 +1715,9 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th, REISERFS_I(inode)->i_attrs = REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK; sd_attrs_to_i_attrs( REISERFS_I(inode) -> i_attrs, inode ); + REISERFS_I(inode)->i_acl_access = NULL; + REISERFS_I(inode)->i_acl_default = NULL; + init_rwsem (&REISERFS_I(inode)->xattr_sem); if (old_format_only (sb)) make_le_item_head (&ih, 0, KEY_FORMAT_3_5, SD_OFFSET, TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT); @@ -1661,9 +1747,9 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th, err = -EINVAL; goto out_bad_inode; } - inode2sd_v1 (&sd, inode); + inode2sd_v1 (&sd, inode, inode->i_size); } else { - inode2sd (&sd, inode); + inode2sd (&sd, inode, inode->i_size); } // these do not go to on-disk stat data inode->i_ino = le32_to_cpu (ih.ih_key.k_objectid); @@ -1687,7 +1773,7 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th, if (REISERFS_I(dir)->new_packing_locality) th->displace_new_blocks = 1; #endif - retval = reiserfs_insert_item (th, &path_to_key, &key, &ih, (char *)(&sd)); + retval = reiserfs_insert_item (th, &path_to_key, &key, &ih, inode, (char *)(&sd)); if (retval) { err = retval; reiserfs_check_path(&path_to_key) ; @@ -1700,14 +1786,14 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th, #endif if (S_ISDIR(mode)) { /* insert item with "." and ".." */ - retval = reiserfs_new_directory (th, &ih, &path_to_key, dir); + retval = reiserfs_new_directory (th, inode, &ih, &path_to_key, dir); } if (S_ISLNK(mode)) { /* insert body of symlink */ if (!old_format_only (sb)) i_size = ROUND_UP(i_size); - retval = reiserfs_new_symlink (th, &ih, &path_to_key, symname, i_size); + retval = reiserfs_new_symlink (th, inode, &ih, &path_to_key, symname, i_size); } if (retval) { err = retval; @@ -1716,6 +1802,20 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th, goto out_inserted_sd; } + /* XXX CHECK THIS */ + if (reiserfs_posixacl (inode->i_sb)) { + retval = reiserfs_inherit_default_acl (dir, dentry, inode); + if (retval) { + err = retval; + reiserfs_check_path(&path_to_key) ; + journal_end(th, th->t_super, th->t_blocks_allocated); + goto out_inserted_sd; + } + } else if (inode->i_sb->s_flags & MS_POSIXACL) { + reiserfs_warning (inode->i_sb, "ACLs aren't enabled in the fs, " + "but vfs thinks they are!"); + } + insert_inode_hash (inode); reiserfs_update_sd(th, inode); reiserfs_check_path(&path_to_key) ; @@ -1732,6 +1832,9 @@ out_bad_inode: /* dquot_drop must be done outside a transaction */ journal_end(th, th->t_super, th->t_blocks_allocated) ; + DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); + inode->i_flags |= S_NOQUOTA; make_bad_inode(inode); out_inserted_sd: @@ -1808,9 +1911,10 @@ static int grab_tail_page(struct inode *p_s_inode, ** I've screwed up the code to find the buffer, or the code to ** call prepare_write */ - reiserfs_warning("clm-6000: error reading block %lu on dev %s\n", - bh->b_blocknr, - reiserfs_bdevname (p_s_inode->i_sb)) ; + reiserfs_warning (p_s_inode->i_sb, + "clm-6000: error reading block %lu on dev %s", + bh->b_blocknr, + reiserfs_bdevname (p_s_inode->i_sb)) ; error = -EIO ; goto unlock ; } @@ -1850,7 +1954,9 @@ void reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps) { // and get_block_create_0 could not find a block to read in, // which is ok. if (error != -ENOENT) - reiserfs_warning("clm-6001: grab_tail_page failed %d\n", error); + reiserfs_warning (p_s_inode->i_sb, + "clm-6001: grab_tail_page failed %d", + error); page = NULL ; bh = NULL ; } @@ -1948,7 +2054,8 @@ research: /* we've found an unformatted node */ if (indirect_item_found(retval, ih)) { if (bytes_copied > 0) { - reiserfs_warning("clm-6002: bytes_copied %d\n", bytes_copied) ; + reiserfs_warning (inode->i_sb, "clm-6002: bytes_copied %d", + bytes_copied) ; } if (!get_block_num(item, pos_in_item)) { /* crap, we are writing to a hole */ @@ -1996,7 +2103,9 @@ research: goto research ; } } else { - reiserfs_warning("clm-6003: bad item inode %lu, device %s\n", inode->i_ino, reiserfs_bdevname (inode->i_sb)) ; + reiserfs_warning (inode->i_sb, + "clm-6003: bad item inode %lu, device %s", + inode->i_ino, reiserfs_bdevname (inode->i_sb)) ; retval = -EIO ; goto out ; } @@ -2269,6 +2378,7 @@ static int reiserfs_commit_write(struct file *f, struct page *page, struct inode *inode = page->mapping->host ; loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; int ret = 0; + int update_sd = 0; struct reiserfs_transaction_handle *th = NULL; reiserfs_wait_on_write_block(inode->i_sb) ; @@ -2295,11 +2405,14 @@ static int reiserfs_commit_write(struct file *f, struct page *page, reiserfs_update_inode_transaction(inode) ; inode->i_size = pos ; reiserfs_update_sd(&myth, inode) ; + update_sd = 1; journal_end(&myth, inode->i_sb, 1) ; reiserfs_write_unlock(inode->i_sb); } if (th) { reiserfs_write_lock(inode->i_sb); + if (!update_sd) + reiserfs_update_sd(th, inode) ; reiserfs_end_persistent_transaction(th); reiserfs_write_unlock(inode->i_sb); } @@ -2326,6 +2439,14 @@ void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode ) inode -> i_flags |= S_IMMUTABLE; else inode -> i_flags &= ~S_IMMUTABLE; + if( sd_attrs & REISERFS_IUNLINK_FL ) + inode -> i_flags |= S_IUNLINK; + else + inode -> i_flags &= ~S_IUNLINK; + if( sd_attrs & REISERFS_BARRIER_FL ) + inode -> i_flags |= S_BARRIER; + else + inode -> i_flags &= ~S_BARRIER; if( sd_attrs & REISERFS_APPEND_FL ) inode -> i_flags |= S_APPEND; else @@ -2348,6 +2469,14 @@ void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs ) *sd_attrs |= REISERFS_IMMUTABLE_FL; else *sd_attrs &= ~REISERFS_IMMUTABLE_FL; + if( inode -> i_flags & S_IUNLINK ) + *sd_attrs |= REISERFS_IUNLINK_FL; + else + *sd_attrs &= ~REISERFS_IUNLINK_FL; + if( inode -> i_flags & S_BARRIER ) + *sd_attrs |= REISERFS_BARRIER_FL; + else + *sd_attrs &= ~REISERFS_BARRIER_FL; if( inode -> i_flags & S_SYNC ) *sd_attrs |= REISERFS_SYNC_FL; else @@ -2508,6 +2637,98 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb, offset, nr_segs, reiserfs_get_blocks_direct_io, NULL); } +int reiserfs_setattr_flags(struct inode *inode, unsigned int flags) +{ + unsigned int oldflags, newflags; + + oldflags = REISERFS_I(inode)->i_flags; + newflags = oldflags & ~(REISERFS_IMMUTABLE_FL | + REISERFS_IUNLINK_FL | REISERFS_BARRIER_FL); + if (flags & ATTR_FLAG_IMMUTABLE) + newflags |= REISERFS_IMMUTABLE_FL; + if (flags & ATTR_FLAG_IUNLINK) + newflags |= REISERFS_IUNLINK_FL; + if (flags & ATTR_FLAG_BARRIER) + newflags |= REISERFS_BARRIER_FL; + + if (oldflags ^ newflags) { + REISERFS_I(inode)->i_flags = newflags; + inode->i_ctime = CURRENT_TIME; + } + return 0; +} + +int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) { + struct inode *inode = dentry->d_inode ; + int error ; + unsigned int ia_valid = attr->ia_valid; + + reiserfs_write_lock(inode->i_sb); + if (S_ISDIR(inode->i_mode)) + goto is_dir; + + if (attr->ia_valid & ATTR_SIZE) { + /* version 2 items will be caught by the s_maxbytes check + ** done for us in vmtruncate + */ + if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 && + attr->ia_size > MAX_NON_LFS) { + error = -EFBIG ; + goto out; + } + /* fill in hole pointers in the expanding truncate case. */ + if (attr->ia_size > inode->i_size) { + error = generic_cont_expand(inode, attr->ia_size) ; + if (REISERFS_I(inode)->i_prealloc_count > 0) { + struct reiserfs_transaction_handle th ; + /* we're changing at most 2 bitmaps, inode + super */ + journal_begin(&th, inode->i_sb, 4) ; + reiserfs_discard_prealloc (&th, inode); + journal_end(&th, inode->i_sb, 4) ; + } + if (error) + goto out; + } + } + + if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) || + ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) && + (get_inode_sd_version (inode) == STAT_DATA_V1)) { + /* stat data of format v3.5 has 16 bit uid and gid */ + error = -EINVAL; + goto out; + } + + is_dir: + error = inode_change_ok(inode, attr) ; + + if (!error && attr->ia_valid & ATTR_ATTR_FLAG) + reiserfs_setattr_flags(inode, attr->ia_attr_flags); + + if (!error) { + if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || + (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { + error = reiserfs_chown_xattrs (inode, attr); + + if (!error) + error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; + } + if (!error) + inode_setattr(inode, attr) ; + } + + + if (!error && reiserfs_posixacl (inode->i_sb)) { + if (attr->ia_valid & ATTR_MODE) + error = reiserfs_acl_chmod (inode); + } + +out: + reiserfs_write_unlock(inode->i_sb); + return error ; +} + + struct address_space_operations reiserfs_address_space_operations = { .writepage = reiserfs_writepage,