From 317602f3e01a25320a712195b32fcf19c1297121 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sun, 20 Jul 2008 23:41:24 -0700 Subject: lockd: trivial sparse endian annotations fs/lockd/svcproc.c:115:11: warning: incorrect type in initializer (different base types) fs/lockd/svcproc.c:115:11: expected int [signed] rc fs/lockd/svcproc.c:115:11: got restricted __be32 [usertype] ... and so on... Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: J. Bruce Fields --- fs/lockd/svc4proc.c | 4 ++-- fs/lockd/svcproc.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 39944463..4a714f64 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -83,7 +83,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, { struct nlm_host *host; struct nlm_file *file; - int rc = rpc_success; + __be32 rc = rpc_success; dprintk("lockd: TEST4 called\n"); resp->cookie = argp->cookie; @@ -116,7 +116,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, { struct nlm_host *host; struct nlm_file *file; - int rc = rpc_success; + __be32 rc = rpc_success; dprintk("lockd: LOCK called\n"); diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 76019d2..76262c1 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -112,7 +112,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, { struct nlm_host *host; struct nlm_file *file; - int rc = rpc_success; + __be32 rc = rpc_success; dprintk("lockd: TEST called\n"); resp->cookie = argp->cookie; @@ -146,7 +146,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, { struct nlm_host *host; struct nlm_file *file; - int rc = rpc_success; + __be32 rc = rpc_success; dprintk("lockd: LOCK called\n"); -- cgit v1.1 From bf068ee266f9dbaa6dacb8433a366bb399e7ae5b Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 19 Aug 2008 22:16:43 -0400 Subject: ext4: Handle unwritten extent properly with delayed allocation When using fallocate the buffer_heads are marked unwritten and unmapped. We need to map them in the writepages after a get_block. Otherwise we split the uninit extents, but never write the content to disk. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Mingming Cao Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 59fbbe8..a1c7d76 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1741,6 +1741,13 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical, if (buffer_delay(bh)) { bh->b_blocknr = pblock; clear_buffer_delay(bh); + bh->b_bdev = inode->i_sb->s_bdev; + } else if (buffer_unwritten(bh)) { + bh->b_blocknr = pblock; + clear_buffer_unwritten(bh); + set_buffer_mapped(bh); + set_buffer_new(bh); + bh->b_bdev = inode->i_sb->s_bdev; } else if (buffer_mapped(bh)) BUG_ON(bh->b_blocknr != pblock); @@ -1814,7 +1821,7 @@ static void mpage_da_map_blocks(struct mpage_da_data *mpd) * If blocks are delayed marked, we need to * put actual blocknr and drop delayed bit */ - if (buffer_delay(lbh)) + if (buffer_delay(lbh) || buffer_unwritten(lbh)) mpage_put_bnr_to_bhs(mpd, next, &new); /* go for the remaining blocks */ @@ -1823,7 +1830,8 @@ static void mpage_da_map_blocks(struct mpage_da_data *mpd) } } -#define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | (1 << BH_Delay)) +#define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | \ + (1 << BH_Delay) | (1 << BH_Unwritten)) /* * mpage_add_bh_to_extent - try to add one more block to extent of blocks -- cgit v1.1 From b4df2030858bde986cb6ff2e4b45945f84649e32 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 13 Aug 2008 21:44:34 -0400 Subject: ext4: Fix potential truncate BUG due to i_prealloc_list being non-empty We need to call ext4_discard_reservation() earlier in ext4_truncate(), to avoid a BUG() in ext4_mb_return_to_preallocation(), which is called (ultimately) by ext4_free_blocks(). So we must ditch the blocks on i_prealloc_list before we start freeing the data blocks. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a1c7d76..2d54c82 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3494,6 +3494,9 @@ void ext4_truncate(struct inode *inode) * modify the block allocation tree. */ down_write(&ei->i_data_sem); + + ext4_discard_reservation(inode); + /* * The orphan list entry will now protect us from any crash which * occurs before the truncate completes, so it is now safe to propagate @@ -3563,8 +3566,6 @@ do_indirects: ; } - ext4_discard_reservation(inode); - up_write(&ei->i_data_sem); inode->i_mtime = inode->i_ctime = ext4_current_time(inode); ext4_mark_inode_dirty(handle, inode); -- cgit v1.1 From cd21322616c3af265d39bf15321d436e667a5dd1 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Tue, 19 Aug 2008 22:16:59 -0400 Subject: ext4: Fix delalloc release block reservation for truncate Ext4 will release the reserved blocks for delayed allocations when inode is truncated/unlinked. If there is no reserved block at all, we shouldn't need to do so. But current code still tries to release the reserved blocks regardless whether the counters's value is 0. Continue to do that causes the later calculation to go wrong and a kernel BUG_ON() caught that. This doesn't happen for extent-based files, as the calculation for 0 reserved blocks was right for extent based file. This patch fixed the kernel BUG() due to above reason. It adds checks for 0 to avoid unnecessary release and fix calculation for non-extent files. Signed-off-by: Mingming Cao Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 2d54c82..5e17d5f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1005,6 +1005,9 @@ static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks) */ static int ext4_calc_metadata_amount(struct inode *inode, int blocks) { + if (!blocks) + return 0; + if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) return ext4_ext_calc_metadata_amount(inode, blocks); @@ -1559,7 +1562,25 @@ static void ext4_da_release_space(struct inode *inode, int to_free) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); int total, mdb, mdb_free, release; + if (!to_free) + return; /* Nothing to release, exit */ + spin_lock(&EXT4_I(inode)->i_block_reservation_lock); + + if (!EXT4_I(inode)->i_reserved_data_blocks) { + /* + * if there is no reserved blocks, but we try to free some + * then the counter is messed up somewhere. + * but since this function is called from invalidate + * page, it's harmless to return without any action + */ + printk(KERN_INFO "ext4 delalloc try to release %d reserved " + "blocks for inode %lu, but there is no reserved " + "data blocks\n", to_free, inode->i_ino); + spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); + return; + } + /* recalculate the number of metablocks still need to be reserved */ total = EXT4_I(inode)->i_reserved_data_blocks - to_free; mdb = ext4_calc_metadata_amount(inode, total); -- cgit v1.1 From d015641734cde55d2fce48a6db3983c8a029fe05 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 19 Aug 2008 21:57:43 -0400 Subject: ext4: Fix ext4_dx_readdir hash collision handling This fixes a bug where readdir() would return a directory entry twice if there was a hash collision in an hash tree indexed directory. Signed-off-by: Eugene Dashevsky Signed-off-by: Mike Snitzer Signed-off-by: "Theodore Ts'o" --- fs/ext4/dir.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index d3d23d7..ec8e33b 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -411,7 +411,7 @@ static int call_filldir(struct file * filp, void * dirent, get_dtype(sb, fname->file_type)); if (error) { filp->f_pos = curr_pos; - info->extra_fname = fname->next; + info->extra_fname = fname; return error; } fname = fname->next; @@ -450,11 +450,21 @@ static int ext4_dx_readdir(struct file * filp, * If there are any leftover names on the hash collision * chain, return them first. */ - if (info->extra_fname && - call_filldir(filp, dirent, filldir, info->extra_fname)) - goto finished; + if (info->extra_fname) { + if (call_filldir(filp, dirent, filldir, info->extra_fname)) + goto finished; - if (!info->curr_node) + info->extra_fname = NULL; + info->curr_node = rb_next(info->curr_node); + if (!info->curr_node) { + if (info->next_hash == ~0) { + filp->f_pos = EXT4_HTREE_EOF; + goto finished; + } + info->curr_hash = info->next_hash; + info->curr_minor_hash = 0; + } + } else if (!info->curr_node) info->curr_node = rb_first(&info->root); while (1) { -- cgit v1.1 From 88aa3cff4e9a38b953de9fbc54c96e619a2bb9f9 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 16 Aug 2008 07:57:35 -0400 Subject: ext4: Use ext4_discard_reservations instead of mballoc-specific call In ext4_ext_truncate(), we should use the more generic ext4_discard_reservations() call so we do the right thing when the filesystem is mounted with the nomballoc option. Signed-off-by: "Theodore Ts'o" Reviewed-by: Mingming Cao --- fs/ext4/extents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 612c3d2..7212947 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2819,7 +2819,7 @@ void ext4_ext_truncate(struct inode *inode) down_write(&EXT4_I(inode)->i_data_sem); ext4_ext_invalidate_cache(inode); - ext4_mb_discard_inode_preallocations(inode); + ext4_discard_reservation(inode); /* * TODO: optimization is possible here. -- cgit v1.1 From 37609fd5ae62db75026d9f53096a1fbc35e040d9 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 19 Aug 2008 22:13:41 -0400 Subject: ext4: don't try to resize if there are no reserved gdt blocks left When trying to resize an ext4 fs and you run out of reserved gdt blocks, you get an error that doesn't actually tell you what went wrong, it just says that the gdb it picked is not correct, which is the case since you don't have any reserved gdt blocks left. This patch adds a check to make sure you have reserved gdt blocks to use, and if not prints out a more relevant error. Signed-off-by: Josef Bacik Cc: Cc: Andreas Dilger Signed-off-by: Andrew Morton Signed-off-by: "Theodore Ts'o" --- fs/ext4/resize.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 0a92651..b3d3560 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -773,7 +773,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) if (reserved_gdb || gdb_off == 0) { if (!EXT4_HAS_COMPAT_FEATURE(sb, - EXT4_FEATURE_COMPAT_RESIZE_INODE)){ + EXT4_FEATURE_COMPAT_RESIZE_INODE) + || !le16_to_cpu(es->s_reserved_gdt_blocks)) { ext4_warning(sb, __func__, "No reserved GDT blocks, can't resize"); return -EPERM; -- cgit v1.1 From c001077f4003fa75793bb62979baa6241dd8eb19 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Tue, 19 Aug 2008 22:19:50 -0400 Subject: ext4: Fix bug where we return ENOSPC even though we have plenty of inodes The find_group_flex() function starts with best_flex as the parent_fbg_group, which happens to have 0 inodes free. Some of the flex groups searched have free blocks and free inodes, but the flex_freeb_ratio is < 10, so they're skipped. Then when a group is compared to the current "best" flex group, it does not have more free blocks than "best", so it is skipped as well. This continues until no flex group with free inodes is found which has a proper ratio or which has more free blocks than the "best" group, and we're left with a "best" group that has 0 inodes free, and we return -ENOSPC. We fix this by changing the logic so that if the current "best" flex group has no inodes free, and the current one does have room, it is promoted to the next "best." Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" --- fs/ext4/ialloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 655e760..f344834 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -351,7 +351,7 @@ find_close_to_parent: goto found_flexbg; } - if (best_flex < 0 || + if (flex_group[best_flex].free_inodes == 0 || (flex_group[i].free_blocks > flex_group[best_flex].free_blocks && flex_group[i].free_inodes)) -- cgit v1.1 From a02908f19c819aeec5e3dcf238adaa6deddd70b0 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Tue, 19 Aug 2008 22:16:07 -0400 Subject: ext4: journal credits calulation cleanup and fix for non-extent writepage When considering how many journal credits are needed for modifying a chunk of data, we need to account for the super block, inode block, quota blocks and xattr block, indirect/index blocks, also, group bitmap and group descriptor blocks for new allocation (including data and indirect/index blocks). There are many places in ext4 do the calculation on their own and often missed one or two meta blocks, and often they assume single block allocation, and did not considering the multile chunk of allocation case. This patch is trying to cleanup current journal credit code, provides some common helper funtion to calculate the journal credits, to be used for writepage, writepages, DIO, fallocate, migration, defrag, and for both nonextent and extent files. This patch modified the writepage/write_begin credit caculation for nonextent files, to use the new helper function. It also fixed the problem that writepage on nonextent files did not consider the case blocksize Reviewed-by: Aneesh Kumar K.V Signed-off-by: "Theodore Ts'o" --- fs/ext4/ext4.h | 3 ++ fs/ext4/ext4_jbd2.h | 8 ++++ fs/ext4/inode.c | 131 ++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 108 insertions(+), 34 deletions(-) (limited to 'fs') diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6c7924d..38e661b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1072,6 +1072,7 @@ extern void ext4_set_inode_flags(struct inode *); extern void ext4_get_inode_flags(struct ext4_inode_info *); extern void ext4_set_aops(struct inode *inode); extern int ext4_writepage_trans_blocks(struct inode *); +extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks); extern int ext4_block_truncate_page(handle_t *handle, struct address_space *mapping, loff_t from); extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page); @@ -1227,6 +1228,8 @@ extern const struct inode_operations ext4_fast_symlink_inode_operations; /* extents.c */ extern int ext4_ext_tree_init(handle_t *handle, struct inode *); extern int ext4_ext_writepage_trans_blocks(struct inode *, int); +extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, + int chunk); extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, ext4_lblk_t iblock, unsigned long max_blocks, struct buffer_head *bh_result, diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index eb8bc3a..b455c68 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -51,6 +51,14 @@ EXT4_XATTR_TRANS_BLOCKS - 2 + \ 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) +/* + * Define the number of metadata blocks we need to account to modify data. + * + * This include super block, inode block, quota blocks and xattr blocks + */ +#define EXT4_META_TRANS_BLOCKS(sb) (EXT4_XATTR_TRANS_BLOCKS + \ + 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) + /* Delete operations potentially hit one directory's namespace plus an * entire inode, plus arbitrary amounts of bitmap/indirection data. Be * generous. We can grow the delete transaction later if necessary. */ diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 5e17d5f..a271290 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4354,56 +4354,119 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, return 0; } +static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, + int chunk) +{ + int indirects; + + /* if nrblocks are contiguous */ + if (chunk) { + /* + * With N contiguous data blocks, it need at most + * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks + * 2 dindirect blocks + * 1 tindirect block + */ + indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb); + return indirects + 3; + } + /* + * if nrblocks are not contiguous, worse case, each block touch + * a indirect block, and each indirect block touch a double indirect + * block, plus a triple indirect block + */ + indirects = nrblocks * 2 + 1; + return indirects; +} + +static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) +{ + if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) + return ext4_indirect_trans_blocks(inode, nrblocks, 0); + return ext4_ext_index_trans_blocks(inode, nrblocks, 0); +} /* - * How many blocks doth make a writepage()? + * Account for index blocks, block groups bitmaps and block group + * descriptor blocks if modify datablocks and index blocks + * worse case, the indexs blocks spread over different block groups * - * With N blocks per page, it may be: - * N data blocks - * 2 indirect block - * 2 dindirect - * 1 tindirect - * N+5 bitmap blocks (from the above) - * N+5 group descriptor summary blocks - * 1 inode block - * 1 superblock. - * 2 * EXT4_SINGLEDATA_TRANS_BLOCKS for the quote files + * If datablocks are discontiguous, they are possible to spread over + * different block groups too. If they are contiugous, with flexbg, + * they could still across block group boundary. * - * 3 * (N + 5) + 2 + 2 * EXT4_SINGLEDATA_TRANS_BLOCKS + * Also account for superblock, inode, quota and xattr blocks + */ +int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk) +{ + int groups, gdpblocks; + int idxblocks; + int ret = 0; + + /* + * How many index blocks need to touch to modify nrblocks? + * The "Chunk" flag indicating whether the nrblocks is + * physically contiguous on disk + * + * For Direct IO and fallocate, they calls get_block to allocate + * one single extent at a time, so they could set the "Chunk" flag + */ + idxblocks = ext4_index_trans_blocks(inode, nrblocks, chunk); + + ret = idxblocks; + + /* + * Now let's see how many group bitmaps and group descriptors need + * to account + */ + groups = idxblocks; + if (chunk) + groups += 1; + else + groups += nrblocks; + + gdpblocks = groups; + if (groups > EXT4_SB(inode->i_sb)->s_groups_count) + groups = EXT4_SB(inode->i_sb)->s_groups_count; + if (groups > EXT4_SB(inode->i_sb)->s_gdb_count) + gdpblocks = EXT4_SB(inode->i_sb)->s_gdb_count; + + /* bitmaps and block group descriptor blocks */ + ret += groups + gdpblocks; + + /* Blocks for super block, inode, quota and xattr blocks */ + ret += EXT4_META_TRANS_BLOCKS(inode->i_sb); + + return ret; +} + +/* + * Calulate the total number of credits to reserve to fit + * the modification of a single pages into a single transaction * - * With ordered or writeback data it's the same, less the N data blocks. + * This could be called via ext4_write_begin() or later + * ext4_da_writepages() in delalyed allocation case. * - * If the inode's direct blocks can hold an integral number of pages then a - * page cannot straddle two indirect blocks, and we can only touch one indirect - * and dindirect block, and the "5" above becomes "3". + * In both case it's possible that we could allocating multiple + * chunks of blocks. We need to consider the worse case, when + * one new block per extent. * - * This still overestimates under most circumstances. If we were to pass the - * start and end offsets in here as well we could do block_to_path() on each - * block and work out the exact number of indirects which are touched. Pah. + * For Direct IO and fallocate, the journal credits reservation + * is based on one single extent allocation, so they could use + * EXT4_DATA_TRANS_BLOCKS to get the needed credit to log a single + * chunk of allocation needs. */ - int ext4_writepage_trans_blocks(struct inode *inode) { int bpp = ext4_journal_blocks_per_page(inode); - int indirects = (EXT4_NDIR_BLOCKS % bpp) ? 5 : 3; int ret; - if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) - return ext4_ext_writepage_trans_blocks(inode, bpp); + ret = ext4_meta_trans_blocks(inode, bpp, 0); + /* Account for data blocks for journalled mode */ if (ext4_should_journal_data(inode)) - ret = 3 * (bpp + indirects) + 2; - else - ret = 2 * (bpp + indirects) + 2; - -#ifdef CONFIG_QUOTA - /* We know that structure was already allocated during DQUOT_INIT so - * we will be updating only the data blocks + inodes */ - ret += 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); -#endif - + ret += bpp; return ret; } - /* * The caller must have previously called ext4_reserve_inode_write(). * Give this, we know that the caller already has write access to iloc->bh. -- cgit v1.1 From ee12b630687d510f6f4b6d4acdc4e267fd4adeda Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Tue, 19 Aug 2008 22:16:05 -0400 Subject: ext4: journal credits reservation fixes for extent file writepage This patch modified the writepage/write_begin credit calculation for extent files, to use the credits caculation helper function. The current calculation of how many index/leaf blocks should be accounted is too conservetive, it always considered the worse case, where the tree level is 5, and in the case of multiple chunk allocations, it always assumed no blocks were dirtied in common across the allocations. This path uses the accurate depth of the inode with some extras to calculate the index blocks, and also less conservative in the case of multiple allocation accounting. Signed-off-by: Mingming Cao Reviewed-by: Aneesh Kumar K.V Signed-off-by: "Theodore Ts'o" --- fs/ext4/ext4_extents.h | 4 +- fs/ext4/extents.c | 104 +++++++++++++++++++++---------------------------- fs/ext4/migrate.c | 3 +- 3 files changed, 49 insertions(+), 62 deletions(-) (limited to 'fs') diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h index 6c166c0..d33dc56 100644 --- a/fs/ext4/ext4_extents.h +++ b/fs/ext4/ext4_extents.h @@ -216,7 +216,9 @@ extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks); extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *); extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t); extern int ext4_extent_tree_init(handle_t *, struct inode *); -extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *); +extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode, + int num, + struct ext4_ext_path *path); extern int ext4_ext_try_to_merge(struct inode *inode, struct ext4_ext_path *path, struct ext4_extent *); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 7212947..5c5dd3a 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1747,54 +1747,61 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, } /* - * ext4_ext_calc_credits_for_insert: - * This routine returns max. credits that the extent tree can consume. - * It should be OK for low-performance paths like ->writepage() - * To allow many writing processes to fit into a single transaction, - * the caller should calculate credits under i_data_sem and - * pass the actual path. + * ext4_ext_calc_credits_for_single_extent: + * This routine returns max. credits that needed to insert an extent + * to the extent tree. + * When pass the actual path, the caller should calculate credits + * under i_data_sem. */ -int ext4_ext_calc_credits_for_insert(struct inode *inode, +int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int num, struct ext4_ext_path *path) { - int depth, needed; - if (path) { + int depth = ext_depth(inode); + int ret; + /* probably there is space in leaf? */ - depth = ext_depth(inode); if (le16_to_cpu(path[depth].p_hdr->eh_entries) - < le16_to_cpu(path[depth].p_hdr->eh_max)) - return 1; - } + < le16_to_cpu(path[depth].p_hdr->eh_max)) { - /* - * given 32-bit logical block (4294967296 blocks), max. tree - * can be 4 levels in depth -- 4 * 340^4 == 53453440000. - * Let's also add one more level for imbalance. - */ - depth = 5; - - /* allocation of new data block(s) */ - needed = 2; + /* + * There are some space in the leaf tree, no + * need to account for leaf block credit + * + * bitmaps and block group descriptor blocks + * and other metadat blocks still need to be + * accounted. + */ + /* 1 one bitmap, 1 block group descriptor */ + ret = 2 + EXT4_META_TRANS_BLOCKS(inode->i_sb); + } + } - /* - * tree can be full, so it would need to grow in depth: - * we need one credit to modify old root, credits for - * new root will be added in split accounting - */ - needed += 1; + return ext4_meta_trans_blocks(inode, num, 1); +} - /* - * Index split can happen, we would need: - * allocate intermediate indexes (bitmap + group) - * + change two blocks at each level, but root (already included) - */ - needed += (depth * 2) + (depth * 2); +/* + * How many index/leaf blocks need to change/allocate to modify nrblocks? + * + * if nrblocks are fit in a single extent (chunk flag is 1), then + * in the worse case, each tree level index/leaf need to be changed + * if the tree split due to insert a new extent, then the old tree + * index/leaf need to be updated too + * + * If the nrblocks are discontiguous, they could cause + * the whole tree split more than once, but this is really rare. + */ +int ext4_ext_index_trans_blocks(struct inode *inode, int num, int chunk) +{ + int index; + int depth = ext_depth(inode); - /* any allocation modifies superblock */ - needed += 1; + if (chunk) + index = depth * 2; + else + index = depth * 3; - return needed; + return index; } static int ext4_remove_blocks(handle_t *handle, struct inode *inode, @@ -1921,9 +1928,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, correct_index = 1; credits += (ext_depth(inode)) + 1; } -#ifdef CONFIG_QUOTA credits += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); -#endif err = ext4_ext_journal_restart(handle, credits); if (err) @@ -2858,27 +2863,6 @@ out_stop: ext4_journal_stop(handle); } -/* - * ext4_ext_writepage_trans_blocks: - * calculate max number of blocks we could modify - * in order to allocate new block for an inode - */ -int ext4_ext_writepage_trans_blocks(struct inode *inode, int num) -{ - int needed; - - needed = ext4_ext_calc_credits_for_insert(inode, NULL); - - /* caller wants to allocate num blocks, but note it includes sb */ - needed = needed * num - (num - 1); - -#ifdef CONFIG_QUOTA - needed += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); -#endif - - return needed; -} - static void ext4_falloc_update_inode(struct inode *inode, int mode, loff_t new_size, int update_ctime) { diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index b9e077b..46fc0b5 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -53,7 +53,8 @@ static int finish_range(handle_t *handle, struct inode *inode, * credit. But below we try to not accumalate too much * of them by restarting the journal. */ - needed = ext4_ext_calc_credits_for_insert(inode, path); + needed = ext4_ext_calc_credits_for_single_extent(inode, + lb->last_block - lb->first_block + 1, path); /* * Make sure the credit we accumalated is not really high -- cgit v1.1 From f3bd1f3fa8ca7ec70cfd87aa94dc5e1a260901f2 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Tue, 19 Aug 2008 22:16:03 -0400 Subject: ext4: journal credits reservation fixes for DIO, fallocate DIO and fallocate credit calculation is different than writepage, as they do start a new journal right for each call to ext4_get_blocks_wrap(). This patch uses the helper function in DIO and fallocate case, passing a flag indicating that the modified data are contigous thus could account less indirect/index blocks. This patch also fixed the journal credit reservation for direct I/O (DIO). Previously the estimated credits for DIO only was calculated for non-extent files, which was not enough if the file is extent-based. Also fixed was fallocate double-counting credits for modifying the the superblock. Signed-off-by: Mingming Cao Reviewed-by: Aneesh Kumar K.V Signed-off-by: "Theodore Ts'o" --- fs/ext4/ext4.h | 1 + fs/ext4/extents.c | 11 +++++------ fs/ext4/inode.c | 45 ++++++++++++++++++++++++--------------------- 3 files changed, 30 insertions(+), 27 deletions(-) (limited to 'fs') diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 38e661b..2950032 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1073,6 +1073,7 @@ extern void ext4_get_inode_flags(struct ext4_inode_info *); extern void ext4_set_aops(struct inode *inode); extern int ext4_writepage_trans_blocks(struct inode *); extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks); +extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); extern int ext4_block_truncate_page(handle_t *handle, struct address_space *mapping, loff_t from); extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 5c5dd3a..5596b70 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1758,7 +1758,7 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int num, { if (path) { int depth = ext_depth(inode); - int ret; + int ret = 0; /* probably there is space in leaf? */ if (le16_to_cpu(path[depth].p_hdr->eh_entries) @@ -1777,7 +1777,7 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int num, } } - return ext4_meta_trans_blocks(inode, num, 1); + return ext4_chunk_trans_blocks(inode, num); } /* @@ -2810,7 +2810,7 @@ void ext4_ext_truncate(struct inode *inode) /* * probably first extent we're gonna free will be last in block */ - err = ext4_writepage_trans_blocks(inode) + 3; + err = ext4_writepage_trans_blocks(inode); handle = ext4_journal_start(inode, err); if (IS_ERR(handle)) return; @@ -2923,10 +2923,9 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) - block; /* - * credits to insert 1 extent into extent tree + buffers to be able to - * modify 1 super block, 1 block bitmap and 1 group descriptor. + * credits to insert 1 extent into extent tree */ - credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + 3; + credits = ext4_chunk_trans_blocks(inode, max_blocks); mutex_lock(&inode->i_mutex); retry: while (ret >= 0 && ret < max_blocks) { diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a271290..ffc95ba 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1044,18 +1044,6 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used) spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); } -/* Maximum number of blocks we map for direct IO at once. */ -#define DIO_MAX_BLOCKS 4096 -/* - * Number of credits we need for writing DIO_MAX_BLOCKS: - * We need sb + group descriptor + bitmap + inode -> 4 - * For B blocks with A block pointers per block we need: - * 1 (triple ind.) + (B/A/A + 2) (doubly ind.) + (B/A + 2) (indirect). - * If we plug in 4096 for B and 256 for A (for 1KB block size), we get 25. - */ -#define DIO_CREDITS 25 - - /* * The ext4_get_blocks_wrap() function try to look up the requested blocks, * and returns if the blocks are already mapped. @@ -1167,19 +1155,23 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, return retval; } +/* Maximum number of blocks we map for direct IO at once. */ +#define DIO_MAX_BLOCKS 4096 + static int ext4_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { handle_t *handle = ext4_journal_current_handle(); int ret = 0, started = 0; unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; + int dio_credits; if (create && !handle) { /* Direct IO write... */ if (max_blocks > DIO_MAX_BLOCKS) max_blocks = DIO_MAX_BLOCKS; - handle = ext4_journal_start(inode, DIO_CREDITS + - 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb)); + dio_credits = ext4_chunk_trans_blocks(inode, max_blocks); + handle = ext4_journal_start(inode, dio_credits); if (IS_ERR(handle)) { ret = PTR_ERR(handle); goto out; @@ -2243,7 +2235,7 @@ static int ext4_da_writepage(struct page *page, * for DIO, writepages, and truncate */ #define EXT4_MAX_WRITEBACK_PAGES DIO_MAX_BLOCKS -#define EXT4_MAX_WRITEBACK_CREDITS DIO_CREDITS +#define EXT4_MAX_WRITEBACK_CREDITS 25 static int ext4_da_writepages(struct address_space *mapping, struct writeback_control *wbc) @@ -4441,7 +4433,8 @@ int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk) /* * Calulate the total number of credits to reserve to fit - * the modification of a single pages into a single transaction + * the modification of a single pages into a single transaction, + * which may include multiple chunks of block allocations. * * This could be called via ext4_write_begin() or later * ext4_da_writepages() in delalyed allocation case. @@ -4449,11 +4442,6 @@ int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk) * In both case it's possible that we could allocating multiple * chunks of blocks. We need to consider the worse case, when * one new block per extent. - * - * For Direct IO and fallocate, the journal credits reservation - * is based on one single extent allocation, so they could use - * EXT4_DATA_TRANS_BLOCKS to get the needed credit to log a single - * chunk of allocation needs. */ int ext4_writepage_trans_blocks(struct inode *inode) { @@ -4467,6 +4455,21 @@ int ext4_writepage_trans_blocks(struct inode *inode) ret += bpp; return ret; } + +/* + * Calculate the journal credits for a chunk of data modification. + * + * This is called from DIO, fallocate or whoever calling + * ext4_get_blocks_wrap() to map/allocate a chunk of contigous disk blocks. + * + * journal buffers for data blocks are not included here, as DIO + * and fallocate do no need to journal data buffers. + */ +int ext4_chunk_trans_blocks(struct inode *inode, int nrblocks) +{ + return ext4_meta_trans_blocks(inode, nrblocks, 1); +} + /* * The caller must have previously called ext4_reserve_inode_write(). * Give this, we know that the caller already has write access to iloc->bh. -- cgit v1.1 From a1d6cc563bfdf1bf2829d3e6ce4d8b774251796b Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 19 Aug 2008 21:55:02 -0400 Subject: ext4: Rework the ext4_da_writepages() function With the below changes we reserve credit needed to insert only one extent resulting from a call to single get_block. This makes sure we don't take too much journal credits during writeout. We also don't limit the pages to write. That means we loop through the dirty pages building largest possible contiguous block request. Then we issue a single get_block request. We may get less block that we requested. If so we would end up not mapping some of the buffer_heads. That means those buffer_heads are still marked delay. Later in the writepage callback via __mpage_writepage we redirty those pages. We should also not limit/throttle wbc->nr_to_write in the filesystem writepages callback. That cause wrong behaviour in generic_sync_sb_inodes caused by wbc->nr_to_write being <= 0 Signed-off-by: Aneesh Kumar K.V Reviewed-by: Mingming Cao Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 201 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 113 insertions(+), 88 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ffc95ba..8dd22ea 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -41,6 +41,8 @@ #include "acl.h" #include "ext4_extents.h" +#define MPAGE_DA_EXTENT_TAIL 0x01 + static inline int ext4_begin_ordered_truncate(struct inode *inode, loff_t new_size) { @@ -1626,11 +1628,13 @@ struct mpage_da_data { unsigned long first_page, next_page; /* extent of pages */ get_block_t *get_block; struct writeback_control *wbc; + int io_done; + long pages_written; }; /* * mpage_da_submit_io - walks through extent of pages and try to write - * them with __mpage_writepage() + * them with writepage() call back * * @mpd->inode: inode * @mpd->first_page: first page of the extent @@ -1645,18 +1649,11 @@ struct mpage_da_data { static int mpage_da_submit_io(struct mpage_da_data *mpd) { struct address_space *mapping = mpd->inode->i_mapping; - struct mpage_data mpd_pp = { - .bio = NULL, - .last_block_in_bio = 0, - .get_block = mpd->get_block, - .use_writepage = 1, - }; int ret = 0, err, nr_pages, i; unsigned long index, end; struct pagevec pvec; BUG_ON(mpd->next_page <= mpd->first_page); - pagevec_init(&pvec, 0); index = mpd->first_page; end = mpd->next_page - 1; @@ -1674,8 +1671,9 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd) break; index++; - err = __mpage_writepage(page, mpd->wbc, &mpd_pp); - + err = mapping->a_ops->writepage(page, mpd->wbc); + if (!err) + mpd->pages_written++; /* * In error case, we have to continue because * remaining pages are still locked @@ -1686,9 +1684,6 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd) } pagevec_release(&pvec); } - if (mpd_pp.bio) - mpage_bio_submit(WRITE, mpd_pp.bio); - return ret; } @@ -1711,7 +1706,7 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical, int blocks = exbh->b_size >> inode->i_blkbits; sector_t pblock = exbh->b_blocknr, cur_logical; struct buffer_head *head, *bh; - unsigned long index, end; + pgoff_t index, end; struct pagevec pvec; int nr_pages, i; @@ -1796,13 +1791,11 @@ static inline void __unmap_underlying_blocks(struct inode *inode, * * The function skips space we know is already mapped to disk blocks. * - * The function ignores errors ->get_block() returns, thus real - * error handling is postponed to __mpage_writepage() */ static void mpage_da_map_blocks(struct mpage_da_data *mpd) { + int err = 0; struct buffer_head *lbh = &mpd->lbh; - int err = 0, remain = lbh->b_size; sector_t next = lbh->b_blocknr; struct buffer_head new; @@ -1812,35 +1805,32 @@ static void mpage_da_map_blocks(struct mpage_da_data *mpd) if (buffer_mapped(lbh) && !buffer_delay(lbh)) return; - while (remain) { - new.b_state = lbh->b_state; - new.b_blocknr = 0; - new.b_size = remain; - err = mpd->get_block(mpd->inode, next, &new, 1); - if (err) { - /* - * Rather than implement own error handling - * here, we just leave remaining blocks - * unallocated and try again with ->writepage() - */ - break; - } - BUG_ON(new.b_size == 0); + new.b_state = lbh->b_state; + new.b_blocknr = 0; + new.b_size = lbh->b_size; - if (buffer_new(&new)) - __unmap_underlying_blocks(mpd->inode, &new); + /* + * If we didn't accumulate anything + * to write simply return + */ + if (!new.b_size) + return; + err = mpd->get_block(mpd->inode, next, &new, 1); + if (err) + return; + BUG_ON(new.b_size == 0); - /* - * If blocks are delayed marked, we need to - * put actual blocknr and drop delayed bit - */ - if (buffer_delay(lbh) || buffer_unwritten(lbh)) - mpage_put_bnr_to_bhs(mpd, next, &new); + if (buffer_new(&new)) + __unmap_underlying_blocks(mpd->inode, &new); - /* go for the remaining blocks */ - next += new.b_size >> mpd->inode->i_blkbits; - remain -= new.b_size; - } + /* + * If blocks are delayed marked, we need to + * put actual blocknr and drop delayed bit + */ + if (buffer_delay(lbh) || buffer_unwritten(lbh)) + mpage_put_bnr_to_bhs(mpd, next, &new); + + return; } #define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | \ @@ -1886,13 +1876,9 @@ static void mpage_add_bh_to_extent(struct mpage_da_data *mpd, * need to flush current extent and start new one */ mpage_da_map_blocks(mpd); - - /* - * Now start a new extent - */ - lbh->b_size = bh->b_size; - lbh->b_state = bh->b_state & BH_FLAGS; - lbh->b_blocknr = logical; + mpage_da_submit_io(mpd); + mpd->io_done = 1; + return; } /* @@ -1912,17 +1898,35 @@ static int __mpage_da_writepage(struct page *page, struct buffer_head *bh, *head, fake; sector_t logical; + if (mpd->io_done) { + /* + * Rest of the page in the page_vec + * redirty then and skip then. We will + * try to to write them again after + * starting a new transaction + */ + redirty_page_for_writepage(wbc, page); + unlock_page(page); + return MPAGE_DA_EXTENT_TAIL; + } /* * Can we merge this page to current extent? */ if (mpd->next_page != page->index) { /* * Nope, we can't. So, we map non-allocated blocks - * and start IO on them using __mpage_writepage() + * and start IO on them using writepage() */ if (mpd->next_page != mpd->first_page) { mpage_da_map_blocks(mpd); mpage_da_submit_io(mpd); + /* + * skip rest of the page in the page_vec + */ + mpd->io_done = 1; + redirty_page_for_writepage(wbc, page); + unlock_page(page); + return MPAGE_DA_EXTENT_TAIL; } /* @@ -1953,6 +1957,8 @@ static int __mpage_da_writepage(struct page *page, set_buffer_dirty(bh); set_buffer_uptodate(bh); mpage_add_bh_to_extent(mpd, logical, bh); + if (mpd->io_done) + return MPAGE_DA_EXTENT_TAIL; } else { /* * Page with regular buffer heads, just add all dirty ones @@ -1961,8 +1967,12 @@ static int __mpage_da_writepage(struct page *page, bh = head; do { BUG_ON(buffer_locked(bh)); - if (buffer_dirty(bh)) + if (buffer_dirty(bh) && + (!buffer_mapped(bh) || buffer_delay(bh))) { mpage_add_bh_to_extent(mpd, logical, bh); + if (mpd->io_done) + return MPAGE_DA_EXTENT_TAIL; + } logical++; } while ((bh = bh->b_this_page) != head); } @@ -1981,22 +1991,13 @@ static int __mpage_da_writepage(struct page *page, * * This is a library function, which implements the writepages() * address_space_operation. - * - * In order to avoid duplication of logic that deals with partial pages, - * multiple bio per page, etc, we find non-allocated blocks, allocate - * them with minimal calls to ->get_block() and re-use __mpage_writepage() - * - * It's important that we call __mpage_writepage() only once for each - * involved page, otherwise we'd have to implement more complicated logic - * to deal with pages w/o PG_lock or w/ PG_writeback and so on. - * - * See comments to mpage_writepages() */ static int mpage_da_writepages(struct address_space *mapping, struct writeback_control *wbc, get_block_t get_block) { struct mpage_da_data mpd; + long to_write; int ret; if (!get_block) @@ -2010,17 +2011,22 @@ static int mpage_da_writepages(struct address_space *mapping, mpd.first_page = 0; mpd.next_page = 0; mpd.get_block = get_block; + mpd.io_done = 0; + mpd.pages_written = 0; + + to_write = wbc->nr_to_write; ret = write_cache_pages(mapping, wbc, __mpage_da_writepage, &mpd); /* * Handle last extent of pages */ - if (mpd.next_page != mpd.first_page) { + if (!mpd.io_done && mpd.next_page != mpd.first_page) { mpage_da_map_blocks(&mpd); mpage_da_submit_io(&mpd); } + wbc->nr_to_write = to_write - mpd.pages_written; return ret; } @@ -2238,7 +2244,7 @@ static int ext4_da_writepage(struct page *page, #define EXT4_MAX_WRITEBACK_CREDITS 25 static int ext4_da_writepages(struct address_space *mapping, - struct writeback_control *wbc) + struct writeback_control *wbc) { struct inode *inode = mapping->host; handle_t *handle = NULL; @@ -2246,42 +2252,53 @@ static int ext4_da_writepages(struct address_space *mapping, int ret = 0; long to_write; loff_t range_start = 0; + long pages_skipped = 0; /* * No pages to write? This is mainly a kludge to avoid starting * a transaction for special inodes like journal inode on last iput() * because that could violate lock ordering on umount */ - if (!mapping->nrpages) + if (!mapping->nrpages || !mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) return 0; - /* - * Estimate the worse case needed credits to write out - * EXT4_MAX_BUF_BLOCKS pages - */ - needed_blocks = EXT4_MAX_WRITEBACK_CREDITS; - - to_write = wbc->nr_to_write; - if (!wbc->range_cyclic) { + if (!wbc->range_cyclic) /* * If range_cyclic is not set force range_cont * and save the old writeback_index */ wbc->range_cont = 1; - range_start = wbc->range_start; - } - while (!ret && to_write) { + range_start = wbc->range_start; + pages_skipped = wbc->pages_skipped; + +restart_loop: + to_write = wbc->nr_to_write; + while (!ret && to_write > 0) { + + /* + * we insert one extent at a time. So we need + * credit needed for single extent allocation. + * journalled mode is currently not supported + * by delalloc + */ + BUG_ON(ext4_should_journal_data(inode)); + needed_blocks = EXT4_DATA_TRANS_BLOCKS(inode->i_sb); + /* start a new transaction*/ handle = ext4_journal_start(inode, needed_blocks); if (IS_ERR(handle)) { ret = PTR_ERR(handle); + printk(KERN_EMERG "%s: jbd2_start: " + "%ld pages, ino %lu; err %d\n", __func__, + wbc->nr_to_write, inode->i_ino, ret); + dump_stack(); goto out_writepages; } if (ext4_should_order_data(inode)) { /* * With ordered mode we need to add - * the inode to the journal handle + * the inode to the journal handl * when we do block allocation. */ ret = ext4_jbd2_file_inode(handle, inode); @@ -2289,20 +2306,20 @@ static int ext4_da_writepages(struct address_space *mapping, ext4_journal_stop(handle); goto out_writepages; } - } - /* - * set the max dirty pages could be write at a time - * to fit into the reserved transaction credits - */ - if (wbc->nr_to_write > EXT4_MAX_WRITEBACK_PAGES) - wbc->nr_to_write = EXT4_MAX_WRITEBACK_PAGES; to_write -= wbc->nr_to_write; ret = mpage_da_writepages(mapping, wbc, - ext4_da_get_block_write); + ext4_da_get_block_write); ext4_journal_stop(handle); - if (wbc->nr_to_write) { + if (ret == MPAGE_DA_EXTENT_TAIL) { + /* + * got one extent now try with + * rest of the pages + */ + to_write += wbc->nr_to_write; + ret = 0; + } else if (wbc->nr_to_write) { /* * There is no more writeout needed * or we requested for a noblocking writeout @@ -2314,10 +2331,18 @@ static int ext4_da_writepages(struct address_space *mapping, wbc->nr_to_write = to_write; } + if (wbc->range_cont && (pages_skipped != wbc->pages_skipped)) { + /* We skipped pages in this loop */ + wbc->range_start = range_start; + wbc->nr_to_write = to_write + + wbc->pages_skipped - pages_skipped; + wbc->pages_skipped = pages_skipped; + goto restart_loop; + } + out_writepages: wbc->nr_to_write = to_write; - if (range_start) - wbc->range_start = range_start; + wbc->range_start = range_start; return ret; } -- cgit v1.1 From 525f4ed8dcb72c71b306a78ecbf06f41d08fe441 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Tue, 19 Aug 2008 22:15:58 -0400 Subject: ext4: journal credit fix for the delayed allocation's writepages() function Previous delalloc writepages implementation started a new transaction outside of a loop which called get_block() to do the block allocation. Since we didn't know exactly how many blocks would need to be allocated, the estimated journal credits required was very conservative and caused many issues. With the reworked delayed allocation, a new transaction is created for each get_block(), thus we don't need to guess how many credits for the multiple chunk of allocation. We start every transaction with enough credits for inserting a single exent. When estimate the credits for indirect blocks to allocate a chunk of blocks, we need to know the number of data blocks to allocate. We use the total number of reserved delalloc datablocks; if that is too big, for non-extent files, we need to limit the number of blocks to EXT4_MAX_TRANS_BLOCKS. Code cleanup from Aneesh. Signed-off-by: Mingming Cao Reviewed-off-by: Aneesh Kumar K.V Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 8 +++--- fs/ext4/inode.c | 74 ++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 24 deletions(-) (limited to 'fs') diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 5596b70..b24d3c5 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1753,7 +1753,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, * When pass the actual path, the caller should calculate credits * under i_data_sem. */ -int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int num, +int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int nrblocks, struct ext4_ext_path *path) { if (path) { @@ -1772,12 +1772,12 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int num, * and other metadat blocks still need to be * accounted. */ - /* 1 one bitmap, 1 block group descriptor */ + /* 1 bitmap, 1 block group descriptor */ ret = 2 + EXT4_META_TRANS_BLOCKS(inode->i_sb); } } - return ext4_chunk_trans_blocks(inode, num); + return ext4_chunk_trans_blocks(inode, nrblocks); } /* @@ -1791,7 +1791,7 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int num, * If the nrblocks are discontiguous, they could cause * the whole tree split more than once, but this is really rare. */ -int ext4_ext_index_trans_blocks(struct inode *inode, int num, int chunk) +int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) { int index; int depth = ext_depth(inode); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8dd22ea..d1906d9 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1848,29 +1848,53 @@ static void mpage_da_map_blocks(struct mpage_da_data *mpd) static void mpage_add_bh_to_extent(struct mpage_da_data *mpd, sector_t logical, struct buffer_head *bh) { - struct buffer_head *lbh = &mpd->lbh; sector_t next; + size_t b_size = bh->b_size; + struct buffer_head *lbh = &mpd->lbh; + int nrblocks = lbh->b_size >> mpd->inode->i_blkbits; - next = lbh->b_blocknr + (lbh->b_size >> mpd->inode->i_blkbits); - + /* check if thereserved journal credits might overflow */ + if (!(EXT4_I(mpd->inode)->i_flags & EXT4_EXTENTS_FL)) { + if (nrblocks >= EXT4_MAX_TRANS_DATA) { + /* + * With non-extent format we are limited by the journal + * credit available. Total credit needed to insert + * nrblocks contiguous blocks is dependent on the + * nrblocks. So limit nrblocks. + */ + goto flush_it; + } else if ((nrblocks + (b_size >> mpd->inode->i_blkbits)) > + EXT4_MAX_TRANS_DATA) { + /* + * Adding the new buffer_head would make it cross the + * allowed limit for which we have journal credit + * reserved. So limit the new bh->b_size + */ + b_size = (EXT4_MAX_TRANS_DATA - nrblocks) << + mpd->inode->i_blkbits; + /* we will do mpage_da_submit_io in the next loop */ + } + } /* * First block in the extent */ if (lbh->b_size == 0) { lbh->b_blocknr = logical; - lbh->b_size = bh->b_size; + lbh->b_size = b_size; lbh->b_state = bh->b_state & BH_FLAGS; return; } + next = lbh->b_blocknr + nrblocks; /* * Can we merge the block to our big extent? */ if (logical == next && (bh->b_state & BH_FLAGS) == lbh->b_state) { - lbh->b_size += bh->b_size; + lbh->b_size += b_size; return; } +flush_it: /* * We couldn't merge the block to our extent, so we * need to flush current extent and start new one @@ -2231,17 +2255,29 @@ static int ext4_da_writepage(struct page *page, } /* - * For now just follow the DIO way to estimate the max credits - * needed to write out EXT4_MAX_WRITEBACK_PAGES. - * todo: need to calculate the max credits need for - * extent based files, currently the DIO credits is based on - * indirect-blocks mapping way. - * - * Probably should have a generic way to calculate credits - * for DIO, writepages, and truncate + * This is called via ext4_da_writepages() to + * calulate the total number of credits to reserve to fit + * a single extent allocation into a single transaction, + * ext4_da_writpeages() will loop calling this before + * the block allocation. */ -#define EXT4_MAX_WRITEBACK_PAGES DIO_MAX_BLOCKS -#define EXT4_MAX_WRITEBACK_CREDITS 25 + +static int ext4_da_writepages_trans_blocks(struct inode *inode) +{ + int max_blocks = EXT4_I(inode)->i_reserved_data_blocks; + + /* + * With non-extent format the journal credit needed to + * insert nrblocks contiguous block is dependent on + * number of contiguous block. So we will limit + * number of contiguous block to a sane value + */ + if (!(inode->i_flags & EXT4_EXTENTS_FL) && + (max_blocks > EXT4_MAX_TRANS_DATA)) + max_blocks = EXT4_MAX_TRANS_DATA; + + return ext4_chunk_trans_blocks(inode, max_blocks); +} static int ext4_da_writepages(struct address_space *mapping, struct writeback_control *wbc) @@ -2283,7 +2319,7 @@ restart_loop: * by delalloc */ BUG_ON(ext4_should_journal_data(inode)); - needed_blocks = EXT4_DATA_TRANS_BLOCKS(inode->i_sb); + needed_blocks = ext4_da_writepages_trans_blocks(inode); /* start a new transaction*/ handle = ext4_journal_start(inode, needed_blocks); @@ -4461,11 +4497,9 @@ int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk) * the modification of a single pages into a single transaction, * which may include multiple chunks of block allocations. * - * This could be called via ext4_write_begin() or later - * ext4_da_writepages() in delalyed allocation case. + * This could be called via ext4_write_begin() * - * In both case it's possible that we could allocating multiple - * chunks of blocks. We need to consider the worse case, when + * We need to consider the worse case, when * one new block per extent. */ int ext4_writepage_trans_blocks(struct inode *inode) -- cgit v1.1 From 16eb72956496594d023a7d7cd14a86404ad195ad Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 19 Aug 2008 21:16:54 -0400 Subject: ext4: make sure ext4_has_free_blocks returns 0 for ENOSPC Fix ext4_has_free_blocks() to return 0 when we don't have enough space. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Mingming Cao Signed-off-by: "Theodore Ts'o" --- fs/ext4/balloc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 1ae5004..e9fa960 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -1626,6 +1626,9 @@ ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi, free_blocks = percpu_counter_sum_and_set(&sbi->s_freeblocks_counter); #endif + if (free_blocks <= root_blocks) + /* we don't have free space */ + return 0; if (free_blocks - root_blocks < nblocks) return free_blocks - root_blocks; return nblocks; -- cgit v1.1 From 91246c009094142f95ecc7573b7caed2bcef52c7 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 19 Aug 2008 21:14:52 -0400 Subject: ext4: Initialize writeback_index to 0 when allocating a new inode The write_cache_pages() function uses the mapping->writeback_index as the starting index to write out when range_cyclic is set. Properly initialize writeback_index so that we start the writeout at index 0. This was found when debugging the small file fragmentation on ext4. Signed-off-by: Aneesh Kumar K.V Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d5d7795..566344b 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -568,6 +568,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) #endif ei->i_block_alloc_info = NULL; ei->vfs_inode.i_version = 1; + ei->vfs_inode.i_data.writeback_index = 0; memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); INIT_LIST_HEAD(&ei->i_prealloc_list); spin_lock_init(&ei->i_prealloc_lock); -- cgit v1.1 From 5e745b041f2ccad63077118b40468521306f3962 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Mon, 18 Aug 2008 18:00:57 -0400 Subject: ext4: Fix small file fragmentation For small file block allocations, mballoc uses per cpu prealloc space. Use goal block when searching for the right prealloc space. Also make sure ext4_da_writepages tries to write all the pages for small files in single attempt Signed-off-by: Aneesh Kumar K.V Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 21 +++++++++++++++------ fs/ext4/mballoc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 61 insertions(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index d1906d9..7e91913e 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2282,13 +2282,12 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode) static int ext4_da_writepages(struct address_space *mapping, struct writeback_control *wbc) { - struct inode *inode = mapping->host; handle_t *handle = NULL; - int needed_blocks; - int ret = 0; - long to_write; loff_t range_start = 0; - long pages_skipped = 0; + struct inode *inode = mapping->host; + int needed_blocks, ret = 0, nr_to_writebump = 0; + long to_write, pages_skipped = 0; + struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb); /* * No pages to write? This is mainly a kludge to avoid starting @@ -2297,6 +2296,16 @@ static int ext4_da_writepages(struct address_space *mapping, */ if (!mapping->nrpages || !mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) return 0; + /* + * Make sure nr_to_write is >= sbi->s_mb_stream_request + * This make sure small files blocks are allocated in + * single attempt. This ensure that small files + * get less fragmented. + */ + if (wbc->nr_to_write < sbi->s_mb_stream_request) { + nr_to_writebump = sbi->s_mb_stream_request - wbc->nr_to_write; + wbc->nr_to_write = sbi->s_mb_stream_request; + } if (!wbc->range_cyclic) /* @@ -2377,7 +2386,7 @@ restart_loop: } out_writepages: - wbc->nr_to_write = to_write; + wbc->nr_to_write = to_write - nr_to_writebump; wbc->range_start = range_start; return ret; } diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 865e9dd..e0e3a5e 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3282,6 +3282,35 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac, } /* + * Return the prealloc space that have minimal distance + * from the goal block. @cpa is the prealloc + * space that is having currently known minimal distance + * from the goal block. + */ +static struct ext4_prealloc_space * +ext4_mb_check_group_pa(ext4_fsblk_t goal_block, + struct ext4_prealloc_space *pa, + struct ext4_prealloc_space *cpa) +{ + ext4_fsblk_t cur_distance, new_distance; + + if (cpa == NULL) { + atomic_inc(&pa->pa_count); + return pa; + } + cur_distance = abs(goal_block - cpa->pa_pstart); + new_distance = abs(goal_block - pa->pa_pstart); + + if (cur_distance < new_distance) + return cpa; + + /* drop the previous reference */ + atomic_dec(&cpa->pa_count); + atomic_inc(&pa->pa_count); + return pa; +} + +/* * search goal blocks in preallocated space */ static noinline_for_stack int @@ -3290,7 +3319,8 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac) int order, i; struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); struct ext4_locality_group *lg; - struct ext4_prealloc_space *pa; + struct ext4_prealloc_space *pa, *cpa = NULL; + ext4_fsblk_t goal_block; /* only data can be preallocated */ if (!(ac->ac_flags & EXT4_MB_HINT_DATA)) @@ -3333,6 +3363,13 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac) /* The max size of hash table is PREALLOC_TB_SIZE */ order = PREALLOC_TB_SIZE - 1; + goal_block = ac->ac_g_ex.fe_group * EXT4_BLOCKS_PER_GROUP(ac->ac_sb) + + ac->ac_g_ex.fe_start + + le32_to_cpu(EXT4_SB(ac->ac_sb)->s_es->s_first_data_block); + /* + * search for the prealloc space that is having + * minimal distance from the goal block. + */ for (i = order; i < PREALLOC_TB_SIZE; i++) { rcu_read_lock(); list_for_each_entry_rcu(pa, &lg->lg_prealloc_list[i], @@ -3340,17 +3377,19 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac) spin_lock(&pa->pa_lock); if (pa->pa_deleted == 0 && pa->pa_free >= ac->ac_o_ex.fe_len) { - atomic_inc(&pa->pa_count); - ext4_mb_use_group_pa(ac, pa); - spin_unlock(&pa->pa_lock); - ac->ac_criteria = 20; - rcu_read_unlock(); - return 1; + + cpa = ext4_mb_check_group_pa(goal_block, + pa, cpa); } spin_unlock(&pa->pa_lock); } rcu_read_unlock(); } + if (cpa) { + ext4_mb_use_group_pa(ac, cpa); + ac->ac_criteria = 20; + return 1; + } return 0; } -- cgit v1.1 From 53e6d8d182e97c5211da4ee1f163c840c7ecf8ca Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 25 Jul 2008 22:08:09 +0200 Subject: fs/nfsd/export.c: Adjust error handling code involving auth_domain_put Once clp is assigned, it never becomes NULL, so we can make a label for it in the error handling code. Because the call to path_lookup follows the call to auth_domain_find, its error handling code should jump to this new label. The semantic match that finds this problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r@ expression x,E; statement S; position p1,p2,p3; @@ ( if ((x = auth_domain_find@p1(...)) == NULL || ...) S | x = auth_domain_find@p1(...) ... when != x if (x == NULL || ...) S ) <... if@p3 (...) { ... when != auth_domain_put(x) when != if (x) { ... auth_domain_put(x); ...} return@p2 ...; } ...> ( return x; | return 0; | x = E | E = x | auth_domain_put(x) ) @exists@ position r.p1,r.p2,r.p3; expression x; int ret != 0; statement S; @@ * x = auth_domain_find@p1(...) <... * if@p3 (...) S ...> * return@p2 \(NULL\|ret\); // Signed-off-by: Julia Lawall Signed-off-by: J. Bruce Fields --- fs/nfsd/export.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 33bfcf0..9dc036f 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -1023,7 +1023,7 @@ exp_export(struct nfsctl_export *nxp) /* Look up the dentry */ err = path_lookup(nxp->ex_path, 0, &nd); if (err) - goto out_unlock; + goto out_put_clp; err = -EINVAL; exp = exp_get_by_name(clp, nd.path.mnt, nd.path.dentry, NULL); @@ -1090,9 +1090,9 @@ finish: exp_put(exp); if (fsid_key && !IS_ERR(fsid_key)) cache_put(&fsid_key->h, &svc_expkey_cache); - if (clp) - auth_domain_put(clp); path_put(&nd.path); +out_put_clp: + auth_domain_put(clp); out_unlock: exp_writeunlock(); out: -- cgit v1.1 From 4f3e7524b2e703d9f8b02ac338153a53dd7ede66 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 11 Aug 2008 09:30:23 +0200 Subject: lockdep: map_acquire Most the free-standing lock_acquire() usages look remarkably similar, sweep them into a new helper. Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- fs/jbd/transaction.c | 4 ++-- fs/jbd2/transaction.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 8dee320..31a4bd7 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -291,7 +291,7 @@ handle_t *journal_start(journal_t *journal, int nblocks) goto out; } - lock_acquire(&handle->h_lockdep_map, 0, 0, 0, 2, _THIS_IP_); + map_acquire(&handle->h_lockdep_map); out: return handle; @@ -1448,7 +1448,7 @@ int journal_stop(handle_t *handle) spin_unlock(&journal->j_state_lock); } - lock_release(&handle->h_lockdep_map, 1, _THIS_IP_); + map_release(&handle->h_lockdep_map); jbd_free_handle(handle); return err; diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 4f7cadb..c074971 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -301,7 +301,7 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks) goto out; } - lock_acquire(&handle->h_lockdep_map, 0, 0, 0, 2, _THIS_IP_); + map_acquire(&handle->h_lockdep_map); out: return handle; } @@ -1279,7 +1279,7 @@ int jbd2_journal_stop(handle_t *handle) spin_unlock(&journal->j_state_lock); } - lock_release(&handle->h_lockdep_map, 1, _THIS_IP_); + map_release(&handle->h_lockdep_map); jbd2_free_handle(handle); return err; -- cgit v1.1 From 3295f0ef9ff048a4619ede597ad9ec9cab725654 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 11 Aug 2008 10:30:30 +0200 Subject: lockdep: rename map_[acquire|release]() => lock_map_[acquire|release]() the names were too generic: drivers/uio/uio.c:87: error: expected identifier or '(' before 'do' drivers/uio/uio.c:87: error: expected identifier or '(' before 'while' drivers/uio/uio.c:113: error: 'map_release' undeclared here (not in a function) Signed-off-by: Ingo Molnar --- fs/jbd/transaction.c | 4 ++-- fs/jbd2/transaction.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 31a4bd7..0540ca2 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -291,7 +291,7 @@ handle_t *journal_start(journal_t *journal, int nblocks) goto out; } - map_acquire(&handle->h_lockdep_map); + lock_map_acquire(&handle->h_lockdep_map); out: return handle; @@ -1448,7 +1448,7 @@ int journal_stop(handle_t *handle) spin_unlock(&journal->j_state_lock); } - map_release(&handle->h_lockdep_map); + lock_map_release(&handle->h_lockdep_map); jbd_free_handle(handle); return err; diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index c074971..e5d5405 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -301,7 +301,7 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks) goto out; } - map_acquire(&handle->h_lockdep_map); + lock_map_acquire(&handle->h_lockdep_map); out: return handle; } @@ -1279,7 +1279,7 @@ int jbd2_journal_stop(handle_t *handle) spin_unlock(&journal->j_state_lock); } - map_release(&handle->h_lockdep_map); + lock_map_release(&handle->h_lockdep_map); jbd2_free_handle(handle); return err; -- cgit v1.1 From 74c27c43ebd020fcb65364613503f6c08dc6f535 Mon Sep 17 00:00:00 2001 From: Takashi YOSHII Date: Mon, 11 Aug 2008 20:10:54 +0900 Subject: binfmt_flat: Stub in a FLAT_PLAT_INIT(). This provides a FLAT_PLAT_INIT() arch hook for platforms that need to set up specific register state prior to calling in to the process, as per ELF_PLAT_INIT(). Signed-off-by: Takashi YOSHII Signed-off-by: Paul Mundt --- fs/binfmt_flat.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 56372ec..dfc0197 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -914,7 +914,9 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs) /* Stash our initial stack pointer into the mm structure */ current->mm->start_stack = (unsigned long )sp; - +#ifdef FLAT_PLAT_INIT + FLAT_PLAT_INIT(regs); +#endif DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n", (int)regs, (int)start_addr, (int)current->mm->start_stack); -- cgit v1.1 From 2c731afb0d4ba16018b400c75665fbdb8feb2175 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 11 Aug 2008 22:28:53 +0000 Subject: [CIFS] if get root inode fails during mount, cleanup tree connection CC: Stable Kernel Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index e8da4ee..f50fc87 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -174,6 +174,8 @@ out_no_root: cERROR(1, ("cifs_read_super: get root inode failed")); if (inode) iput(inode); + + cifs_umount(sb, cifs_sb); out_mount_failed: if (cifs_sb) { -- cgit v1.1 From 54b4602d5fe50571362e101138d24edb9cf82d29 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 11 Aug 2008 22:31:40 +0000 Subject: [CIFS] remove trailing whitespace Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index f50fc87..25ecbd5 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -174,7 +174,7 @@ out_no_root: cERROR(1, ("cifs_read_super: get root inode failed")); if (inode) iput(inode); - + cifs_umount(sb, cifs_sb); out_mount_failed: -- cgit v1.1 From 523723bb5032f291272f9732713713b9b82ccfe0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 12 Aug 2008 15:09:01 -0700 Subject: fs/eventpoll.c: fix sys_epoll_create1() comment The `size' argument was removed. Reported-by: Geert Uytterhoeven Cc: Ulrich Drepper Cc: Davide Libenzi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/eventpoll.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 0c87474..7cc0eb7 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1041,10 +1041,7 @@ retry: } /* - * It opens an eventpoll file descriptor. The "size" parameter is there - * for historical reasons, when epoll was using an hash instead of an - * RB tree. With the current implementation, the "size" parameter is ignored - * (besides sanity checks). + * Open an eventpoll file descriptor. */ asmlinkage long sys_epoll_create1(int flags) { -- cgit v1.1 From dd763460eb628b57814251a15a39f8d75c044d76 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Tue, 12 Aug 2008 15:09:01 -0700 Subject: reiserfs: removed duplicated #include Removed duplicated #include in fs/reiserfs/super.c. Signed-off-by: Huang Weiyi Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/super.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 282a135..d318c7e 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -27,7 +27,6 @@ #include #include #include -#include struct file_system_type reiserfs_fs_type; -- cgit v1.1 From 50ac2d694f2dd1658341cf97bcf2ffb836d772cb Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 12 Aug 2008 15:09:02 -0700 Subject: seq_file: add seq_cpumask(), seq_nodemask() Short enough reads from /proc/irq/*/smp_affinity return -EINVAL for no good reason. This became noticed with NR_CPUS=4096 patches, when length of printed representation of cpumask becase 1152, but cat(1) continued to read with 1024-byte chunks. bitmap_scnprintf() in good faith fills buffer, returns 1023, check returns -EINVAL. Fix it by switching to seq_file, so handler will just fill buffer and doesn't care about offsets, length, filling EOF and all this crap. For that add seq_bitmap(), and wrappers around it -- seq_cpumask() and seq_nodemask(). Signed-off-by: Alexey Dobriyan Reviewed-by: Paul Jackson Cc: Mike Travis Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/seq_file.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'fs') diff --git a/fs/seq_file.c b/fs/seq_file.c index 3f54dbd..5d54205 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -443,6 +443,20 @@ int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc) return -1; } +int seq_bitmap(struct seq_file *m, unsigned long *bits, unsigned int nr_bits) +{ + size_t len = bitmap_scnprintf_len(nr_bits); + + if (m->count + len < m->size) { + bitmap_scnprintf(m->buf + m->count, m->size - m->count, + bits, nr_bits); + m->count += len; + return 0; + } + m->count = m->size; + return -1; +} + static void *single_start(struct seq_file *p, loff_t *pos) { return NULL + (*pos == 0); -- cgit v1.1 From 79071eb0b2f142b9cc6531d04fa2915943938b5e Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 15:41:12 +1000 Subject: [XFS] Use the generic bitops rather than implementing them ourselves. This keeps xfs_lowbit64 as it was since there aren't good generic helpers there ... Patch inspired by Andi Kleen. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31472a Signed-off-by: David Chinner Signed-off-by: Eric Sandeen Signed-off-by: Donald Douwsma Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_bit.c | 103 --------------------------------------------------- fs/xfs/xfs_bit.h | 34 +++++++++++++++-- fs/xfs/xfs_rtalloc.c | 19 ++++------ 3 files changed, 37 insertions(+), 119 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c index fab0b6d..4822884 100644 --- a/fs/xfs/xfs_bit.c +++ b/fs/xfs/xfs_bit.c @@ -25,109 +25,6 @@ * XFS bit manipulation routines, used in non-realtime code. */ -#ifndef HAVE_ARCH_HIGHBIT -/* - * Index of high bit number in byte, -1 for none set, 0..7 otherwise. - */ -static const char xfs_highbit[256] = { - -1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */ - 3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */ - 4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */ - 4, 4, 4, 4, 4, 4, 4, 4, /* 18 .. 1f */ - 5, 5, 5, 5, 5, 5, 5, 5, /* 20 .. 27 */ - 5, 5, 5, 5, 5, 5, 5, 5, /* 28 .. 2f */ - 5, 5, 5, 5, 5, 5, 5, 5, /* 30 .. 37 */ - 5, 5, 5, 5, 5, 5, 5, 5, /* 38 .. 3f */ - 6, 6, 6, 6, 6, 6, 6, 6, /* 40 .. 47 */ - 6, 6, 6, 6, 6, 6, 6, 6, /* 48 .. 4f */ - 6, 6, 6, 6, 6, 6, 6, 6, /* 50 .. 57 */ - 6, 6, 6, 6, 6, 6, 6, 6, /* 58 .. 5f */ - 6, 6, 6, 6, 6, 6, 6, 6, /* 60 .. 67 */ - 6, 6, 6, 6, 6, 6, 6, 6, /* 68 .. 6f */ - 6, 6, 6, 6, 6, 6, 6, 6, /* 70 .. 77 */ - 6, 6, 6, 6, 6, 6, 6, 6, /* 78 .. 7f */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 80 .. 87 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 88 .. 8f */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 90 .. 97 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* 98 .. 9f */ - 7, 7, 7, 7, 7, 7, 7, 7, /* a0 .. a7 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* a8 .. af */ - 7, 7, 7, 7, 7, 7, 7, 7, /* b0 .. b7 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* b8 .. bf */ - 7, 7, 7, 7, 7, 7, 7, 7, /* c0 .. c7 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* c8 .. cf */ - 7, 7, 7, 7, 7, 7, 7, 7, /* d0 .. d7 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* d8 .. df */ - 7, 7, 7, 7, 7, 7, 7, 7, /* e0 .. e7 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* e8 .. ef */ - 7, 7, 7, 7, 7, 7, 7, 7, /* f0 .. f7 */ - 7, 7, 7, 7, 7, 7, 7, 7, /* f8 .. ff */ -}; -#endif - -/* - * xfs_highbit32: get high bit set out of 32-bit argument, -1 if none set. - */ -inline int -xfs_highbit32( - __uint32_t v) -{ -#ifdef HAVE_ARCH_HIGHBIT - return highbit32(v); -#else - int i; - - if (v & 0xffff0000) - if (v & 0xff000000) - i = 24; - else - i = 16; - else if (v & 0x0000ffff) - if (v & 0x0000ff00) - i = 8; - else - i = 0; - else - return -1; - return i + xfs_highbit[(v >> i) & 0xff]; -#endif -} - -/* - * xfs_lowbit64: get low bit set out of 64-bit argument, -1 if none set. - */ -int -xfs_lowbit64( - __uint64_t v) -{ - __uint32_t w = (__uint32_t)v; - int n = 0; - - if (w) { /* lower bits */ - n = ffs(w); - } else { /* upper bits */ - w = (__uint32_t)(v >> 32); - if (w && (n = ffs(w))) - n += 32; - } - return n - 1; -} - -/* - * xfs_highbit64: get high bit set out of 64-bit argument, -1 if none set. - */ -int -xfs_highbit64( - __uint64_t v) -{ - __uint32_t h = (__uint32_t)(v >> 32); - - if (h) - return xfs_highbit32(h) + 32; - return xfs_highbit32((__uint32_t)v); -} - - /* * Return whether bitmap is empty. * Size is number of words in the bitmap, which is padded to word boundary diff --git a/fs/xfs/xfs_bit.h b/fs/xfs/xfs_bit.h index 082641a..8e0e463 100644 --- a/fs/xfs/xfs_bit.h +++ b/fs/xfs/xfs_bit.h @@ -47,13 +47,39 @@ static inline __uint64_t xfs_mask64lo(int n) } /* Get high bit set out of 32-bit argument, -1 if none set */ -extern int xfs_highbit32(__uint32_t v); +static inline int xfs_highbit32(__uint32_t v) +{ + return fls(v) - 1; +} + +/* Get high bit set out of 64-bit argument, -1 if none set */ +static inline int xfs_highbit64(__uint64_t v) +{ + return fls64(v) - 1; +} + +/* Get low bit set out of 32-bit argument, -1 if none set */ +static inline int xfs_lowbit32(__uint32_t v) +{ + unsigned long t = v; + return (v) ? find_first_bit(&t, 32) : -1; +} /* Get low bit set out of 64-bit argument, -1 if none set */ -extern int xfs_lowbit64(__uint64_t v); +static inline int xfs_lowbit64(__uint64_t v) +{ + __uint32_t w = (__uint32_t)v; + int n = 0; -/* Get high bit set out of 64-bit argument, -1 if none set */ -extern int xfs_highbit64(__uint64_t); + if (w) { /* lower bits */ + n = ffs(w); + } else { /* upper bits */ + w = (__uint32_t)(v >> 32); + if (w && (n = ffs(w))) + n += 32; + } + return n - 1; +} /* Return whether bitmap is empty (1 == empty) */ extern int xfs_bitmap_empty(uint *map, uint size); diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index bf87a59..e2f68de 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -74,18 +74,6 @@ STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int, */ /* - * xfs_lowbit32: get low bit set out of 32-bit argument, -1 if none set. - */ -STATIC int -xfs_lowbit32( - __uint32_t v) -{ - if (v) - return ffs(v) - 1; - return -1; -} - -/* * Allocate space to the bitmap or summary file, and zero it, for growfs. */ STATIC int /* error */ @@ -450,6 +438,7 @@ xfs_rtallocate_extent_near( } bbno = XFS_BITTOBLOCK(mp, bno); i = 0; + ASSERT(minlen != 0); log2len = xfs_highbit32(minlen); /* * Loop over all bitmap blocks (bbno + i is current block). @@ -618,6 +607,8 @@ xfs_rtallocate_extent_size( xfs_suminfo_t sum; /* summary information for extents */ ASSERT(minlen % prod == 0 && maxlen % prod == 0); + ASSERT(maxlen != 0); + /* * Loop over all the levels starting with maxlen. * At each level, look at all the bitmap blocks, to see if there @@ -675,6 +666,9 @@ xfs_rtallocate_extent_size( *rtblock = NULLRTBLOCK; return 0; } + ASSERT(minlen != 0); + ASSERT(maxlen != 0); + /* * Loop over sizes, from maxlen down to minlen. * This time, when we do the allocations, allow smaller ones @@ -1961,6 +1955,7 @@ xfs_growfs_rt( nsbp->sb_blocksize * nsbp->sb_rextsize); nsbp->sb_rextents = nsbp->sb_rblocks; do_div(nsbp->sb_rextents, nsbp->sb_rextsize); + ASSERT(nsbp->sb_rextents != 0); nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents); nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1; nrsumsize = -- cgit v1.1 From 3790689fa3c771bba6bafb7dee3e8389dd0b55bc Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 13 Aug 2008 15:42:10 +1000 Subject: [XFS] Do not access buffers after dropping reference count We should not access a buffer after dropping it's reference count otherwise we could race with another thread that releases the final reference count and frees the buffer causing us to access potentially unmapped memory. The bug this change fixes only occured on DEBUG XFS since the offending code was in an ASSERT. SGI-PV: 984429 SGI-Modid: xfs-linux-melb:xfs-kern:31715a Signed-off-by: Lachlan McIlroy Signed-off-by: David Chinner --- fs/xfs/linux-2.6/xfs_buf.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 9cc8f02..9f45c74 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -838,6 +838,7 @@ xfs_buf_rele( return; } + ASSERT(atomic_read(&bp->b_hold) > 0); if (atomic_dec_and_lock(&bp->b_hold, &hash->bh_lock)) { if (bp->b_relse) { atomic_inc(&bp->b_hold); @@ -851,11 +852,6 @@ xfs_buf_rele( spin_unlock(&hash->bh_lock); xfs_buf_free(bp); } - } else { - /* - * Catch reference count leaks - */ - ASSERT(atomic_read(&bp->b_hold) >= 0); } } -- cgit v1.1 From 016516462575d28fab3354f762cad16c86c09116 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 15:45:15 +1000 Subject: [XFS] Avoid directly referencing the VFS inode. In several places we directly convert from the XFS inode to the linux (VFS) inode by a simple deference of ip->i_vnode. We should not do this - a helper function should be used to extract the VFS inode from the XFS inode. Introduce the function VFS_I() to extract the VFS inode from the XFS inode. The name was chosen to match XFS_I() which is used to extract the XFS inode from the VFS inode. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31720a Signed-off-by: David Chinner Signed-off-by: Niv Sardi Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_export.c | 6 +++--- fs/xfs/linux-2.6/xfs_fs_subr.c | 6 +++--- fs/xfs/linux-2.6/xfs_iops.c | 14 +++++++------- fs/xfs/linux-2.6/xfs_iops.h | 6 ------ fs/xfs/linux-2.6/xfs_lrw.c | 2 +- fs/xfs/linux-2.6/xfs_super.c | 4 ++-- fs/xfs/xfs_iget.c | 7 ++++--- fs/xfs/xfs_inode.h | 22 +++++++++++++++++++--- fs/xfs/xfs_utils.c | 4 ++-- 9 files changed, 41 insertions(+), 30 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index 987fe84..d3880b7 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -139,7 +139,7 @@ xfs_nfs_get_inode( } xfs_iunlock(ip, XFS_ILOCK_SHARED); - return ip->i_vnode; + return VFS_I(ip); } STATIC struct dentry * @@ -219,9 +219,9 @@ xfs_fs_get_parent( if (unlikely(error)) return ERR_PTR(-error); - parent = d_alloc_anon(cip->i_vnode); + parent = d_alloc_anon(VFS_I(cip)); if (unlikely(!parent)) { - iput(cip->i_vnode); + iput(VFS_I(cip)); return ERR_PTR(-ENOMEM); } return parent; diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index 1eefe61..36caa6d 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c @@ -31,7 +31,7 @@ xfs_tosspages( xfs_off_t last, int fiopt) { - struct address_space *mapping = ip->i_vnode->i_mapping; + struct address_space *mapping = VFS_I(ip)->i_mapping; if (mapping->nrpages) truncate_inode_pages(mapping, first); @@ -44,7 +44,7 @@ xfs_flushinval_pages( xfs_off_t last, int fiopt) { - struct address_space *mapping = ip->i_vnode->i_mapping; + struct address_space *mapping = VFS_I(ip)->i_mapping; int ret = 0; if (mapping->nrpages) { @@ -64,7 +64,7 @@ xfs_flush_pages( uint64_t flags, int fiopt) { - struct address_space *mapping = ip->i_vnode->i_mapping; + struct address_space *mapping = VFS_I(ip)->i_mapping; int ret = 0; int ret2; diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index e88f510..fec5ff5 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -62,7 +62,7 @@ void xfs_synchronize_atime( xfs_inode_t *ip) { - struct inode *inode = ip->i_vnode; + struct inode *inode = VFS_I(ip); if (inode) { ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; @@ -79,7 +79,7 @@ void xfs_mark_inode_dirty_sync( xfs_inode_t *ip) { - struct inode *inode = ip->i_vnode; + struct inode *inode = VFS_I(ip); if (inode) mark_inode_dirty_sync(inode); @@ -299,7 +299,7 @@ xfs_vn_mknod( if (unlikely(error)) goto out_free_acl; - inode = ip->i_vnode; + inode = VFS_I(ip); error = xfs_init_security(inode, dir); if (unlikely(error)) @@ -366,7 +366,7 @@ xfs_vn_lookup( return NULL; } - return d_splice_alias(cip->i_vnode, dentry); + return d_splice_alias(VFS_I(cip), dentry); } STATIC struct dentry * @@ -399,12 +399,12 @@ xfs_vn_ci_lookup( /* if exact match, just splice and exit */ if (!ci_name.name) - return d_splice_alias(ip->i_vnode, dentry); + return d_splice_alias(VFS_I(ip), dentry); /* else case-insensitive match... */ dname.name = ci_name.name; dname.len = ci_name.len; - dentry = d_add_ci(ip->i_vnode, dentry, &dname); + dentry = d_add_ci(VFS_I(ip), dentry, &dname); kmem_free(ci_name.name); return dentry; } @@ -478,7 +478,7 @@ xfs_vn_symlink( if (unlikely(error)) goto out; - inode = cip->i_vnode; + inode = VFS_I(cip); error = xfs_init_security(inode, dir); if (unlikely(error)) diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index d97ba93..fdda404 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h @@ -33,10 +33,4 @@ struct xfs_inode; extern void xfs_ichgtime(struct xfs_inode *, int); extern void xfs_ichgtime_fast(struct xfs_inode *, struct inode *, int); -#define xfs_vtoi(vp) \ - ((struct xfs_inode *)vn_to_inode(vp)->i_private) - -#define XFS_I(inode) \ - ((struct xfs_inode *)(inode)->i_private) - #endif /* __XFS_IOPS_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 82333b3..e03e2c3 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -137,7 +137,7 @@ xfs_iozero( struct address_space *mapping; int status; - mapping = ip->i_vnode->i_mapping; + mapping = VFS_I(ip)->i_mapping; do { unsigned offset, bytes; void *fsdata; diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 30ae963..b497229 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1106,7 +1106,7 @@ void xfs_flush_inode( xfs_inode_t *ip) { - struct inode *inode = ip->i_vnode; + struct inode *inode = VFS_I(ip); igrab(inode); xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work); @@ -1825,7 +1825,7 @@ xfs_fs_fill_super( sb->s_time_gran = 1; set_posix_acl_flag(sb); - root = igrab(mp->m_rootip->i_vnode); + root = igrab(VFS_I(mp->m_rootip)); if (!root) { error = ENOENT; goto fail_unmount; diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index b07604b..d443426 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -411,10 +411,11 @@ xfs_iput(xfs_inode_t *ip, * Special iput for brand-new inodes that are still locked */ void -xfs_iput_new(xfs_inode_t *ip, - uint lock_flags) +xfs_iput_new( + xfs_inode_t *ip, + uint lock_flags) { - struct inode *inode = ip->i_vnode; + struct inode *inode = VFS_I(ip); xfs_itrace_entry(ip); diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 17a04b6..4a5e48c 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -263,6 +263,25 @@ typedef struct xfs_inode { #define XFS_ISIZE(ip) (((ip)->i_d.di_mode & S_IFMT) == S_IFREG) ? \ (ip)->i_size : (ip)->i_d.di_size; +/* Convert from vfs inode to xfs inode */ +static inline struct xfs_inode *XFS_I(struct inode *inode) +{ + return (struct xfs_inode *)inode->i_private; +} + +static inline struct xfs_inode *xfs_vtoi(bhv_vnode_t *vp) +{ + return XFS_I((struct inode *)vp); +} + +/* convert from xfs inode to vfs inode */ +static inline struct inode *VFS_I(struct xfs_inode *ip) +{ + return (struct inode *)ip->i_vnode; +} +#define XFS_ITOV(ip) VFS_I(ip) +#define XFS_ITOV_NULL(ip) VFS_I(ip) + /* * i_flags helper functions */ @@ -439,9 +458,6 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags) #define XFS_ITRUNC_DEFINITE 0x1 #define XFS_ITRUNC_MAYBE 0x2 -#define XFS_ITOV(ip) ((ip)->i_vnode) -#define XFS_ITOV_NULL(ip) ((ip)->i_vnode) - /* * For multiple groups support: if S_ISGID bit is set in the parent * directory, group of new file is set to that of the parent, and diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 98e5f11..35d4d41 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c @@ -237,7 +237,7 @@ xfs_droplink( ASSERT (ip->i_d.di_nlink > 0); ip->i_d.di_nlink--; - drop_nlink(ip->i_vnode); + drop_nlink(VFS_I(ip)); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); error = 0; @@ -301,7 +301,7 @@ xfs_bumplink( ASSERT(ip->i_d.di_nlink > 0); ip->i_d.di_nlink++; - inc_nlink(ip->i_vnode); + inc_nlink(VFS_I(ip)); if ((ip->i_d.di_version == XFS_DINODE_VERSION_1) && (ip->i_d.di_nlink > XFS_MAXLINK_1)) { /* -- cgit v1.1 From 705db4a24e0576f30d736de3c49623b4686ce473 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 15:47:43 +1000 Subject: [XFS] kill shouty XFS_ITOV_NULL macro Replace XFS_ITOV_NULL() with the new VFS_I() inline. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31722a Signed-off-by: David Chinner Signed-off-by: Niv Sardi Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_vnode.c | 2 +- fs/xfs/quota/xfs_qm_syscalls.c | 2 +- fs/xfs/xfs_inode.c | 4 ++-- fs/xfs/xfs_inode.h | 1 - fs/xfs/xfs_vfsops.c | 2 +- fs/xfs/xfs_vnodeops.c | 2 +- 6 files changed, 6 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 25488b6..1e39d04 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -108,7 +108,7 @@ vn_hold( */ static inline int xfs_icount(struct xfs_inode *ip) { - bhv_vnode_t *vp = XFS_ITOV_NULL(ip); + bhv_vnode_t *vp = VFS_I(ip); if (vp) return vn_count(vp); diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index adfb872..132a0ab 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -1059,7 +1059,7 @@ again: ip = ip->i_mnext; continue; } - vp = XFS_ITOV_NULL(ip); + vp = VFS_I(ip); if (!vp) { ASSERT(ip->i_udquot == NULL); ASSERT(ip->i_gdquot == NULL); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index bedc661..46cecba 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1077,7 +1077,7 @@ xfs_ialloc( } ASSERT(ip != NULL); - vp = XFS_ITOV(ip); + vp = VFS_I(ip); ip->i_d.di_mode = (__uint16_t)mode; ip->i_d.di_onlink = 0; ip->i_d.di_nlink = nlink; @@ -3480,7 +3480,7 @@ xfs_iflush_all( continue; } - vp = XFS_ITOV_NULL(ip); + vp = VFS_I(ip); if (!vp) { XFS_MOUNT_IUNLOCK(mp); xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC); diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 4a5e48c..f04e026 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -280,7 +280,6 @@ static inline struct inode *VFS_I(struct xfs_inode *ip) return (struct inode *)ip->i_vnode; } #define XFS_ITOV(ip) VFS_I(ip) -#define XFS_ITOV_NULL(ip) VFS_I(ip) /* * i_flags helper functions diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 4a9a433..5f461ce 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -404,7 +404,7 @@ xfs_sync_inodes( continue; } - vp = XFS_ITOV_NULL(ip); + vp = VFS_I(ip); /* * If the vnode is gone then this is being torn down, diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 76a1166..a2e470a 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -2933,7 +2933,7 @@ xfs_finish_reclaim( int sync_mode) { xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino); - bhv_vnode_t *vp = XFS_ITOV_NULL(ip); + bhv_vnode_t *vp = VFS_I(ip); if (vp && VN_BAD(vp)) goto reclaim; -- cgit v1.1 From e4f7529108d01bf66af8ebecd6be2b98d8db30ce Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 16:00:45 +1000 Subject: [XFS] Kill shouty XFS_ITOV() macro Replace XFS_ITOV() with the new VFS_I() inline. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31724a Signed-off-by: David Chinner Signed-off-by: Niv Sardi Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_ioctl.c | 4 ++-- fs/xfs/linux-2.6/xfs_iops.c | 2 +- fs/xfs/linux-2.6/xfs_linux.h | 2 +- fs/xfs/linux-2.6/xfs_super.c | 2 +- fs/xfs/quota/xfs_dquot.c | 2 +- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_dfrag.c | 4 ++-- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_inode.h | 1 - fs/xfs/xfs_itable.c | 2 +- fs/xfs/xfs_utils.h | 4 ++-- fs/xfs/xfs_vfsops.c | 8 ++++---- fs/xfs/xfs_vnodeops.c | 12 ++++++------ 13 files changed, 23 insertions(+), 24 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index acb978d..48799ba 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -245,7 +245,7 @@ xfs_vget_fsop_handlereq( xfs_iunlock(ip, XFS_ILOCK_SHARED); - *inode = XFS_ITOV(ip); + *inode = VFS_I(ip); return 0; } @@ -927,7 +927,7 @@ STATIC void xfs_diflags_to_linux( struct xfs_inode *ip) { - struct inode *inode = XFS_ITOV(ip); + struct inode *inode = VFS_I(ip); unsigned int xflags = xfs_ip2xflags(ip); if (xflags & XFS_XFLAG_IMMUTABLE) diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index fec5ff5..cc0f21a 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -101,7 +101,7 @@ xfs_ichgtime( xfs_inode_t *ip, int flags) { - struct inode *inode = vn_to_inode(XFS_ITOV(ip)); + struct inode *inode = VFS_I(ip); timespec_t tv; nanotime(&tv); diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 4d45d93..a9cd6e4 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -180,7 +180,7 @@ #define xfs_sort(a,n,s,fn) sort(a,n,s,fn,NULL) #define xfs_stack_trace() dump_stack() #define xfs_itruncate_data(ip, off) \ - (-vmtruncate(vn_to_inode(XFS_ITOV(ip)), (off))) + (-vmtruncate(vn_to_inode(VFS_I(ip)), (off))) /* Move the kernel do_div definition off to one side */ diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index b497229..c9ec44a 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1131,7 +1131,7 @@ void xfs_flush_device( xfs_inode_t *ip) { - struct inode *inode = vn_to_inode(XFS_ITOV(ip)); + struct inode *inode = VFS_I(ip); igrab(inode); xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work); diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index fc9f3fb..68adc5f 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -431,7 +431,7 @@ xfs_qm_dqalloc( * when it unlocks the inode. Since we want to keep the quota * inode around, we bump the vnode ref count now. */ - VN_HOLD(XFS_ITOV(quotip)); + VN_HOLD(VFS_I(quotip)); xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL); nmaps = 1; diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 3c4beb3..2f46b67 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -4000,7 +4000,7 @@ xfs_bmap_add_attrfork( ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; } ASSERT(ip->i_d.di_anextents == 0); - VN_HOLD(XFS_ITOV(ip)); + VN_HOLD(VFS_I(ip)); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); switch (ip->i_d.di_format) { diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 2211e88..9e75101 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -150,8 +150,8 @@ xfs_swap_extents( } sbp = &sxp->sx_stat; - vp = XFS_ITOV(ip); - tvp = XFS_ITOV(tip); + vp = VFS_I(ip); + tvp = VFS_I(tip); /* Lock in i_ino order */ if (ip->i_ino < tip->i_ino) { diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 46cecba..cfbafc9 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1408,7 +1408,7 @@ xfs_itruncate_start( (flags == XFS_ITRUNC_MAYBE)); mp = ip->i_mount; - vp = XFS_ITOV(ip); + vp = VFS_I(ip); /* wait for the completion of any pending DIOs */ if (new_size < ip->i_size) diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index f04e026..4e1e55e 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -279,7 +279,6 @@ static inline struct inode *VFS_I(struct xfs_inode *ip) { return (struct inode *)ip->i_vnode; } -#define XFS_ITOV(ip) VFS_I(ip) /* * i_flags helper functions diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 9a3ef9d..4feda54 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -72,7 +72,7 @@ xfs_bulkstat_one_iget( ASSERT(ip != NULL); ASSERT(ip->i_blkno != (xfs_daddr_t)0); - vp = XFS_ITOV(ip); + vp = VFS_I(ip); dic = &ip->i_d; /* xfs_iget returns the following without needing diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h index f316cb8..7b533df 100644 --- a/fs/xfs/xfs_utils.h +++ b/fs/xfs/xfs_utils.h @@ -18,8 +18,8 @@ #ifndef __XFS_UTILS_H__ #define __XFS_UTILS_H__ -#define IRELE(ip) VN_RELE(XFS_ITOV(ip)) -#define IHOLD(ip) VN_HOLD(XFS_ITOV(ip)) +#define IRELE(ip) VN_RELE(VFS_I(ip)) +#define IHOLD(ip) VN_HOLD(VFS_I(ip)) extern int xfs_truncate_file(xfs_mount_t *, xfs_inode_t *); extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 5f461ce..38450f1f 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -128,7 +128,7 @@ xfs_unmount_flush( xfs_inode_t *rip = mp->m_rootip; xfs_inode_t *rbmip; xfs_inode_t *rsumip = NULL; - bhv_vnode_t *rvp = XFS_ITOV(rip); + bhv_vnode_t *rvp = VFS_I(rip); int error; xfs_ilock(rip, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); @@ -146,7 +146,7 @@ xfs_unmount_flush( if (error == EFSCORRUPTED) goto fscorrupt_out; - ASSERT(vn_count(XFS_ITOV(rbmip)) == 1); + ASSERT(vn_count(VFS_I(rbmip)) == 1); rsumip = mp->m_rsumip; xfs_ilock(rsumip, XFS_ILOCK_EXCL); @@ -157,7 +157,7 @@ xfs_unmount_flush( if (error == EFSCORRUPTED) goto fscorrupt_out; - ASSERT(vn_count(XFS_ITOV(rsumip)) == 1); + ASSERT(vn_count(VFS_I(rsumip)) == 1); } /* @@ -479,7 +479,7 @@ xfs_sync_inodes( IPOINTER_INSERT(ip, mp); xfs_ilock(ip, lock_flags); - ASSERT(vp == XFS_ITOV(ip)); + ASSERT(vp == VFS_I(ip)); ASSERT(ip->i_mount == mp); vnode_refed = B_TRUE; diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index a2e470a..35a053f 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -83,7 +83,7 @@ xfs_setattr( cred_t *credp) { xfs_mount_t *mp = ip->i_mount; - struct inode *inode = XFS_ITOV(ip); + struct inode *inode = VFS_I(ip); int mask = iattr->ia_valid; xfs_trans_t *tp; int code; @@ -714,7 +714,7 @@ xfs_fsync( return XFS_ERROR(EIO); /* capture size updates in I/O completion before writing the inode. */ - error = filemap_fdatawait(vn_to_inode(XFS_ITOV(ip))->i_mapping); + error = filemap_fdatawait(vn_to_inode(VFS_I(ip))->i_mapping); if (error) return XFS_ERROR(error); @@ -1160,7 +1160,7 @@ int xfs_release( xfs_inode_t *ip) { - bhv_vnode_t *vp = XFS_ITOV(ip); + bhv_vnode_t *vp = VFS_I(ip); xfs_mount_t *mp = ip->i_mount; int error; @@ -1227,7 +1227,7 @@ int xfs_inactive( xfs_inode_t *ip) { - bhv_vnode_t *vp = XFS_ITOV(ip); + bhv_vnode_t *vp = VFS_I(ip); xfs_bmap_free_t free_list; xfs_fsblock_t first_block; int committed; @@ -2873,7 +2873,7 @@ int xfs_reclaim( xfs_inode_t *ip) { - bhv_vnode_t *vp = XFS_ITOV(ip); + bhv_vnode_t *vp = VFS_I(ip); xfs_itrace_entry(ip); @@ -3341,7 +3341,7 @@ xfs_free_file_space( xfs_trans_t *tp; int need_iolock = 1; - vp = XFS_ITOV(ip); + vp = VFS_I(ip); mp = ip->i_mount; xfs_itrace_entry(ip); -- cgit v1.1 From e6064d30c3407db7f8c19d5538ec847b29e47e30 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 16:01:45 +1000 Subject: [XFS] XFS: Kill xfs_vtoi() xfs_vtoi() is redundant and only unsed in small sections of code. Replace them with widely used XFS_I() inline and kill xfs_vtoi(). SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31725a Signed-off-by: David Chinner Signed-off-by: Niv Sardi Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_aops.c | 3 +-- fs/xfs/linux-2.6/xfs_vnode.h | 4 ++-- fs/xfs/xfs_acl.c | 16 ++++++++-------- fs/xfs/xfs_inode.h | 5 ----- 4 files changed, 11 insertions(+), 17 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index fa47e43..f42f80a 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -73,7 +73,6 @@ xfs_page_trace( unsigned long pgoff) { xfs_inode_t *ip; - bhv_vnode_t *vp = vn_from_inode(inode); loff_t isize = i_size_read(inode); loff_t offset = page_offset(page); int delalloc = -1, unmapped = -1, unwritten = -1; @@ -81,7 +80,7 @@ xfs_page_trace( if (page_has_buffers(page)) xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); - ip = xfs_vtoi(vp); + ip = XFS_I(inode); if (!ip->i_rwtrace) return; diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 41ca2ce..c3afecf 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -89,9 +89,9 @@ extern bhv_vnode_t *vn_hold(bhv_vnode_t *); #if defined(XFS_INODE_TRACE) #define VN_HOLD(vp) \ ((void)vn_hold(vp), \ - xfs_itrace_hold(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address)) + xfs_itrace_hold(XFS_I(vp), __FILE__, __LINE__, (inst_t *)__return_address)) #define VN_RELE(vp) \ - (xfs_itrace_rele(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address), \ + (xfs_itrace_rele(XFS_I(vp), __FILE__, __LINE__, (inst_t *)__return_address), \ iput(vn_to_inode(vp))) #else #define VN_HOLD(vp) ((void)vn_hold(vp)) diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 3e4648a..fdeca54 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -239,7 +239,7 @@ xfs_acl_vget( goto out; } if (kind == _ACL_TYPE_ACCESS) - xfs_acl_sync_mode(xfs_vtoi(vp)->i_d.di_mode, xfs_acl); + xfs_acl_sync_mode(XFS_I(vp)->i_d.di_mode, xfs_acl); error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size); } out: @@ -259,7 +259,7 @@ xfs_acl_vremove( VN_HOLD(vp); error = xfs_acl_allow_set(vp, kind); if (!error) { - error = xfs_attr_remove(xfs_vtoi(vp), + error = xfs_attr_remove(XFS_I(vp), kind == _ACL_TYPE_DEFAULT? SGI_ACL_DEFAULT: SGI_ACL_FILE, ATTR_ROOT); @@ -372,7 +372,7 @@ xfs_acl_allow_set( return ENOTDIR; if (vp->i_sb->s_flags & MS_RDONLY) return EROFS; - if (xfs_vtoi(vp)->i_d.di_uid != current->fsuid && !capable(CAP_FOWNER)) + if (XFS_I(vp)->i_d.di_uid != current->fsuid && !capable(CAP_FOWNER)) return EPERM; return 0; } @@ -576,7 +576,7 @@ xfs_acl_get_attr( ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1); flags |= ATTR_ROOT; - *error = xfs_attr_get(xfs_vtoi(vp), + *error = xfs_attr_get(XFS_I(vp), kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE : SGI_ACL_DEFAULT, (char *)aclp, &len, flags); @@ -615,7 +615,7 @@ xfs_acl_set_attr( INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm); } INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); - *error = xfs_attr_set(xfs_vtoi(vp), + *error = xfs_attr_set(XFS_I(vp), kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT, (char *)newacl, len, ATTR_ROOT); @@ -639,7 +639,7 @@ xfs_acl_vtoacl( if (error) access_acl->acl_cnt = XFS_ACL_NOT_PRESENT; else /* We have a good ACL and the file mode, synchronize. */ - xfs_acl_sync_mode(xfs_vtoi(vp)->i_d.di_mode, access_acl); + xfs_acl_sync_mode(XFS_I(vp)->i_d.di_mode, access_acl); } if (default_acl) { @@ -734,7 +734,7 @@ xfs_acl_setmode( * mode. The m:: bits take precedence over the g:: bits. */ iattr.ia_valid = ATTR_MODE; - iattr.ia_mode = xfs_vtoi(vp)->i_d.di_mode; + iattr.ia_mode = XFS_I(vp)->i_d.di_mode; iattr.ia_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO); ap = acl->acl_entry; for (i = 0; i < acl->acl_cnt; ++i) { @@ -764,7 +764,7 @@ xfs_acl_setmode( if (gap && nomask) iattr.ia_mode |= gap->ae_perm << 3; - return xfs_setattr(xfs_vtoi(vp), &iattr, 0, sys_cred); + return xfs_setattr(XFS_I(vp), &iattr, 0, sys_cred); } /* diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 4e1e55e..4088951 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -269,11 +269,6 @@ static inline struct xfs_inode *XFS_I(struct inode *inode) return (struct xfs_inode *)inode->i_private; } -static inline struct xfs_inode *xfs_vtoi(bhv_vnode_t *vp) -{ - return XFS_I((struct inode *)vp); -} - /* convert from xfs inode to vfs inode */ static inline struct inode *VFS_I(struct xfs_inode *ip) { -- cgit v1.1 From 6785073ba138a2f0dc575c332c1812b713670b6a Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 16:02:51 +1000 Subject: [XFS] Use KM_NOFS for incore inode extent tree allocation V2 If we allow incore extent tree allocations to recurse into the filesystem under memory pressure, new delayed allocations through xfs_iomap_write_delay() can deadlock on themselves if memory reclaim tries to write back dirty pages from that inode. It will deadlock in xfs_iomap_write_allocate() trying to take the ilock we already hold. This can also show up as complex ABBA deadlocks when multiple threads are triggering memory reclaim when trying to allocate extents. The main cause of this is the fact that delayed allocation is not done in a transaction, so KM_NOFS is not automatically added to the allocations to prevent this recursion. Mark all allocations done for the incore inode extent tree as KM_NOFS to ensure they never recurse back into the filesystem. Version 2: o KM_NOFS implies KM_SLEEP, so just use KM_NOFS SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31726a Signed-off-by: David Chinner Signed-off-by: Niv Sardi Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_inode.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index cfbafc9..8da67d5 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -3707,7 +3707,7 @@ xfs_iext_add_indirect_multi( * (all extents past */ if (nex2) { byte_diff = nex2 * sizeof(xfs_bmbt_rec_t); - nex2_ep = (xfs_bmbt_rec_t *) kmem_alloc(byte_diff, KM_SLEEP); + nex2_ep = (xfs_bmbt_rec_t *) kmem_alloc(byte_diff, KM_NOFS); memmove(nex2_ep, &erp->er_extbuf[idx], byte_diff); erp->er_extcount -= nex2; xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, -nex2); @@ -4007,8 +4007,7 @@ xfs_iext_realloc_direct( ifp->if_u1.if_extents = kmem_realloc(ifp->if_u1.if_extents, rnew_size, - ifp->if_real_bytes, - KM_SLEEP); + ifp->if_real_bytes, KM_NOFS); } if (rnew_size > ifp->if_real_bytes) { memset(&ifp->if_u1.if_extents[ifp->if_bytes / @@ -4067,7 +4066,7 @@ xfs_iext_inline_to_direct( xfs_ifork_t *ifp, /* inode fork pointer */ int new_size) /* number of extents in file */ { - ifp->if_u1.if_extents = kmem_alloc(new_size, KM_SLEEP); + ifp->if_u1.if_extents = kmem_alloc(new_size, KM_NOFS); memset(ifp->if_u1.if_extents, 0, new_size); if (ifp->if_bytes) { memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext, @@ -4099,7 +4098,7 @@ xfs_iext_realloc_indirect( } else { ifp->if_u1.if_ext_irec = (xfs_ext_irec_t *) kmem_realloc(ifp->if_u1.if_ext_irec, - new_size, size, KM_SLEEP); + new_size, size, KM_NOFS); } } @@ -4341,11 +4340,10 @@ xfs_iext_irec_init( nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); ASSERT(nextents <= XFS_LINEAR_EXTS); - erp = (xfs_ext_irec_t *) - kmem_alloc(sizeof(xfs_ext_irec_t), KM_SLEEP); + erp = kmem_alloc(sizeof(xfs_ext_irec_t), KM_NOFS); if (nextents == 0) { - ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP); + ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_NOFS); } else if (!ifp->if_real_bytes) { xfs_iext_inline_to_direct(ifp, XFS_IEXT_BUFSZ); } else if (ifp->if_real_bytes < XFS_IEXT_BUFSZ) { @@ -4393,7 +4391,7 @@ xfs_iext_irec_new( /* Initialize new extent record */ erp = ifp->if_u1.if_ext_irec; - erp[erp_idx].er_extbuf = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP); + erp[erp_idx].er_extbuf = kmem_alloc(XFS_IEXT_BUFSZ, KM_NOFS); ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ; memset(erp[erp_idx].er_extbuf, 0, XFS_IEXT_BUFSZ); erp[erp_idx].er_extcount = 0; -- cgit v1.1 From 5e9da7b7a1edfc75a839b0269935393fa347f38b Mon Sep 17 00:00:00 2001 From: Niv Sardi Date: Wed, 13 Aug 2008 16:03:35 +1000 Subject: [XFS] Move attr log alloc size calculator to another function. We will need that to be able to calculate the size of log we need for a specific attr (for Create+EA). The local flag is needed so that we can fail if we run into ENOSPC when trying to alloc blocks. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31727a Signed-off-by: Niv Sardi Signed-off-by: Christoph Hellwig Signed-off-by: Tim Shimmin Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_attr.c | 80 +++++++++++++++++++++++++++++++++---------------------- fs/xfs/xfs_attr.h | 1 + 2 files changed, 49 insertions(+), 32 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 78de80e..ffa634d 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -194,6 +194,46 @@ xfs_attr_get( return(error); } +/* + * Calculate how many blocks we need for the new attribute, + */ +int +xfs_attr_calc_size( + struct xfs_inode *ip, + int namelen, + int valuelen, + int *local) +{ + struct xfs_mount *mp = ip->i_mount; + int size; + int nblks; + + /* + * Determine space new attribute will use, and if it would be + * "local" or "remote" (note: local != inline). + */ + size = xfs_attr_leaf_newentsize(namelen, valuelen, + mp->m_sb.sb_blocksize, local); + + nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); + if (*local) { + if (size > (mp->m_sb.sb_blocksize >> 1)) { + /* Double split possible */ + nblks *= 2; + } + } else { + /* + * Out of line attribute, cannot double split, but + * make room for the attribute value itself. + */ + uint dblocks = XFS_B_TO_FSB(mp, valuelen); + nblks += dblocks; + nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); + } + + return nblks; +} + STATIC int xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, char *value, int valuelen, int flags) @@ -202,10 +242,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, xfs_fsblock_t firstblock; xfs_bmap_free_t flist; int error, err2, committed; - int local, size; - uint nblks; xfs_mount_t *mp = dp->i_mount; int rsvd = (flags & ATTR_ROOT) != 0; + int local; /* * Attach the dquots to the inode. @@ -241,30 +280,8 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, args.whichfork = XFS_ATTR_FORK; args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; - /* - * Determine space new attribute will use, and if it would be - * "local" or "remote" (note: local != inline). - */ - size = xfs_attr_leaf_newentsize(name->len, valuelen, - mp->m_sb.sb_blocksize, &local); - - nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); - if (local) { - if (size > (mp->m_sb.sb_blocksize >> 1)) { - /* Double split possible */ - nblks <<= 1; - } - } else { - uint dblocks = XFS_B_TO_FSB(mp, valuelen); - /* Out of line attribute, cannot double split, but make - * room for the attribute value itself. - */ - nblks += dblocks; - nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); - } - /* Size is now blocks for attribute data */ - args.total = nblks; + args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local); /* * Start our first transaction of the day. @@ -286,18 +303,17 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, if (rsvd) args.trans->t_flags |= XFS_TRANS_RESERVE; - if ((error = xfs_trans_reserve(args.trans, (uint) nblks, - XFS_ATTRSET_LOG_RES(mp, nblks), - 0, XFS_TRANS_PERM_LOG_RES, - XFS_ATTRSET_LOG_COUNT))) { + if ((error = xfs_trans_reserve(args.trans, args.total, + XFS_ATTRSET_LOG_RES(mp, args.total), 0, + XFS_TRANS_PERM_LOG_RES, XFS_ATTRSET_LOG_COUNT))) { xfs_trans_cancel(args.trans, 0); return(error); } xfs_ilock(dp, XFS_ILOCK_EXCL); - error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0, - rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : - XFS_QMOPT_RES_REGBLKS); + error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, args.total, 0, + rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : + XFS_QMOPT_RES_REGBLKS); if (error) { xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h index 8b2d31c..fb3b2a6 100644 --- a/fs/xfs/xfs_attr.h +++ b/fs/xfs/xfs_attr.h @@ -129,6 +129,7 @@ typedef struct xfs_attr_list_context { /* * Overall external interface routines. */ +int xfs_attr_calc_size(struct xfs_inode *, int, int, int *); int xfs_attr_inactive(struct xfs_inode *dp); int xfs_attr_fetch(struct xfs_inode *, struct xfs_name *, char *, int *, int); int xfs_attr_rmtval_get(struct xfs_da_args *args); -- cgit v1.1 From a738159df2b97398f960978272944cbdd8f726ef Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:04:05 +1000 Subject: [XFS] don't leak m_fsname/m_rtname/m_logname Add a helper to free the m_fsname/m_rtname/m_logname allocations and use it properly for all mount failure cases. Also switch the allocations for these to kstrdup while we're at it. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31728a Signed-off-by: Christoph Hellwig Signed-off-by: Niv Sardi Signed-off-by: David Chinner Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_super.c | 51 +++++++++++++++++++++++++++++++++++--------- fs/xfs/xfs_mount.c | 7 ------ 2 files changed, 41 insertions(+), 17 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index c9ec44a..2775840 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1201,6 +1201,15 @@ xfssyncd( } STATIC void +xfs_free_fsname( + struct xfs_mount *mp) +{ + kfree(mp->m_fsname); + kfree(mp->m_rtname); + kfree(mp->m_logname); +} + +STATIC void xfs_fs_put_super( struct super_block *sb) { @@ -1261,6 +1270,7 @@ xfs_fs_put_super( xfs_close_devices(mp); xfs_qmops_put(mp); xfs_dmops_put(mp); + xfs_free_fsname(mp); kfree(mp); } @@ -1517,6 +1527,8 @@ xfs_start_flags( struct xfs_mount_args *ap, struct xfs_mount *mp) { + int error; + /* Values are in BBs */ if ((ap->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) { /* @@ -1549,17 +1561,27 @@ xfs_start_flags( ap->logbufsize); return XFS_ERROR(EINVAL); } + + error = ENOMEM; + mp->m_logbsize = ap->logbufsize; mp->m_fsname_len = strlen(ap->fsname) + 1; - mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP); - strcpy(mp->m_fsname, ap->fsname); + + mp->m_fsname = kstrdup(ap->fsname, GFP_KERNEL); + if (!mp->m_fsname) + goto out; + if (ap->rtname[0]) { - mp->m_rtname = kmem_alloc(strlen(ap->rtname) + 1, KM_SLEEP); - strcpy(mp->m_rtname, ap->rtname); + mp->m_rtname = kstrdup(ap->rtname, GFP_KERNEL); + if (!mp->m_rtname) + goto out_free_fsname; + } + if (ap->logname[0]) { - mp->m_logname = kmem_alloc(strlen(ap->logname) + 1, KM_SLEEP); - strcpy(mp->m_logname, ap->logname); + mp->m_logname = kstrdup(ap->logname, GFP_KERNEL); + if (!mp->m_logname) + goto out_free_rtname; } if (ap->flags & XFSMNT_WSYNC) @@ -1632,6 +1654,14 @@ xfs_start_flags( if (ap->flags & XFSMNT_DMAPI) mp->m_flags |= XFS_MOUNT_DMAPI; return 0; + + + out_free_rtname: + kfree(mp->m_rtname); + out_free_fsname: + kfree(mp->m_fsname); + out: + return error; } /* @@ -1792,10 +1822,10 @@ xfs_fs_fill_super( */ error = xfs_start_flags(args, mp); if (error) - goto out_destroy_counters; + goto out_free_fsname; error = xfs_readsb(mp, flags); if (error) - goto out_destroy_counters; + goto out_free_fsname; error = xfs_finish_flags(args, mp); if (error) goto out_free_sb; @@ -1857,7 +1887,8 @@ xfs_fs_fill_super( xfs_filestream_unmount(mp); out_free_sb: xfs_freesb(mp); - out_destroy_counters: + out_free_fsname: + xfs_free_fsname(mp); xfs_icsb_destroy_counters(mp); xfs_close_devices(mp); out_put_qmops: @@ -1893,7 +1924,7 @@ xfs_fs_fill_super( IRELE(mp->m_rootip); xfs_unmountfs(mp); - goto out_destroy_counters; + goto out_free_fsname; } STATIC int diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 6c5d132..31699b1 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -146,13 +146,6 @@ xfs_mount_free( mutex_destroy(&mp->m_growlock); if (mp->m_quotainfo) XFS_QM_DONE(mp); - - if (mp->m_fsname != NULL) - kmem_free(mp->m_fsname); - if (mp->m_rtname != NULL) - kmem_free(mp->m_rtname); - if (mp->m_logname != NULL) - kmem_free(mp->m_logname); } /* -- cgit v1.1 From 322ff6b8cd54feb1c4c0426630f3642ab1dd2176 Mon Sep 17 00:00:00 2001 From: Niv Sardi Date: Wed, 13 Aug 2008 16:05:49 +1000 Subject: [XFS] Move xfs_attr_rolltrans to xfs_trans_roll Move it from the attr code to the transaction code and make the attr code call the new function. We rolltrans is really usefull whenever we want to use rolling transaction, should be generic, it isn't dependent on any part of the attr code anyway. We use this excuse to change all the: if ((error = xfs_attr_rolltrans())) calls into: error = xfs_trans_roll(); if (error) SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31729a Signed-off-by: Niv Sardi Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_attr.c | 30 +++++++++++++------- fs/xfs/xfs_attr_leaf.c | 75 ++++++-------------------------------------------- fs/xfs/xfs_attr_leaf.h | 2 -- fs/xfs/xfs_trans.c | 63 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_trans.h | 1 + 5 files changed, 92 insertions(+), 79 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index ffa634d..f7cdc28 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -400,7 +400,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, * Commit the leaf transformation. We'll need another (linked) * transaction to add the new attribute to the leaf. */ - if ((error = xfs_attr_rolltrans(&args.trans, dp))) + + error = xfs_trans_roll(&args.trans, dp); + if (error) goto out; } @@ -980,7 +982,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * Commit the current trans (including the inode) and start * a new one. */ - if ((error = xfs_attr_rolltrans(&args->trans, dp))) + error = xfs_trans_roll(&args->trans, dp); + if (error) return (error); /* @@ -994,7 +997,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * Commit the transaction that added the attr name so that * later routines can manage their own transactions. */ - if ((error = xfs_attr_rolltrans(&args->trans, dp))) + error = xfs_trans_roll(&args->trans, dp); + if (error) return (error); /* @@ -1083,7 +1087,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) /* * Commit the remove and start the next trans in series. */ - error = xfs_attr_rolltrans(&args->trans, dp); + error = xfs_trans_roll(&args->trans, dp); } else if (args->rmtblkno > 0) { /* @@ -1314,7 +1318,8 @@ restart: * Commit the node conversion and start the next * trans in the chain. */ - if ((error = xfs_attr_rolltrans(&args->trans, dp))) + error = xfs_trans_roll(&args->trans, dp); + if (error) goto out; goto restart; @@ -1365,7 +1370,8 @@ restart: * Commit the leaf addition or btree split and start the next * trans in the chain. */ - if ((error = xfs_attr_rolltrans(&args->trans, dp))) + error = xfs_trans_roll(&args->trans, dp); + if (error) goto out; /* @@ -1465,7 +1471,8 @@ restart: /* * Commit and start the next trans in the chain. */ - if ((error = xfs_attr_rolltrans(&args->trans, dp))) + error = xfs_trans_roll(&args->trans, dp); + if (error) goto out; } else if (args->rmtblkno > 0) { @@ -1597,7 +1604,8 @@ xfs_attr_node_removename(xfs_da_args_t *args) /* * Commit the Btree join operation and start a new trans. */ - if ((error = xfs_attr_rolltrans(&args->trans, dp))) + error = xfs_trans_roll(&args->trans, dp); + if (error) goto out; } @@ -2098,7 +2106,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) /* * Start the next trans in the chain. */ - if ((error = xfs_attr_rolltrans(&args->trans, dp))) + error = xfs_trans_roll(&args->trans, dp); + if (error) return (error); } @@ -2248,7 +2257,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) /* * Close out trans and start the next one in the chain. */ - if ((error = xfs_attr_rolltrans(&args->trans, args->dp))) + error = xfs_trans_roll(&args->trans, args->dp); + if (error) return (error); } return(0); diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 23ef5d7..79da6b2 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -2498,9 +2498,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) /* * Commit the flag value change and start the next trans in series. */ - error = xfs_attr_rolltrans(&args->trans, args->dp); - - return(error); + return xfs_trans_roll(&args->trans, args->dp); } /* @@ -2547,9 +2545,7 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args) /* * Commit the flag value change and start the next trans in series. */ - error = xfs_attr_rolltrans(&args->trans, args->dp); - - return(error); + return xfs_trans_roll(&args->trans, args->dp); } /* @@ -2665,7 +2661,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) /* * Commit the flag value change and start the next trans in series. */ - error = xfs_attr_rolltrans(&args->trans, args->dp); + error = xfs_trans_roll(&args->trans, args->dp); return(error); } @@ -2723,7 +2719,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) /* * Commit the invalidate and start the next transaction. */ - error = xfs_attr_rolltrans(trans, dp); + error = xfs_trans_roll(trans, dp); return (error); } @@ -2825,7 +2821,8 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, /* * Atomically commit the whole invalidate stuff. */ - if ((error = xfs_attr_rolltrans(trans, dp))) + error = xfs_trans_roll(trans, dp); + if (error) return (error); } @@ -2964,7 +2961,8 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, /* * Roll to next transaction. */ - if ((error = xfs_attr_rolltrans(trans, dp))) + error = xfs_trans_roll(trans, dp); + if (error) return (error); } @@ -2974,60 +2972,3 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, return(0); } - - -/* - * Roll from one trans in the sequence of PERMANENT transactions to the next. - */ -int -xfs_attr_rolltrans(xfs_trans_t **transp, xfs_inode_t *dp) -{ - xfs_trans_t *trans; - unsigned int logres, count; - int error; - - /* - * Ensure that the inode is always logged. - */ - trans = *transp; - xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE); - - /* - * Copy the critical parameters from one trans to the next. - */ - logres = trans->t_log_res; - count = trans->t_log_count; - *transp = xfs_trans_dup(trans); - - /* - * Commit the current transaction. - * If this commit failed, then it'd just unlock those items that - * are not marked ihold. That also means that a filesystem shutdown - * is in progress. The caller takes the responsibility to cancel - * the duplicate transaction that gets returned. - */ - if ((error = xfs_trans_commit(trans, 0))) - return (error); - - trans = *transp; - - /* - * Reserve space in the log for th next transaction. - * This also pushes items in the "AIL", the list of logged items, - * out to disk if they are taking up space at the tail of the log - * that we want to use. This requires that either nothing be locked - * across this call, or that anything that is locked be logged in - * the prior and the next transactions. - */ - error = xfs_trans_reserve(trans, 0, logres, 0, - XFS_TRANS_PERM_LOG_RES, count); - /* - * Ensure that the inode is in the new transaction and locked. - */ - if (!error) { - xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL); - xfs_trans_ihold(trans, dp); - } - return (error); - -} diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h index 5ecf437..83e9af4 100644 --- a/fs/xfs/xfs_attr_leaf.h +++ b/fs/xfs/xfs_attr_leaf.h @@ -274,6 +274,4 @@ int xfs_attr_leaf_order(struct xfs_dabuf *leaf1_bp, struct xfs_dabuf *leaf2_bp); int xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local); -int xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp); - #endif /* __XFS_ATTR_LEAF_H__ */ diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index e4ebddd..d98758a 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -43,6 +43,7 @@ #include "xfs_quota.h" #include "xfs_trans_priv.h" #include "xfs_trans_space.h" +#include "xfs_inode_item.h" STATIC void xfs_trans_apply_sb_deltas(xfs_trans_t *); @@ -1216,6 +1217,68 @@ xfs_trans_free( kmem_zone_free(xfs_trans_zone, tp); } +/* + * Roll from one trans in the sequence of PERMANENT transactions to + * the next: permanent transactions are only flushed out when + * committed with XFS_TRANS_RELEASE_LOG_RES, but we still want as soon + * as possible to let chunks of it go to the log. So we commit the + * chunk we've been working on and get a new transaction to continue. + */ +int +xfs_trans_roll( + struct xfs_trans **tpp, + struct xfs_inode *dp) +{ + struct xfs_trans *trans; + unsigned int logres, count; + int error; + + /* + * Ensure that the inode is always logged. + */ + trans = *tpp; + xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE); + + /* + * Copy the critical parameters from one trans to the next. + */ + logres = trans->t_log_res; + count = trans->t_log_count; + *tpp = xfs_trans_dup(trans); + + /* + * Commit the current transaction. + * If this commit failed, then it'd just unlock those items that + * are not marked ihold. That also means that a filesystem shutdown + * is in progress. The caller takes the responsibility to cancel + * the duplicate transaction that gets returned. + */ + error = xfs_trans_commit(trans, 0); + if (error) + return (error); + + trans = *tpp; + + /* + * Reserve space in the log for th next transaction. + * This also pushes items in the "AIL", the list of logged items, + * out to disk if they are taking up space at the tail of the log + * that we want to use. This requires that either nothing be locked + * across this call, or that anything that is locked be logged in + * the prior and the next transactions. + */ + error = xfs_trans_reserve(trans, 0, logres, 0, + XFS_TRANS_PERM_LOG_RES, count); + /* + * Ensure that the inode is in the new transaction and locked. + */ + if (error) + return error; + + xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL); + xfs_trans_ihold(trans, dp); + return 0; +} /* * THIS SHOULD BE REWRITTEN TO USE xfs_trans_next_item(). diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 0804207..9161e99 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -986,6 +986,7 @@ int _xfs_trans_commit(xfs_trans_t *, int *); #define xfs_trans_commit(tp, flags) _xfs_trans_commit(tp, flags, NULL) void xfs_trans_cancel(xfs_trans_t *, int); +int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); int xfs_trans_ail_init(struct xfs_mount *); void xfs_trans_ail_destroy(struct xfs_mount *); void xfs_trans_push_ail(struct xfs_mount *, xfs_lsn_t); -- cgit v1.1 From cdeb380aa2ca3b8f8ba3736f2469f5818eadb9aa Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 13 Aug 2008 16:07:53 +1000 Subject: [XFS] remove INT_GET and friends Thanks to hch's endian work, INT_GET etc are no longer used, and may as well be removed. INT_SET is still used in the acl code, though. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31756a Signed-off-by: Eric Sandeen Signed-off-by: Niv Sardi Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_arch.h | 68 ------------------------------------------------------- 1 file changed, 68 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_arch.h b/fs/xfs/xfs_arch.h index f9472a2..0b3b5ef 100644 --- a/fs/xfs/xfs_arch.h +++ b/fs/xfs/xfs_arch.h @@ -92,16 +92,6 @@ ((__u8*)(pointer))[1] = (((value) ) & 0xff); \ } -/* define generic INT_ macros */ - -#define INT_GET(reference,arch) \ - (((arch) == ARCH_NOCONVERT) \ - ? \ - (reference) \ - : \ - INT_SWAP((reference),(reference)) \ - ) - /* does not return a value */ #define INT_SET(reference,arch,valueref) \ (__builtin_constant_p(valueref) ? \ @@ -112,64 +102,6 @@ ) \ ) -/* does not return a value */ -#define INT_MOD_EXPR(reference,arch,code) \ - (((arch) == ARCH_NOCONVERT) \ - ? \ - (void)((reference) code) \ - : \ - (void)( \ - (reference) = INT_GET((reference),arch) , \ - ((reference) code), \ - INT_SET(reference, arch, reference) \ - ) \ - ) - -/* does not return a value */ -#define INT_MOD(reference,arch,delta) \ - (void)( \ - INT_MOD_EXPR(reference,arch,+=(delta)) \ - ) - -/* - * INT_COPY - copy a value between two locations with the - * _same architecture_ but _potentially different sizes_ - * - * if the types of the two parameters are equal or they are - * in native architecture, a simple copy is done - * - * otherwise, architecture conversions are done - * - */ - -/* does not return a value */ -#define INT_COPY(dst,src,arch) \ - ( \ - ((sizeof(dst) == sizeof(src)) || ((arch) == ARCH_NOCONVERT)) \ - ? \ - (void)((dst) = (src)) \ - : \ - INT_SET(dst, arch, INT_GET(src, arch)) \ - ) - -/* - * INT_XLATE - copy a value in either direction between two locations - * with different architectures - * - * dir < 0 - copy from memory to buffer (native to arch) - * dir > 0 - copy from buffer to memory (arch to native) - */ - -/* does not return a value */ -#define INT_XLATE(buf,mem,dir,arch) {\ - ASSERT(dir); \ - if (dir>0) { \ - (mem)=INT_GET(buf, arch); \ - } else { \ - INT_SET(buf, arch, mem); \ - } \ -} - /* * In directories inode numbers are stored as unaligned arrays of unsigned * 8bit integers on disk. -- cgit v1.1 From db7a2c71d287686eef1d4df1565fa32f89a9fe68 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 13 Aug 2008 16:09:25 +1000 Subject: [XFS] convert xfs to use ERR_CAST Looks like somehow xfs got missed in the conversion that took place in e231c2ee64eb1c5cd3c63c31da9dac7d888dcf7f, "Convert ERR_PTR(PTR_ERR(p)) instances to ERR_CAST(p) " SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31757a Signed-off-by: Eric Sandeen Acked-by: David Howells Signed-off-by: Niv Sardi Signed-off-by: Christoph Hellwig Signed-off-by: David Howells Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_export.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index d3880b7..24fd598 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -167,7 +167,7 @@ xfs_fs_fh_to_dentry(struct super_block *sb, struct fid *fid, if (!inode) return NULL; if (IS_ERR(inode)) - return ERR_PTR(PTR_ERR(inode)); + return ERR_CAST(inode); result = d_alloc_anon(inode); if (!result) { iput(inode); @@ -198,7 +198,7 @@ xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, if (!inode) return NULL; if (IS_ERR(inode)) - return ERR_PTR(PTR_ERR(inode)); + return ERR_CAST(inode); result = d_alloc_anon(inode); if (!result) { iput(inode); -- cgit v1.1 From 39dab9d7daf5f664a3569378107a2cb284c8a594 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 13 Aug 2008 16:10:52 +1000 Subject: [XFS] remove shouting-indirection macros from xfs_trans.h SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31758a Signed-off-by: Eric Sandeen Signed-off-by: Niv Sardi Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_bmap.c | 6 ++--- fs/xfs/xfs_trans.c | 12 ++++----- fs/xfs/xfs_trans.h | 11 --------- fs/xfs/xfs_trans_buf.c | 12 ++++----- fs/xfs/xfs_trans_item.c | 66 ++++++++++++++++++++++++------------------------- 5 files changed, 48 insertions(+), 59 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 2f46b67..bac82af 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -6096,7 +6096,7 @@ xfs_bmap_get_bp( tp = cur->bc_tp; licp = &tp->t_items; while (!bp && licp != NULL) { - if (XFS_LIC_ARE_ALL_FREE(licp)) { + if (xfs_lic_are_all_free(licp)) { licp = licp->lic_next; continue; } @@ -6106,11 +6106,11 @@ xfs_bmap_get_bp( xfs_buf_log_item_t *bip; xfs_buf_t *lbp; - if (XFS_LIC_ISFREE(licp, i)) { + if (xfs_lic_isfree(licp, i)) { continue; } - lidp = XFS_LIC_SLOT(licp, i); + lidp = xfs_lic_slot(licp, i); lip = lidp->lid_item; if (lip->li_type != XFS_LI_BUF) continue; diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index d98758a..4e1c22a 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -254,7 +254,7 @@ _xfs_trans_alloc( tp->t_mountp = mp; tp->t_items_free = XFS_LIC_NUM_SLOTS; tp->t_busy_free = XFS_LBC_NUM_SLOTS; - XFS_LIC_INIT(&(tp->t_items)); + xfs_lic_init(&(tp->t_items)); XFS_LBC_INIT(&(tp->t_busy)); return tp; } @@ -283,7 +283,7 @@ xfs_trans_dup( ntp->t_mountp = tp->t_mountp; ntp->t_items_free = XFS_LIC_NUM_SLOTS; ntp->t_busy_free = XFS_LBC_NUM_SLOTS; - XFS_LIC_INIT(&(ntp->t_items)); + xfs_lic_init(&(ntp->t_items)); XFS_LBC_INIT(&(ntp->t_busy)); ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); @@ -1170,7 +1170,7 @@ xfs_trans_cancel( while (licp != NULL) { lidp = licp->lic_descs; for (i = 0; i < licp->lic_unused; i++, lidp++) { - if (XFS_LIC_ISFREE(licp, i)) { + if (xfs_lic_isfree(licp, i)) { continue; } @@ -1316,7 +1316,7 @@ xfs_trans_committed( * Special case the chunk embedded in the transaction. */ licp = &(tp->t_items); - if (!(XFS_LIC_ARE_ALL_FREE(licp))) { + if (!(xfs_lic_are_all_free(licp))) { xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag); } @@ -1325,7 +1325,7 @@ xfs_trans_committed( */ licp = licp->lic_next; while (licp != NULL) { - ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); + ASSERT(!xfs_lic_are_all_free(licp)); xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag); next_licp = licp->lic_next; kmem_free(licp); @@ -1388,7 +1388,7 @@ xfs_trans_chunk_committed( lidp = licp->lic_descs; for (i = 0; i < licp->lic_unused; i++, lidp++) { - if (XFS_LIC_ISFREE(licp, i)) { + if (xfs_lic_isfree(licp, i)) { continue; } diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 9161e99..74c80bd 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -210,62 +210,52 @@ typedef struct xfs_log_item_chunk { * lic_unused to the right value (0 matches all free). The * lic_descs.lid_index values are set up as each desc is allocated. */ -#define XFS_LIC_INIT(cp) xfs_lic_init(cp) static inline void xfs_lic_init(xfs_log_item_chunk_t *cp) { cp->lic_free = XFS_LIC_FREEMASK; } -#define XFS_LIC_INIT_SLOT(cp,slot) xfs_lic_init_slot(cp, slot) static inline void xfs_lic_init_slot(xfs_log_item_chunk_t *cp, int slot) { cp->lic_descs[slot].lid_index = (unsigned char)(slot); } -#define XFS_LIC_VACANCY(cp) xfs_lic_vacancy(cp) static inline int xfs_lic_vacancy(xfs_log_item_chunk_t *cp) { return cp->lic_free & XFS_LIC_FREEMASK; } -#define XFS_LIC_ALL_FREE(cp) xfs_lic_all_free(cp) static inline void xfs_lic_all_free(xfs_log_item_chunk_t *cp) { cp->lic_free = XFS_LIC_FREEMASK; } -#define XFS_LIC_ARE_ALL_FREE(cp) xfs_lic_are_all_free(cp) static inline int xfs_lic_are_all_free(xfs_log_item_chunk_t *cp) { return ((cp->lic_free & XFS_LIC_FREEMASK) == XFS_LIC_FREEMASK); } -#define XFS_LIC_ISFREE(cp,slot) xfs_lic_isfree(cp,slot) static inline int xfs_lic_isfree(xfs_log_item_chunk_t *cp, int slot) { return (cp->lic_free & (1 << slot)); } -#define XFS_LIC_CLAIM(cp,slot) xfs_lic_claim(cp,slot) static inline void xfs_lic_claim(xfs_log_item_chunk_t *cp, int slot) { cp->lic_free &= ~(1 << slot); } -#define XFS_LIC_RELSE(cp,slot) xfs_lic_relse(cp,slot) static inline void xfs_lic_relse(xfs_log_item_chunk_t *cp, int slot) { cp->lic_free |= 1 << slot; } -#define XFS_LIC_SLOT(cp,slot) xfs_lic_slot(cp,slot) static inline xfs_log_item_desc_t * xfs_lic_slot(xfs_log_item_chunk_t *cp, int slot) { return &(cp->lic_descs[slot]); } -#define XFS_LIC_DESC_TO_SLOT(dp) xfs_lic_desc_to_slot(dp) static inline int xfs_lic_desc_to_slot(xfs_log_item_desc_t *dp) { return (uint)dp->lid_index; @@ -278,7 +268,6 @@ static inline int xfs_lic_desc_to_slot(xfs_log_item_desc_t *dp) * All of this yields the address of the chunk, which is * cast to a chunk pointer. */ -#define XFS_LIC_DESC_TO_CHUNK(dp) xfs_lic_desc_to_chunk(dp) static inline xfs_log_item_chunk_t * xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) { diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index cb0c583..4e855b5 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -1021,16 +1021,16 @@ xfs_trans_buf_item_match( bp = NULL; len = BBTOB(len); licp = &tp->t_items; - if (!XFS_LIC_ARE_ALL_FREE(licp)) { + if (!xfs_lic_are_all_free(licp)) { for (i = 0; i < licp->lic_unused; i++) { /* * Skip unoccupied slots. */ - if (XFS_LIC_ISFREE(licp, i)) { + if (xfs_lic_isfree(licp, i)) { continue; } - lidp = XFS_LIC_SLOT(licp, i); + lidp = xfs_lic_slot(licp, i); blip = (xfs_buf_log_item_t *)lidp->lid_item; if (blip->bli_item.li_type != XFS_LI_BUF) { continue; @@ -1074,7 +1074,7 @@ xfs_trans_buf_item_match_all( bp = NULL; len = BBTOB(len); for (licp = &tp->t_items; licp != NULL; licp = licp->lic_next) { - if (XFS_LIC_ARE_ALL_FREE(licp)) { + if (xfs_lic_are_all_free(licp)) { ASSERT(licp == &tp->t_items); ASSERT(licp->lic_next == NULL); return NULL; @@ -1083,11 +1083,11 @@ xfs_trans_buf_item_match_all( /* * Skip unoccupied slots. */ - if (XFS_LIC_ISFREE(licp, i)) { + if (xfs_lic_isfree(licp, i)) { continue; } - lidp = XFS_LIC_SLOT(licp, i); + lidp = xfs_lic_slot(licp, i); blip = (xfs_buf_log_item_t *)lidp->lid_item; if (blip->bli_item.li_type != XFS_LI_BUF) { continue; diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c index db5c835..3c666e8 100644 --- a/fs/xfs/xfs_trans_item.c +++ b/fs/xfs/xfs_trans_item.c @@ -53,11 +53,11 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip) * Initialize the chunk, and then * claim the first slot in the newly allocated chunk. */ - XFS_LIC_INIT(licp); - XFS_LIC_CLAIM(licp, 0); + xfs_lic_init(licp); + xfs_lic_claim(licp, 0); licp->lic_unused = 1; - XFS_LIC_INIT_SLOT(licp, 0); - lidp = XFS_LIC_SLOT(licp, 0); + xfs_lic_init_slot(licp, 0); + lidp = xfs_lic_slot(licp, 0); /* * Link in the new chunk and update the free count. @@ -88,14 +88,14 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip) */ licp = &tp->t_items; while (licp != NULL) { - if (XFS_LIC_VACANCY(licp)) { + if (xfs_lic_vacancy(licp)) { if (licp->lic_unused <= XFS_LIC_MAX_SLOT) { i = licp->lic_unused; - ASSERT(XFS_LIC_ISFREE(licp, i)); + ASSERT(xfs_lic_isfree(licp, i)); break; } for (i = 0; i <= XFS_LIC_MAX_SLOT; i++) { - if (XFS_LIC_ISFREE(licp, i)) + if (xfs_lic_isfree(licp, i)) break; } ASSERT(i <= XFS_LIC_MAX_SLOT); @@ -108,12 +108,12 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip) * If we find a free descriptor, claim it, * initialize it, and return it. */ - XFS_LIC_CLAIM(licp, i); + xfs_lic_claim(licp, i); if (licp->lic_unused <= i) { licp->lic_unused = i + 1; - XFS_LIC_INIT_SLOT(licp, i); + xfs_lic_init_slot(licp, i); } - lidp = XFS_LIC_SLOT(licp, i); + lidp = xfs_lic_slot(licp, i); tp->t_items_free--; lidp->lid_item = lip; lidp->lid_flags = 0; @@ -136,9 +136,9 @@ xfs_trans_free_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) xfs_log_item_chunk_t *licp; xfs_log_item_chunk_t **licpp; - slot = XFS_LIC_DESC_TO_SLOT(lidp); - licp = XFS_LIC_DESC_TO_CHUNK(lidp); - XFS_LIC_RELSE(licp, slot); + slot = xfs_lic_desc_to_slot(lidp); + licp = xfs_lic_desc_to_chunk(lidp); + xfs_lic_relse(licp, slot); lidp->lid_item->li_desc = NULL; tp->t_items_free++; @@ -154,7 +154,7 @@ xfs_trans_free_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) * Also decrement the transaction structure's count of free items * by the number in a chunk since we are freeing an empty chunk. */ - if (XFS_LIC_ARE_ALL_FREE(licp) && (licp != &(tp->t_items))) { + if (xfs_lic_are_all_free(licp) && (licp != &(tp->t_items))) { licpp = &(tp->t_items.lic_next); while (*licpp != licp) { ASSERT(*licpp != NULL); @@ -207,20 +207,20 @@ xfs_trans_first_item(xfs_trans_t *tp) /* * If it's not in the first chunk, skip to the second. */ - if (XFS_LIC_ARE_ALL_FREE(licp)) { + if (xfs_lic_are_all_free(licp)) { licp = licp->lic_next; } /* * Return the first non-free descriptor in the chunk. */ - ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); + ASSERT(!xfs_lic_are_all_free(licp)); for (i = 0; i < licp->lic_unused; i++) { - if (XFS_LIC_ISFREE(licp, i)) { + if (xfs_lic_isfree(licp, i)) { continue; } - return XFS_LIC_SLOT(licp, i); + return xfs_lic_slot(licp, i); } cmn_err(CE_WARN, "xfs_trans_first_item() -- no first item"); return NULL; @@ -242,18 +242,18 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) xfs_log_item_chunk_t *licp; int i; - licp = XFS_LIC_DESC_TO_CHUNK(lidp); + licp = xfs_lic_desc_to_chunk(lidp); /* * First search the rest of the chunk. The for loop keeps us * from referencing things beyond the end of the chunk. */ - for (i = (int)XFS_LIC_DESC_TO_SLOT(lidp) + 1; i < licp->lic_unused; i++) { - if (XFS_LIC_ISFREE(licp, i)) { + for (i = (int)xfs_lic_desc_to_slot(lidp) + 1; i < licp->lic_unused; i++) { + if (xfs_lic_isfree(licp, i)) { continue; } - return XFS_LIC_SLOT(licp, i); + return xfs_lic_slot(licp, i); } /* @@ -266,13 +266,13 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) } licp = licp->lic_next; - ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); + ASSERT(!xfs_lic_are_all_free(licp)); for (i = 0; i < licp->lic_unused; i++) { - if (XFS_LIC_ISFREE(licp, i)) { + if (xfs_lic_isfree(licp, i)) { continue; } - return XFS_LIC_SLOT(licp, i); + return xfs_lic_slot(licp, i); } ASSERT(0); /* NOTREACHED */ @@ -300,9 +300,9 @@ xfs_trans_free_items( /* * Special case the embedded chunk so we don't free it below. */ - if (!XFS_LIC_ARE_ALL_FREE(licp)) { + if (!xfs_lic_are_all_free(licp)) { (void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN); - XFS_LIC_ALL_FREE(licp); + xfs_lic_all_free(licp); licp->lic_unused = 0; } licp = licp->lic_next; @@ -311,7 +311,7 @@ xfs_trans_free_items( * Unlock each item in each chunk and free the chunks. */ while (licp != NULL) { - ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); + ASSERT(!xfs_lic_are_all_free(licp)); (void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN); next_licp = licp->lic_next; kmem_free(licp); @@ -347,7 +347,7 @@ xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn) /* * Special case the embedded chunk so we don't free. */ - if (!XFS_LIC_ARE_ALL_FREE(licp)) { + if (!xfs_lic_are_all_free(licp)) { freed = xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn); } licpp = &(tp->t_items.lic_next); @@ -358,10 +358,10 @@ xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn) * and free empty chunks. */ while (licp != NULL) { - ASSERT(!XFS_LIC_ARE_ALL_FREE(licp)); + ASSERT(!xfs_lic_are_all_free(licp)); freed += xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn); next_licp = licp->lic_next; - if (XFS_LIC_ARE_ALL_FREE(licp)) { + if (xfs_lic_are_all_free(licp)) { *licpp = next_licp; kmem_free(licp); freed -= XFS_LIC_NUM_SLOTS; @@ -402,7 +402,7 @@ xfs_trans_unlock_chunk( freed = 0; lidp = licp->lic_descs; for (i = 0; i < licp->lic_unused; i++, lidp++) { - if (XFS_LIC_ISFREE(licp, i)) { + if (xfs_lic_isfree(licp, i)) { continue; } lip = lidp->lid_item; @@ -421,7 +421,7 @@ xfs_trans_unlock_chunk( */ if (!(freeing_chunk) && (!(lidp->lid_flags & XFS_LID_DIRTY) || abort)) { - XFS_LIC_RELSE(licp, i); + xfs_lic_relse(licp, i); freed++; } } -- cgit v1.1 From a19d033cd2cc66120f01b370ec081d67b59b7924 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:11:26 +1000 Subject: [XFS] Remove vn_from_inode() bhv_vnode_t is just a typedef for struct inode, so there's no need for a helper to convert between the two. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31760a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_super.c | 2 +- fs/xfs/linux-2.6/xfs_vnode.h | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 2775840..184ef14 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -994,7 +994,7 @@ STATIC void xfs_fs_destroy_inode( struct inode *inode) { - kmem_zone_free(xfs_vnode_zone, vn_from_inode(inode)); + kmem_zone_free(xfs_vnode_zone, inode); } STATIC void diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index c3afecf..536515c 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -27,10 +27,6 @@ typedef struct inode bhv_vnode_t; /* * Vnode to Linux inode mapping. */ -static inline bhv_vnode_t *vn_from_inode(struct inode *inode) -{ - return inode; -} static inline struct inode *vn_to_inode(bhv_vnode_t *vnode) { return vnode; @@ -100,8 +96,7 @@ extern bhv_vnode_t *vn_hold(bhv_vnode_t *); static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp) { - struct inode *inode = igrab(vn_to_inode(vp)); - return inode ? vn_from_inode(inode) : NULL; + return igrab(vn_to_inode(vp)); } /* -- cgit v1.1 From 863890cd90e8b213f7028036c6e2200d93223527 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:12:05 +1000 Subject: [XFS] kill vn_to_inode bhv_vnode_t is just a typedef for struct inode, so there's no need for a helper to convert between the two. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31761a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_linux.h | 2 +- fs/xfs/linux-2.6/xfs_super.c | 14 ++++++-------- fs/xfs/linux-2.6/xfs_vnode.c | 2 +- fs/xfs/linux-2.6/xfs_vnode.h | 24 ++++++++---------------- fs/xfs/xfs_vnodeops.c | 4 ++-- 5 files changed, 18 insertions(+), 28 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index a9cd6e4..1b8dfdc 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -180,7 +180,7 @@ #define xfs_sort(a,n,s,fn) sort(a,n,s,fn,NULL) #define xfs_stack_trace() dump_stack() #define xfs_itruncate_data(ip, off) \ - (-vmtruncate(vn_to_inode(VFS_I(ip)), (off))) + (-vmtruncate(VFS_I(ip), (off))) /* Move the kernel do_div definition off to one side */ diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 184ef14..71ac3a6 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -613,10 +613,9 @@ xfs_set_inodeops( STATIC_INLINE void xfs_revalidate_inode( xfs_mount_t *mp, - bhv_vnode_t *vp, + struct inode *inode, xfs_inode_t *ip) { - struct inode *inode = vn_to_inode(vp); inode->i_mode = ip->i_d.di_mode; inode->i_nlink = ip->i_d.di_nlink; @@ -665,13 +664,12 @@ xfs_revalidate_inode( void xfs_initialize_vnode( struct xfs_mount *mp, - bhv_vnode_t *vp, + struct inode *inode, struct xfs_inode *ip) { - struct inode *inode = vn_to_inode(vp); if (!ip->i_vnode) { - ip->i_vnode = vp; + ip->i_vnode = inode; inode->i_private = ip; } @@ -683,7 +681,7 @@ xfs_initialize_vnode( * finish our work. */ if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) { - xfs_revalidate_inode(mp, vp, ip); + xfs_revalidate_inode(mp, inode, ip); xfs_set_inodeops(inode); xfs_iflags_clear(ip, XFS_INEW); @@ -987,7 +985,7 @@ xfs_fs_alloc_inode( vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); if (unlikely(!vp)) return NULL; - return vn_to_inode(vp); + return vp; } STATIC void @@ -1001,7 +999,7 @@ STATIC void xfs_fs_inode_init_once( void *vnode) { - inode_init_once(vn_to_inode((bhv_vnode_t *)vnode)); + inode_init_once((struct inode *)vnode); } /* diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 1e39d04..4af972b 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -94,7 +94,7 @@ vn_hold( XFS_STATS_INC(vn_hold); - inode = igrab(vn_to_inode(vp)); + inode = igrab(vp); ASSERT(inode); return vp; diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 536515c..cc53687 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -25,14 +25,6 @@ struct attrlist_cursor_kern; typedef struct inode bhv_vnode_t; /* - * Vnode to Linux inode mapping. - */ -static inline struct inode *vn_to_inode(bhv_vnode_t *vnode) -{ - return vnode; -} - -/* * Return values for xfs_inactive. A return value of * VN_INACTIVE_NOCACHE implies that the file system behavior * has disassociated its state and bhv_desc_t from the vnode. @@ -74,7 +66,7 @@ extern void vn_ioerror(struct xfs_inode *ip, int error, char *f, int l); static inline int vn_count(bhv_vnode_t *vp) { - return atomic_read(&vn_to_inode(vp)->i_count); + return atomic_read(&vp->i_count); } /* @@ -88,15 +80,15 @@ extern bhv_vnode_t *vn_hold(bhv_vnode_t *); xfs_itrace_hold(XFS_I(vp), __FILE__, __LINE__, (inst_t *)__return_address)) #define VN_RELE(vp) \ (xfs_itrace_rele(XFS_I(vp), __FILE__, __LINE__, (inst_t *)__return_address), \ - iput(vn_to_inode(vp))) + iput(vp)) #else #define VN_HOLD(vp) ((void)vn_hold(vp)) -#define VN_RELE(vp) (iput(vn_to_inode(vp))) +#define VN_RELE(vp) (iput(vp)) #endif static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp) { - return igrab(vn_to_inode(vp)); + return igrab(vp); } /* @@ -104,7 +96,7 @@ static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp) */ static inline int VN_BAD(bhv_vnode_t *vp) { - return is_bad_inode(vn_to_inode(vp)); + return is_bad_inode(vp); } /* @@ -129,9 +121,9 @@ static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt) /* * Some useful predicates. */ -#define VN_MAPPED(vp) mapping_mapped(vn_to_inode(vp)->i_mapping) -#define VN_CACHED(vp) (vn_to_inode(vp)->i_mapping->nrpages) -#define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \ +#define VN_MAPPED(vp) mapping_mapped(vp->i_mapping) +#define VN_CACHED(vp) (vp->i_mapping->nrpages) +#define VN_DIRTY(vp) mapping_tagged(vp->i_mapping, \ PAGECACHE_TAG_DIRTY) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 35a053f..c5dc7ea 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -714,7 +714,7 @@ xfs_fsync( return XFS_ERROR(EIO); /* capture size updates in I/O completion before writing the inode. */ - error = filemap_fdatawait(vn_to_inode(VFS_I(ip))->i_mapping); + error = filemap_fdatawait(VFS_I(ip)->i_mapping); if (error) return XFS_ERROR(error); @@ -2917,7 +2917,7 @@ xfs_reclaim( XFS_MOUNT_ILOCK(mp); spin_lock(&ip->i_flags_lock); __xfs_iflags_set(ip, XFS_IRECLAIMABLE); - vn_to_inode(vp)->i_private = NULL; + vp->i_private = NULL; ip->i_vnode = NULL; spin_unlock(&ip->i_flags_lock); list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); -- cgit v1.1 From 604323ca760beebf00a07153706dcbe7128324e0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:12:37 +1000 Subject: [XFS] remove spurious VN_HOLD/VN_RELE calls from xfs_acl.c All the ACL routines are called from inode operations which are guaranteed to have a referenced inode by the VFS, so there's no need for the ACL code to grab another temporary one. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31763a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_acl.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index fdeca54..795c81e 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -217,7 +217,6 @@ xfs_acl_vget( posix_acl_xattr_header *ext_acl = acl; int flags = 0; - VN_HOLD(vp); if(size) { if (!(_ACL_ALLOC(xfs_acl))) { error = ENOMEM; @@ -243,7 +242,6 @@ xfs_acl_vget( error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size); } out: - VN_RELE(vp); if(xfs_acl) _ACL_FREE(xfs_acl); return -error; @@ -256,7 +254,6 @@ xfs_acl_vremove( { int error; - VN_HOLD(vp); error = xfs_acl_allow_set(vp, kind); if (!error) { error = xfs_attr_remove(XFS_I(vp), @@ -266,7 +263,6 @@ xfs_acl_vremove( if (error == ENOATTR) error = 0; /* 'scool */ } - VN_RELE(vp); return -error; } @@ -298,7 +294,6 @@ xfs_acl_vset( return 0; } - VN_HOLD(vp); error = xfs_acl_allow_set(vp, kind); /* Incoming ACL exists, set file mode based on its value */ @@ -321,7 +316,6 @@ xfs_acl_vset( } out: - VN_RELE(vp); _ACL_FREE(xfs_acl); return -error; } -- cgit v1.1 From 0b1f917730dc2276fadbd9813ac3666abd7b1cbd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:13:09 +1000 Subject: [XFS] remove remaining VN_HOLD calls Use IHOLD(ip) instead of VN_HOLD(VFS_I(ip)). SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31765a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/quota/xfs_dquot.c | 2 +- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_dfrag.c | 10 +++------- 3 files changed, 5 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 68adc5f..9de42d0 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -431,7 +431,7 @@ xfs_qm_dqalloc( * when it unlocks the inode. Since we want to keep the quota * inode around, we bump the vnode ref count now. */ - VN_HOLD(VFS_I(quotip)); + IHOLD(quotip); xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL); nmaps = 1; diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index bac82af..3d6a2ce 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -4000,7 +4000,7 @@ xfs_bmap_add_attrfork( ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; } ASSERT(ip->i_d.di_anextents == 0); - VN_HOLD(VFS_I(ip)); + IHOLD(ip); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); switch (ip->i_d.di_format) { diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 9e75101..d924078 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -350,15 +350,11 @@ xfs_swap_extents( break; } - /* - * Increment vnode ref counts since xfs_trans_commit & - * xfs_trans_cancel will both unlock the inodes and - * decrement the associated ref counts. - */ - VN_HOLD(vp); - VN_HOLD(tvp); + IHOLD(ip); xfs_trans_ijoin(tp, ip, lock_flags); + + IHOLD(tip); xfs_trans_ijoin(tp, tip, lock_flags); xfs_trans_log_inode(tp, ip, ilf_fields); -- cgit v1.1 From 907f49a8f552acc5d75635e86d567f05daf5c0d8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:13:45 +1000 Subject: [XFS] implement IHOLD/IRELE directly Now that all direct calls to VN_HOLD/VN_RELE are gone we can implement IHOLD/IRELE directly. For the IHOLD case also replace igrab with a direct increment of i_count because we are guaranteed to already have a live and referenced inode by the VFS. Also remove the vn_hold statistic because it's been rather meaningless for some time with most references done by other callers. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31764a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_vnode.c | 18 ------------------ fs/xfs/linux-2.6/xfs_vnode.h | 28 ++++++++++++---------------- fs/xfs/xfs_utils.h | 3 --- 3 files changed, 12 insertions(+), 37 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 4af972b..1c5a34f 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -82,24 +82,6 @@ vn_ioerror( xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l); } - -/* - * Add a reference to a referenced vnode. - */ -bhv_vnode_t * -vn_hold( - bhv_vnode_t *vp) -{ - struct inode *inode; - - XFS_STATS_INC(vn_hold); - - inode = igrab(vp); - ASSERT(inode); - - return vp; -} - #ifdef XFS_INODE_TRACE /* diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index cc53687..0d7eac0 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -69,22 +69,18 @@ static inline int vn_count(bhv_vnode_t *vp) return atomic_read(&vp->i_count); } -/* - * Vnode reference counting functions (and macros for compatibility). - */ -extern bhv_vnode_t *vn_hold(bhv_vnode_t *); - -#if defined(XFS_INODE_TRACE) -#define VN_HOLD(vp) \ - ((void)vn_hold(vp), \ - xfs_itrace_hold(XFS_I(vp), __FILE__, __LINE__, (inst_t *)__return_address)) -#define VN_RELE(vp) \ - (xfs_itrace_rele(XFS_I(vp), __FILE__, __LINE__, (inst_t *)__return_address), \ - iput(vp)) -#else -#define VN_HOLD(vp) ((void)vn_hold(vp)) -#define VN_RELE(vp) (iput(vp)) -#endif +#define IHOLD(ip) \ +do { \ + ASSERT(atomic_read(&VFS_I(ip)->i_count) > 0) ; \ + atomic_inc(&(VFS_I(ip)->i_count)); \ + xfs_itrace_hold((ip), __FILE__, __LINE__, (inst_t *)__return_address); \ +} while (0) + +#define IRELE(ip) \ +do { \ + xfs_itrace_rele((ip), __FILE__, __LINE__, (inst_t *)__return_address); \ + iput(VFS_I(ip)); \ +} while (0) static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp) { diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h index 7b533df..ef32122 100644 --- a/fs/xfs/xfs_utils.h +++ b/fs/xfs/xfs_utils.h @@ -18,9 +18,6 @@ #ifndef __XFS_UTILS_H__ #define __XFS_UTILS_H__ -#define IRELE(ip) VN_RELE(VFS_I(ip)) -#define IHOLD(ip) VN_HOLD(VFS_I(ip)) - extern int xfs_truncate_file(xfs_mount_t *, xfs_inode_t *); extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, xfs_dev_t, cred_t *, prid_t, int, -- cgit v1.1 From 1550d0b0b08bc34c0c37a86bd884b1a70782104e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:17:37 +1000 Subject: [XFS] kill INDUCE_IO_ERROR All the error injection is already enabled through ifdef DEBUG, so kill the never set second cpp symbol to activate it without the rest of the debugging infrastructure. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31771a Signed-off-by: Christoph Hellwig Signed-off-by: Niv Sardi Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_error.c | 5 +---- fs/xfs/xfs_error.h | 12 ++---------- fs/xfs/xfs_mount.c | 2 +- 3 files changed, 4 insertions(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index f66756c..f227ecd 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -58,9 +58,6 @@ xfs_error_trap(int e) } return e; } -#endif - -#if (defined(DEBUG) || defined(INDUCE_IO_ERROR)) int xfs_etest[XFS_NUM_INJECT_ERROR]; int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; @@ -154,7 +151,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud) return 0; } -#endif /* DEBUG || INDUCE_IO_ERROR */ +#endif /* DEBUG */ static void xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap) diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index d8559d1..11543f1 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -125,22 +125,14 @@ extern void xfs_corruption_error(char *tag, int level, struct xfs_mount *mp, #define XFS_RANDOM_DIOWRITE_IOERR (XFS_RANDOM_DEFAULT/10) #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT -#if (defined(DEBUG) || defined(INDUCE_IO_ERROR)) +#ifdef DEBUG extern int xfs_error_test(int, int *, char *, int, char *, unsigned long); #define XFS_NUM_INJECT_ERROR 10 - -#ifdef __ANSI_CPP__ -#define XFS_TEST_ERROR(expr, mp, tag, rf) \ - ((expr) || \ - xfs_error_test((tag), (mp)->m_fixedfsid, #expr, __LINE__, __FILE__, \ - (rf))) -#else #define XFS_TEST_ERROR(expr, mp, tag, rf) \ ((expr) || \ xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \ (rf))) -#endif /* __ANSI_CPP__ */ extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp); extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud); @@ -148,7 +140,7 @@ extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud); #define XFS_TEST_ERROR(expr, mp, tag, rf) (expr) #define xfs_errortag_add(tag, mp) (ENOSYS) #define xfs_errortag_clearall(mp, loud) (ENOSYS) -#endif /* (DEBUG || INDUCE_IO_ERROR) */ +#endif /* DEBUG */ /* * XFS panic tags -- allow a call to xfs_cmn_err() be turned into diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 31699b1..6b43507 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1315,7 +1315,7 @@ xfs_unmountfs(xfs_mount_t *mp) if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) uuid_table_remove(&mp->m_sb.sb_uuid); -#if defined(DEBUG) || defined(INDUCE_IO_ERROR) +#if defined(DEBUG) xfs_errortag_clearall(mp, 0); #endif xfs_mount_free(mp); -- cgit v1.1 From e1cccd917be7364f81b5dc4e33ee3a6e0db21a99 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:18:07 +1000 Subject: [XFS] kill xfs_lock_dir_and_entry When multiple inodes are locked in XFS it happens in order of the inode number, with the everything but the first inode trylocked if any of the previous inodes is in the AIL. Except for the sorting of the inodes this logic is implemented in xfs_lock_inodes, but also partially duplicated in xfs_lock_dir_and_entry in a particularly stupid way adds a lock roundtrip if the inode ordering is not optimal. This patch adds a new helper xfs_lock_two_inodes that takes two inodes and locks them in the most optimal way according to the above locking protocol and uses it for all places that want to lock two inodes. The only caller of xfs_lock_inodes is xfs_rename which might lock up to four inodes. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31772a Signed-off-by: Christoph Hellwig Signed-off-by: Donald Douwsma Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_dfrag.c | 14 +---- fs/xfs/xfs_inode.h | 1 + fs/xfs/xfs_vnodeops.c | 162 +++++++++++++------------------------------------- 3 files changed, 44 insertions(+), 133 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index d924078..5ce91a0 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -128,7 +128,6 @@ xfs_swap_extents( xfs_swapext_t *sxp) { xfs_mount_t *mp; - xfs_inode_t *ips[2]; xfs_trans_t *tp; xfs_bstat_t *sbp = &sxp->sx_stat; bhv_vnode_t *vp, *tvp; @@ -153,16 +152,7 @@ xfs_swap_extents( vp = VFS_I(ip); tvp = VFS_I(tip); - /* Lock in i_ino order */ - if (ip->i_ino < tip->i_ino) { - ips[0] = ip; - ips[1] = tip; - } else { - ips[0] = tip; - ips[1] = ip; - } - - xfs_lock_inodes(ips, 2, lock_flags); + xfs_lock_two_inodes(ip, tip, lock_flags); locked = 1; /* Verify that both files have the same format */ @@ -265,7 +255,7 @@ xfs_swap_extents( locked = 0; goto error0; } - xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL); + xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); /* * Count the number of extended attribute blocks diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 4088951..ec9f454 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -531,6 +531,7 @@ void xfs_iflush_all(struct xfs_mount *); void xfs_ichgtime(xfs_inode_t *, int); xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); void xfs_lock_inodes(xfs_inode_t **, int, uint); +void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); void xfs_synchronize_atime(xfs_inode_t *); void xfs_mark_inode_dirty_sync(xfs_inode_t *); diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index c5dc7ea..077c86b 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1708,111 +1708,6 @@ std_return: } #ifdef DEBUG -/* - * Some counters to see if (and how often) we are hitting some deadlock - * prevention code paths. - */ - -int xfs_rm_locks; -int xfs_rm_lock_delays; -int xfs_rm_attempts; -#endif - -/* - * The following routine will lock the inodes associated with the - * directory and the named entry in the directory. The locks are - * acquired in increasing inode number. - * - * If the entry is "..", then only the directory is locked. The - * vnode ref count will still include that from the .. entry in - * this case. - * - * There is a deadlock we need to worry about. If the locked directory is - * in the AIL, it might be blocking up the log. The next inode we lock - * could be already locked by another thread waiting for log space (e.g - * a permanent log reservation with a long running transaction (see - * xfs_itruncate_finish)). To solve this, we must check if the directory - * is in the ail and use lock_nowait. If we can't lock, we need to - * drop the inode lock on the directory and try again. xfs_iunlock will - * potentially push the tail if we were holding up the log. - */ -STATIC int -xfs_lock_dir_and_entry( - xfs_inode_t *dp, - xfs_inode_t *ip) /* inode of entry 'name' */ -{ - int attempts; - xfs_ino_t e_inum; - xfs_inode_t *ips[2]; - xfs_log_item_t *lp; - -#ifdef DEBUG - xfs_rm_locks++; -#endif - attempts = 0; - -again: - xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); - - e_inum = ip->i_ino; - - xfs_itrace_ref(ip); - - /* - * We want to lock in increasing inum. Since we've already - * acquired the lock on the directory, we may need to release - * if if the inum of the entry turns out to be less. - */ - if (e_inum > dp->i_ino) { - /* - * We are already in the right order, so just - * lock on the inode of the entry. - * We need to use nowait if dp is in the AIL. - */ - - lp = (xfs_log_item_t *)dp->i_itemp; - if (lp && (lp->li_flags & XFS_LI_IN_AIL)) { - if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { - attempts++; -#ifdef DEBUG - xfs_rm_attempts++; -#endif - - /* - * Unlock dp and try again. - * xfs_iunlock will try to push the tail - * if the inode is in the AIL. - */ - - xfs_iunlock(dp, XFS_ILOCK_EXCL); - - if ((attempts % 5) == 0) { - delay(1); /* Don't just spin the CPU */ -#ifdef DEBUG - xfs_rm_lock_delays++; -#endif - } - goto again; - } - } else { - xfs_ilock(ip, XFS_ILOCK_EXCL); - } - } else if (e_inum < dp->i_ino) { - xfs_iunlock(dp, XFS_ILOCK_EXCL); - - ips[0] = ip; - ips[1] = dp; - xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL); - } - /* else e_inum == dp->i_ino */ - /* This can happen if we're asked to lock /x/.. - * the entry is "..", which is also the parent directory. - */ - - return 0; -} - -#ifdef DEBUG int xfs_locked_n; int xfs_small_retries; int xfs_middle_retries; @@ -1946,6 +1841,45 @@ again: #endif } +void +xfs_lock_two_inodes( + xfs_inode_t *ip0, + xfs_inode_t *ip1, + uint lock_mode) +{ + xfs_inode_t *temp; + int attempts = 0; + xfs_log_item_t *lp; + + ASSERT(ip0->i_ino != ip1->i_ino); + + if (ip0->i_ino > ip1->i_ino) { + temp = ip0; + ip0 = ip1; + ip1 = temp; + } + + again: + xfs_ilock(ip0, xfs_lock_inumorder(lock_mode, 0)); + + /* + * If the first lock we have locked is in the AIL, we must TRY to get + * the second lock. If we can't get it, we must release the first one + * and try again. + */ + lp = (xfs_log_item_t *)ip0->i_itemp; + if (lp && (lp->li_flags & XFS_LI_IN_AIL)) { + if (!xfs_ilock_nowait(ip1, xfs_lock_inumorder(lock_mode, 1))) { + xfs_iunlock(ip0, lock_mode); + if ((++attempts % 5) == 0) + delay(1); /* Don't just spin the CPU */ + goto again; + } + } else { + xfs_ilock(ip1, xfs_lock_inumorder(lock_mode, 1)); + } +} + int xfs_remove( xfs_inode_t *dp, @@ -2018,9 +1952,7 @@ xfs_remove( goto out_trans_cancel; } - error = xfs_lock_dir_and_entry(dp, ip); - if (error) - goto out_trans_cancel; + xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL); /* * At this point, we've gotten both the directory and the entry @@ -2047,9 +1979,6 @@ xfs_remove( } } - /* - * Entry must exist since we did a lookup in xfs_lock_dir_and_entry. - */ XFS_BMAP_INIT(&free_list, &first_block); error = xfs_dir_removename(tp, dp, name, ip->i_ino, &first_block, &free_list, resblks); @@ -2155,7 +2084,6 @@ xfs_link( { xfs_mount_t *mp = tdp->i_mount; xfs_trans_t *tp; - xfs_inode_t *ips[2]; int error; xfs_bmap_free_t free_list; xfs_fsblock_t first_block; @@ -2203,15 +2131,7 @@ xfs_link( goto error_return; } - if (sip->i_ino < tdp->i_ino) { - ips[0] = sip; - ips[1] = tdp; - } else { - ips[0] = tdp; - ips[1] = sip; - } - - xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL); + xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL); /* * Increment vnode ref counts since xfs_trans_commit & -- cgit v1.1 From df80c933f9eb01a7af3812bbe437e38205386304 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:22:09 +1000 Subject: [XFS] remove some easy bhv_vnode_t instances In various places we can just move a VFS_I call into the argument list of called functions/macros instead of having a local bhv_vnode_t. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31776a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_super.c | 7 +------ fs/xfs/xfs_dfrag.c | 9 +++------ fs/xfs/xfs_inode.c | 10 +++------- fs/xfs/xfs_itable.c | 4 +--- fs/xfs/xfs_vfsops.c | 3 +-- fs/xfs/xfs_vnodeops.c | 21 ++++++++------------- 6 files changed, 17 insertions(+), 37 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 71ac3a6..1ca593fb 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -980,12 +980,7 @@ STATIC struct inode * xfs_fs_alloc_inode( struct super_block *sb) { - bhv_vnode_t *vp; - - vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); - if (unlikely(!vp)) - return NULL; - return vp; + return kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); } STATIC void diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 5ce91a0..760f4c5 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -130,7 +130,6 @@ xfs_swap_extents( xfs_mount_t *mp; xfs_trans_t *tp; xfs_bstat_t *sbp = &sxp->sx_stat; - bhv_vnode_t *vp, *tvp; xfs_ifork_t *tempifp, *ifp, *tifp; int ilf_fields, tilf_fields; static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; @@ -149,8 +148,6 @@ xfs_swap_extents( } sbp = &sxp->sx_stat; - vp = VFS_I(ip); - tvp = VFS_I(tip); xfs_lock_two_inodes(ip, tip, lock_flags); locked = 1; @@ -174,7 +171,7 @@ xfs_swap_extents( goto error0; } - if (VN_CACHED(tvp) != 0) { + if (VN_CACHED(VFS_I(tip)) != 0) { xfs_inval_cached_trace(tip, 0, -1, 0, -1); error = xfs_flushinval_pages(tip, 0, -1, FI_REMAPF_LOCKED); @@ -183,7 +180,7 @@ xfs_swap_extents( } /* Verify O_DIRECT for ftmp */ - if (VN_CACHED(tvp) != 0) { + if (VN_CACHED(VFS_I(tip)) != 0) { error = XFS_ERROR(EINVAL); goto error0; } @@ -227,7 +224,7 @@ xfs_swap_extents( * vop_read (or write in the case of autogrow) they block on the iolock * until we have switched the extents. */ - if (VN_MAPPED(vp)) { + if (VN_MAPPED(VFS_I(ip))) { error = XFS_ERROR(EBUSY); goto error0; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 8da67d5..efac885 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1399,7 +1399,6 @@ xfs_itruncate_start( xfs_fsize_t last_byte; xfs_off_t toss_start; xfs_mount_t *mp; - bhv_vnode_t *vp; int error = 0; ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); @@ -1408,7 +1407,6 @@ xfs_itruncate_start( (flags == XFS_ITRUNC_MAYBE)); mp = ip->i_mount; - vp = VFS_I(ip); /* wait for the completion of any pending DIOs */ if (new_size < ip->i_size) @@ -1457,7 +1455,7 @@ xfs_itruncate_start( #ifdef DEBUG if (new_size == 0) { - ASSERT(VN_CACHED(vp) == 0); + ASSERT(VN_CACHED(VFS_I(ip)) == 0); } #endif return error; @@ -3465,7 +3463,6 @@ xfs_iflush_all( xfs_mount_t *mp) { xfs_inode_t *ip; - bhv_vnode_t *vp; again: XFS_MOUNT_ILOCK(mp); @@ -3480,14 +3477,13 @@ xfs_iflush_all( continue; } - vp = VFS_I(ip); - if (!vp) { + if (!VFS_I(ip)) { XFS_MOUNT_IUNLOCK(mp); xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC); goto again; } - ASSERT(vn_count(vp) == 0); + ASSERT(vn_count(VFS_I(ip)) == 0); ip = ip->i_mnext; } while (ip != mp->m_inodes); diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 4feda54..cf6754a 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -59,7 +59,6 @@ xfs_bulkstat_one_iget( { xfs_icdinode_t *dic; /* dinode core info pointer */ xfs_inode_t *ip; /* incore inode pointer */ - bhv_vnode_t *vp; int error; error = xfs_iget(mp, NULL, ino, @@ -72,7 +71,6 @@ xfs_bulkstat_one_iget( ASSERT(ip != NULL); ASSERT(ip->i_blkno != (xfs_daddr_t)0); - vp = VFS_I(ip); dic = &ip->i_d; /* xfs_iget returns the following without needing @@ -85,7 +83,7 @@ xfs_bulkstat_one_iget( buf->bs_uid = dic->di_uid; buf->bs_gid = dic->di_gid; buf->bs_size = dic->di_size; - vn_atime_to_bstime(vp, &buf->bs_atime); + vn_atime_to_bstime(VFS_I(ip), &buf->bs_atime); buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 38450f1f..974d3c0 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -128,7 +128,6 @@ xfs_unmount_flush( xfs_inode_t *rip = mp->m_rootip; xfs_inode_t *rbmip; xfs_inode_t *rsumip = NULL; - bhv_vnode_t *rvp = VFS_I(rip); int error; xfs_ilock(rip, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); @@ -167,7 +166,7 @@ xfs_unmount_flush( if (error == EFSCORRUPTED) goto fscorrupt_out2; - if (vn_count(rvp) != 1 && !relocation) { + if (vn_count(VFS_I(rip)) != 1 && !relocation) { xfs_iunlock(rip, XFS_ILOCK_EXCL); return XFS_ERROR(EBUSY); } diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 077c86b..21da312 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1160,7 +1160,6 @@ int xfs_release( xfs_inode_t *ip) { - bhv_vnode_t *vp = VFS_I(ip); xfs_mount_t *mp = ip->i_mount; int error; @@ -1195,13 +1194,13 @@ xfs_release( * be exposed to that problem. */ truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED); - if (truncated && VN_DIRTY(vp) && ip->i_delayed_blks > 0) + if (truncated && VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) xfs_flush_pages(ip, 0, -1, XFS_B_ASYNC, FI_NONE); } if (ip->i_d.di_nlink != 0) { if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && - ((ip->i_size > 0) || (VN_CACHED(vp) > 0 || + ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) && (ip->i_df.if_flags & XFS_IFEXTENTS)) && (!(ip->i_d.di_flags & @@ -1227,7 +1226,6 @@ int xfs_inactive( xfs_inode_t *ip) { - bhv_vnode_t *vp = VFS_I(ip); xfs_bmap_free_t free_list; xfs_fsblock_t first_block; int committed; @@ -1242,7 +1240,7 @@ xfs_inactive( * If the inode is already free, then there can be nothing * to clean up here. */ - if (ip->i_d.di_mode == 0 || VN_BAD(vp)) { + if (ip->i_d.di_mode == 0 || VN_BAD(VFS_I(ip))) { ASSERT(ip->i_df.if_real_bytes == 0); ASSERT(ip->i_df.if_broot_bytes == 0); return VN_INACTIVE_CACHE; @@ -1272,7 +1270,7 @@ xfs_inactive( if (ip->i_d.di_nlink != 0) { if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && - ((ip->i_size > 0) || (VN_CACHED(vp) > 0 || + ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) && (ip->i_df.if_flags & XFS_IFEXTENTS) && (!(ip->i_d.di_flags & @@ -2793,14 +2791,13 @@ int xfs_reclaim( xfs_inode_t *ip) { - bhv_vnode_t *vp = VFS_I(ip); xfs_itrace_entry(ip); - ASSERT(!VN_MAPPED(vp)); + ASSERT(!VN_MAPPED(VFS_I(ip))); /* bad inode, get out here ASAP */ - if (VN_BAD(vp)) { + if (VN_BAD(VFS_I(ip))) { xfs_ireclaim(ip); return 0; } @@ -2837,7 +2834,7 @@ xfs_reclaim( XFS_MOUNT_ILOCK(mp); spin_lock(&ip->i_flags_lock); __xfs_iflags_set(ip, XFS_IRECLAIMABLE); - vp->i_private = NULL; + VFS_I(ip)->i_private = NULL; ip->i_vnode = NULL; spin_unlock(&ip->i_flags_lock); list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); @@ -3241,7 +3238,6 @@ xfs_free_file_space( xfs_off_t len, int attr_flags) { - bhv_vnode_t *vp; int committed; int done; xfs_off_t end_dmi_offset; @@ -3261,7 +3257,6 @@ xfs_free_file_space( xfs_trans_t *tp; int need_iolock = 1; - vp = VFS_I(ip); mp = ip->i_mount; xfs_itrace_entry(ip); @@ -3298,7 +3293,7 @@ xfs_free_file_space( rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE); ioffset = offset & ~(rounding - 1); - if (VN_CACHED(vp) != 0) { + if (VN_CACHED(VFS_I(ip)) != 0) { xfs_inval_cached_trace(ip, ioffset, -1, ioffset, -1); error = xfs_flushinval_pages(ip, ioffset, -1, FI_REMAPF_LOCKED); if (error) -- cgit v1.1 From 5ec7f8c7d14a3ea6bf920b3350f5c5d3527cb837 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:22:40 +1000 Subject: [XFS] kill bhv_vnode_t All remaining bhv_vnode_t instance are in code that's more or less Linux specific. (Well, for xfs_acl.c that could be argued, but that code is on the removal list, too). So just do an s/bhv_vnode_t/struct inode/ over the whole tree. We can clean up variable naming and some useless helpers later. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31781a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_super.c | 2 +- fs/xfs/linux-2.6/xfs_super.h | 2 +- fs/xfs/linux-2.6/xfs_vnode.c | 2 +- fs/xfs/linux-2.6/xfs_vnode.h | 14 ++++++-------- fs/xfs/quota/xfs_qm_syscalls.c | 2 +- fs/xfs/xfs_acl.c | 30 +++++++++++++++--------------- fs/xfs/xfs_acl.h | 14 +++++++------- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_inode.h | 2 +- fs/xfs/xfs_vfsops.c | 2 +- fs/xfs/xfs_vnodeops.c | 2 +- 11 files changed, 36 insertions(+), 38 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 1ca593fb..7605b07 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -2038,7 +2038,7 @@ xfs_free_trace_bufs(void) STATIC int __init xfs_init_zones(void) { - xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode", + xfs_vnode_zone = kmem_zone_init_flags(sizeof(struct inode), "xfs_vnode", KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | KM_ZONE_SPREAD, xfs_fs_inode_init_once); diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index b7d13da..57145ff 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h @@ -101,7 +101,7 @@ struct block_device; extern __uint64_t xfs_max_file_offset(unsigned int); -extern void xfs_initialize_vnode(struct xfs_mount *mp, bhv_vnode_t *vp, +extern void xfs_initialize_vnode(struct xfs_mount *mp, struct inode *vp, struct xfs_inode *ip); extern void xfs_flush_inode(struct xfs_inode *); diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 1c5a34f..5cad327 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -90,7 +90,7 @@ vn_ioerror( */ static inline int xfs_icount(struct xfs_inode *ip) { - bhv_vnode_t *vp = VFS_I(ip); + struct inode *vp = VFS_I(ip); if (vp) return vn_count(vp); diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 0d7eac0..683ce16 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -22,8 +22,6 @@ struct file; struct xfs_iomap; struct attrlist_cursor_kern; -typedef struct inode bhv_vnode_t; - /* * Return values for xfs_inactive. A return value of * VN_INACTIVE_NOCACHE implies that the file system behavior @@ -64,7 +62,7 @@ extern void vn_iowait(struct xfs_inode *ip); extern void vn_iowake(struct xfs_inode *ip); extern void vn_ioerror(struct xfs_inode *ip, int error, char *f, int l); -static inline int vn_count(bhv_vnode_t *vp) +static inline int vn_count(struct inode *vp) { return atomic_read(&vp->i_count); } @@ -82,7 +80,7 @@ do { \ iput(VFS_I(ip)); \ } while (0) -static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp) +static inline struct inode *vn_grab(struct inode *vp) { return igrab(vp); } @@ -90,7 +88,7 @@ static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp) /* * Dealing with bad inodes */ -static inline int VN_BAD(bhv_vnode_t *vp) +static inline int VN_BAD(struct inode *vp) { return is_bad_inode(vp); } @@ -98,18 +96,18 @@ static inline int VN_BAD(bhv_vnode_t *vp) /* * Extracting atime values in various formats */ -static inline void vn_atime_to_bstime(bhv_vnode_t *vp, xfs_bstime_t *bs_atime) +static inline void vn_atime_to_bstime(struct inode *vp, xfs_bstime_t *bs_atime) { bs_atime->tv_sec = vp->i_atime.tv_sec; bs_atime->tv_nsec = vp->i_atime.tv_nsec; } -static inline void vn_atime_to_timespec(bhv_vnode_t *vp, struct timespec *ts) +static inline void vn_atime_to_timespec(struct inode *vp, struct timespec *ts) { *ts = vp->i_atime; } -static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt) +static inline void vn_atime_to_time_t(struct inode *vp, time_t *tt) { *tt = vp->i_atime.tv_sec; } diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 132a0ab..1a3b803 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -1034,7 +1034,7 @@ xfs_qm_dqrele_all_inodes( { xfs_inode_t *ip, *topino; uint ireclaims; - bhv_vnode_t *vp; + struct inode *vp; boolean_t vnode_refd; ASSERT(mp->m_quotainfo); diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 795c81e..b2f639a 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -37,15 +37,15 @@ #include #include -STATIC int xfs_acl_setmode(bhv_vnode_t *, xfs_acl_t *, int *); +STATIC int xfs_acl_setmode(struct inode *, xfs_acl_t *, int *); STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *); STATIC void xfs_acl_get_endian(xfs_acl_t *); STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *); STATIC int xfs_acl_invalid(xfs_acl_t *); STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *); -STATIC void xfs_acl_get_attr(bhv_vnode_t *, xfs_acl_t *, int, int, int *); -STATIC void xfs_acl_set_attr(bhv_vnode_t *, xfs_acl_t *, int, int *); -STATIC int xfs_acl_allow_set(bhv_vnode_t *, int); +STATIC void xfs_acl_get_attr(struct inode *, xfs_acl_t *, int, int, int *); +STATIC void xfs_acl_set_attr(struct inode *, xfs_acl_t *, int, int *); +STATIC int xfs_acl_allow_set(struct inode *, int); kmem_zone_t *xfs_acl_zone; @@ -55,7 +55,7 @@ kmem_zone_t *xfs_acl_zone; */ int xfs_acl_vhasacl_access( - bhv_vnode_t *vp) + struct inode *vp) { int error; @@ -68,7 +68,7 @@ xfs_acl_vhasacl_access( */ int xfs_acl_vhasacl_default( - bhv_vnode_t *vp) + struct inode *vp) { int error; @@ -207,7 +207,7 @@ posix_acl_xfs_to_xattr( int xfs_acl_vget( - bhv_vnode_t *vp, + struct inode *vp, void *acl, size_t size, int kind) @@ -249,7 +249,7 @@ out: int xfs_acl_vremove( - bhv_vnode_t *vp, + struct inode *vp, int kind) { int error; @@ -268,7 +268,7 @@ xfs_acl_vremove( int xfs_acl_vset( - bhv_vnode_t *vp, + struct inode *vp, void *acl, size_t size, int kind) @@ -357,7 +357,7 @@ xfs_acl_iaccess( STATIC int xfs_acl_allow_set( - bhv_vnode_t *vp, + struct inode *vp, int kind) { if (vp->i_flags & (S_IMMUTABLE|S_APPEND)) @@ -560,7 +560,7 @@ xfs_acl_get_endian( */ STATIC void xfs_acl_get_attr( - bhv_vnode_t *vp, + struct inode *vp, xfs_acl_t *aclp, int kind, int flags, @@ -584,7 +584,7 @@ xfs_acl_get_attr( */ STATIC void xfs_acl_set_attr( - bhv_vnode_t *vp, + struct inode *vp, xfs_acl_t *aclp, int kind, int *error) @@ -618,7 +618,7 @@ xfs_acl_set_attr( int xfs_acl_vtoacl( - bhv_vnode_t *vp, + struct inode *vp, xfs_acl_t *access_acl, xfs_acl_t *default_acl) { @@ -650,7 +650,7 @@ xfs_acl_vtoacl( */ int xfs_acl_inherit( - bhv_vnode_t *vp, + struct inode *vp, mode_t mode, xfs_acl_t *pdaclp) { @@ -709,7 +709,7 @@ out_error: */ STATIC int xfs_acl_setmode( - bhv_vnode_t *vp, + struct inode *vp, xfs_acl_t *acl, int *basicperms) { diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 323ee94..a4e293b 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h @@ -59,14 +59,14 @@ extern struct kmem_zone *xfs_acl_zone; (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name)) #define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone) -extern int xfs_acl_inherit(bhv_vnode_t *, mode_t mode, xfs_acl_t *); +extern int xfs_acl_inherit(struct inode *, mode_t mode, xfs_acl_t *); extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *); -extern int xfs_acl_vtoacl(bhv_vnode_t *, xfs_acl_t *, xfs_acl_t *); -extern int xfs_acl_vhasacl_access(bhv_vnode_t *); -extern int xfs_acl_vhasacl_default(bhv_vnode_t *); -extern int xfs_acl_vset(bhv_vnode_t *, void *, size_t, int); -extern int xfs_acl_vget(bhv_vnode_t *, void *, size_t, int); -extern int xfs_acl_vremove(bhv_vnode_t *, int); +extern int xfs_acl_vtoacl(struct inode *, xfs_acl_t *, xfs_acl_t *); +extern int xfs_acl_vhasacl_access(struct inode *); +extern int xfs_acl_vhasacl_default(struct inode *); +extern int xfs_acl_vset(struct inode *, void *, size_t, int); +extern int xfs_acl_vget(struct inode *, void *, size_t, int); +extern int xfs_acl_vremove(struct inode *, int); #define _ACL_PERM_INVALID(perm) ((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE)) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index efac885..19e7a7b 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1046,7 +1046,7 @@ xfs_ialloc( { xfs_ino_t ino; xfs_inode_t *ip; - bhv_vnode_t *vp; + struct inode *vp; uint flags; int error; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index ec9f454..5717244 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -204,7 +204,7 @@ typedef struct xfs_inode { struct xfs_inode *i_mprev; /* ptr to prev inode */ struct xfs_mount *i_mount; /* fs mount struct ptr */ struct list_head i_reclaim; /* reclaim list */ - bhv_vnode_t *i_vnode; /* vnode backpointer */ + struct inode *i_vnode; /* vnode backpointer */ struct xfs_dquot *i_udquot; /* user dquot */ struct xfs_dquot *i_gdquot; /* group dquot */ diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 974d3c0..439dd39 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -283,7 +283,7 @@ xfs_sync_inodes( int *bypassed) { xfs_inode_t *ip = NULL; - bhv_vnode_t *vp = NULL; + struct inode *vp = NULL; int error; int last_error; uint64_t fflag; diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 21da312..7b967c0 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -2850,7 +2850,7 @@ xfs_finish_reclaim( int sync_mode) { xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino); - bhv_vnode_t *vp = VFS_I(ip); + struct inode *vp = VFS_I(ip); if (vp && VN_BAD(vp)) goto reclaim; -- cgit v1.1 From 41be8bed1f3168f34386f3a15d63682cfd586b8e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:23:13 +1000 Subject: [XFS] sanitize xfs_initialize_vnode Sanitize setting up the Linux indode. Setting up the xfs_inode <-> inode link is opencoded in xfs_iget_core now because that's the only place it needs to be done, xfs_initialize_vnode is renamed to xfs_setup_inode and loses all superflous paramaters. The check for I_NEW is removed because it always is true and the di_mode check moves into xfs_iget_core because it's only needed there. xfs_set_inodeops and xfs_revalidate_inode are merged into xfs_setup_inode and the whole things is moved into xfs_iops.c where it belongs. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31782a Signed-off-by: Christoph Hellwig Signed-off-by: Niv Sardi Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_iops.c | 103 ++++++++++++++++++++++++++++++++++++++-- fs/xfs/linux-2.6/xfs_iops.h | 8 ++-- fs/xfs/linux-2.6/xfs_super.c | 110 ------------------------------------------- fs/xfs/linux-2.6/xfs_super.h | 3 -- fs/xfs/xfs_iget.c | 9 +++- fs/xfs/xfs_inode.c | 4 +- 6 files changed, 111 insertions(+), 126 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index cc0f21a..ace56bd 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -710,7 +710,7 @@ out_error: return error; } -const struct inode_operations xfs_inode_operations = { +static const struct inode_operations xfs_inode_operations = { .permission = xfs_vn_permission, .truncate = xfs_vn_truncate, .getattr = xfs_vn_getattr, @@ -722,7 +722,7 @@ const struct inode_operations xfs_inode_operations = { .fallocate = xfs_vn_fallocate, }; -const struct inode_operations xfs_dir_inode_operations = { +static const struct inode_operations xfs_dir_inode_operations = { .create = xfs_vn_create, .lookup = xfs_vn_lookup, .link = xfs_vn_link, @@ -747,7 +747,7 @@ const struct inode_operations xfs_dir_inode_operations = { .listxattr = xfs_vn_listxattr, }; -const struct inode_operations xfs_dir_ci_inode_operations = { +static const struct inode_operations xfs_dir_ci_inode_operations = { .create = xfs_vn_create, .lookup = xfs_vn_ci_lookup, .link = xfs_vn_link, @@ -772,7 +772,7 @@ const struct inode_operations xfs_dir_ci_inode_operations = { .listxattr = xfs_vn_listxattr, }; -const struct inode_operations xfs_symlink_inode_operations = { +static const struct inode_operations xfs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = xfs_vn_follow_link, .put_link = xfs_vn_put_link, @@ -784,3 +784,98 @@ const struct inode_operations xfs_symlink_inode_operations = { .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, }; + +STATIC void +xfs_diflags_to_iflags( + struct inode *inode, + struct xfs_inode *ip) +{ + if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE) + inode->i_flags |= S_IMMUTABLE; + else + inode->i_flags &= ~S_IMMUTABLE; + if (ip->i_d.di_flags & XFS_DIFLAG_APPEND) + inode->i_flags |= S_APPEND; + else + inode->i_flags &= ~S_APPEND; + if (ip->i_d.di_flags & XFS_DIFLAG_SYNC) + inode->i_flags |= S_SYNC; + else + inode->i_flags &= ~S_SYNC; + if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME) + inode->i_flags |= S_NOATIME; + else + inode->i_flags &= ~S_NOATIME; +} + +/* + * Initialize the Linux inode, set up the operation vectors and + * unlock the inode. + * + * When reading existing inodes from disk this is called directly + * from xfs_iget, when creating a new inode it is called from + * xfs_ialloc after setting up the inode. + */ +void +xfs_setup_inode( + struct xfs_inode *ip) +{ + struct inode *inode = ip->i_vnode; + + inode->i_mode = ip->i_d.di_mode; + inode->i_nlink = ip->i_d.di_nlink; + inode->i_uid = ip->i_d.di_uid; + inode->i_gid = ip->i_d.di_gid; + + switch (inode->i_mode & S_IFMT) { + case S_IFBLK: + case S_IFCHR: + inode->i_rdev = + MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff, + sysv_minor(ip->i_df.if_u2.if_rdev)); + break; + default: + inode->i_rdev = 0; + break; + } + + inode->i_generation = ip->i_d.di_gen; + i_size_write(inode, ip->i_d.di_size); + inode->i_atime.tv_sec = ip->i_d.di_atime.t_sec; + inode->i_atime.tv_nsec = ip->i_d.di_atime.t_nsec; + inode->i_mtime.tv_sec = ip->i_d.di_mtime.t_sec; + inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; + inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec; + inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec; + xfs_diflags_to_iflags(inode, ip); + xfs_iflags_clear(ip, XFS_IMODIFIED); + + switch (inode->i_mode & S_IFMT) { + case S_IFREG: + inode->i_op = &xfs_inode_operations; + inode->i_fop = &xfs_file_operations; + inode->i_mapping->a_ops = &xfs_address_space_operations; + break; + case S_IFDIR: + if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) + inode->i_op = &xfs_dir_ci_inode_operations; + else + inode->i_op = &xfs_dir_inode_operations; + inode->i_fop = &xfs_dir_file_operations; + break; + case S_IFLNK: + inode->i_op = &xfs_symlink_inode_operations; + if (!(ip->i_df.if_flags & XFS_IFINLINE)) + inode->i_mapping->a_ops = &xfs_address_space_operations; + break; + default: + inode->i_op = &xfs_inode_operations; + init_special_inode(inode, inode->i_mode, inode->i_rdev); + break; + } + + xfs_iflags_clear(ip, XFS_INEW); + barrier(); + + unlock_new_inode(inode); +} diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index fdda404..2204f46 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h @@ -18,10 +18,7 @@ #ifndef __XFS_IOPS_H__ #define __XFS_IOPS_H__ -extern const struct inode_operations xfs_inode_operations; -extern const struct inode_operations xfs_dir_inode_operations; -extern const struct inode_operations xfs_dir_ci_inode_operations; -extern const struct inode_operations xfs_symlink_inode_operations; +struct xfs_inode; extern const struct file_operations xfs_file_operations; extern const struct file_operations xfs_dir_file_operations; @@ -29,8 +26,9 @@ extern const struct file_operations xfs_invis_file_operations; extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size); -struct xfs_inode; extern void xfs_ichgtime(struct xfs_inode *, int); extern void xfs_ichgtime_fast(struct xfs_inode *, struct inode *, int); +extern void xfs_setup_inode(struct xfs_inode *); + #endif /* __XFS_IOPS_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 7605b07..0eaad84 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -581,116 +581,6 @@ xfs_max_file_offset( return (((__uint64_t)pagefactor) << bitshift) - 1; } -STATIC_INLINE void -xfs_set_inodeops( - struct inode *inode) -{ - switch (inode->i_mode & S_IFMT) { - case S_IFREG: - inode->i_op = &xfs_inode_operations; - inode->i_fop = &xfs_file_operations; - inode->i_mapping->a_ops = &xfs_address_space_operations; - break; - case S_IFDIR: - if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) - inode->i_op = &xfs_dir_ci_inode_operations; - else - inode->i_op = &xfs_dir_inode_operations; - inode->i_fop = &xfs_dir_file_operations; - break; - case S_IFLNK: - inode->i_op = &xfs_symlink_inode_operations; - if (!(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE)) - inode->i_mapping->a_ops = &xfs_address_space_operations; - break; - default: - inode->i_op = &xfs_inode_operations; - init_special_inode(inode, inode->i_mode, inode->i_rdev); - break; - } -} - -STATIC_INLINE void -xfs_revalidate_inode( - xfs_mount_t *mp, - struct inode *inode, - xfs_inode_t *ip) -{ - - inode->i_mode = ip->i_d.di_mode; - inode->i_nlink = ip->i_d.di_nlink; - inode->i_uid = ip->i_d.di_uid; - inode->i_gid = ip->i_d.di_gid; - - switch (inode->i_mode & S_IFMT) { - case S_IFBLK: - case S_IFCHR: - inode->i_rdev = - MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff, - sysv_minor(ip->i_df.if_u2.if_rdev)); - break; - default: - inode->i_rdev = 0; - break; - } - - inode->i_generation = ip->i_d.di_gen; - i_size_write(inode, ip->i_d.di_size); - inode->i_atime.tv_sec = ip->i_d.di_atime.t_sec; - inode->i_atime.tv_nsec = ip->i_d.di_atime.t_nsec; - inode->i_mtime.tv_sec = ip->i_d.di_mtime.t_sec; - inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; - inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec; - inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec; - if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE) - inode->i_flags |= S_IMMUTABLE; - else - inode->i_flags &= ~S_IMMUTABLE; - if (ip->i_d.di_flags & XFS_DIFLAG_APPEND) - inode->i_flags |= S_APPEND; - else - inode->i_flags &= ~S_APPEND; - if (ip->i_d.di_flags & XFS_DIFLAG_SYNC) - inode->i_flags |= S_SYNC; - else - inode->i_flags &= ~S_SYNC; - if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME) - inode->i_flags |= S_NOATIME; - else - inode->i_flags &= ~S_NOATIME; - xfs_iflags_clear(ip, XFS_IMODIFIED); -} - -void -xfs_initialize_vnode( - struct xfs_mount *mp, - struct inode *inode, - struct xfs_inode *ip) -{ - - if (!ip->i_vnode) { - ip->i_vnode = inode; - inode->i_private = ip; - } - - /* - * We need to set the ops vectors, and unlock the inode, but if - * we have been called during the new inode create process, it is - * too early to fill in the Linux inode. We will get called a - * second time once the inode is properly set up, and then we can - * finish our work. - */ - if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) { - xfs_revalidate_inode(mp, inode, ip); - xfs_set_inodeops(inode); - - xfs_iflags_clear(ip, XFS_INEW); - barrier(); - - unlock_new_inode(inode); - } -} - int xfs_blkdev_get( xfs_mount_t *mp, diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index 57145ff..fe2ef4e 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h @@ -101,9 +101,6 @@ struct block_device; extern __uint64_t xfs_max_file_offset(unsigned int); -extern void xfs_initialize_vnode(struct xfs_mount *mp, struct inode *vp, - struct xfs_inode *ip); - extern void xfs_flush_inode(struct xfs_inode *); extern void xfs_flush_device(struct xfs_inode *); diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index d443426..539c2dd 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -288,10 +288,17 @@ finish_inode: *ipp = ip; /* + * Set up the Linux with the Linux inode. + */ + ip->i_vnode = inode; + inode->i_private = ip; + + /* * If we have a real type for an on-disk inode, we can set ops(&unlock) * now. If it's a new inode being created, xfs_ialloc will handle it. */ - xfs_initialize_vnode(mp, inode, ip); + if (ip->i_d.di_mode != 0) + xfs_setup_inode(ip); return 0; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 19e7a7b..5bb638b 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1046,7 +1046,6 @@ xfs_ialloc( { xfs_ino_t ino; xfs_inode_t *ip; - struct inode *vp; uint flags; int error; @@ -1077,7 +1076,6 @@ xfs_ialloc( } ASSERT(ip != NULL); - vp = VFS_I(ip); ip->i_d.di_mode = (__uint16_t)mode; ip->i_d.di_onlink = 0; ip->i_d.di_nlink = nlink; @@ -1220,7 +1218,7 @@ xfs_ialloc( xfs_trans_log_inode(tp, ip, flags); /* now that we have an i_mode we can setup inode ops and unlock */ - xfs_initialize_vnode(tp->t_mountp, vp, ip); + xfs_setup_inode(ip); *ipp = ip; return 0; -- cgit v1.1 From cdcf43335cbb2380e533441e007e0c4ec42634d5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:23:50 +1000 Subject: [XFS] small cleanups in xfs_btree.c Remove unneeded xfs_btree_get_block forward declaration. Move xfs_btree_firstrec next to xfs_btree_lastrec. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31787a Signed-off-by: Christoph Hellwig Signed-off-by: Tim Shimmin Signed-off-by: David Chinner Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_btree.c | 87 +++++++++++++++++++----------------------------------- 1 file changed, 30 insertions(+), 57 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index aeb87ca..2b0d454 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c @@ -46,38 +46,11 @@ kmem_zone_t *xfs_btree_cur_zone; /* * Btree magic numbers. */ -const __uint32_t xfs_magics[XFS_BTNUM_MAX] = -{ +const __uint32_t xfs_magics[XFS_BTNUM_MAX] = { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC }; /* - * Prototypes for internal routines. - */ - -/* - * Checking routine: return maxrecs for the block. - */ -STATIC int /* number of records fitting in block */ -xfs_btree_maxrecs( - xfs_btree_cur_t *cur, /* btree cursor */ - xfs_btree_block_t *block);/* generic btree block pointer */ - -/* - * Internal routines. - */ - -/* - * Retrieve the block pointer from the cursor at the given level. - * This may be a bmap btree root or from a buffer. - */ -STATIC xfs_btree_block_t * /* generic btree block pointer */ -xfs_btree_get_block( - xfs_btree_cur_t *cur, /* btree cursor */ - int level, /* level in btree */ - struct xfs_buf **bpp); /* buffer containing the block */ - -/* * Checking routine: return maxrecs for the block. */ STATIC int /* number of records fitting in block */ @@ -457,35 +430,6 @@ xfs_btree_dup_cursor( } /* - * Change the cursor to point to the first record at the given level. - * Other levels are unaffected. - */ -int /* success=1, failure=0 */ -xfs_btree_firstrec( - xfs_btree_cur_t *cur, /* btree cursor */ - int level) /* level to change */ -{ - xfs_btree_block_t *block; /* generic btree block pointer */ - xfs_buf_t *bp; /* buffer containing block */ - - /* - * Get the block pointer for this level. - */ - block = xfs_btree_get_block(cur, level, &bp); - xfs_btree_check_block(cur, block, level, bp); - /* - * It's empty, there is no such record. - */ - if (!block->bb_h.bb_numrecs) - return 0; - /* - * Set the ptr value to 1, that's the first record/key. - */ - cur->bc_ptrs[level] = 1; - return 1; -} - -/* * Retrieve the block pointer from the cursor at the given level. * This may be a bmap btree root or from a buffer. */ @@ -671,6 +615,35 @@ xfs_btree_islastblock( } /* + * Change the cursor to point to the first record at the given level. + * Other levels are unaffected. + */ +int /* success=1, failure=0 */ +xfs_btree_firstrec( + xfs_btree_cur_t *cur, /* btree cursor */ + int level) /* level to change */ +{ + xfs_btree_block_t *block; /* generic btree block pointer */ + xfs_buf_t *bp; /* buffer containing block */ + + /* + * Get the block pointer for this level. + */ + block = xfs_btree_get_block(cur, level, &bp); + xfs_btree_check_block(cur, block, level, bp); + /* + * It's empty, there is no such record. + */ + if (!block->bb_h.bb_numrecs) + return 0; + /* + * Set the ptr value to 1, that's the first record/key. + */ + cur->bc_ptrs[level] = 1; + return 1; +} + +/* * Change the cursor to point to the last record in the current block * at the given level. Other levels are unaffected. */ -- cgit v1.1 From 169d6227a71da125913c69c381643a8ae89da62d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:25:27 +1000 Subject: [XFS] Use the same btree_cur union member for alloc and inobt trees. The alloc and inobt btree use the same agbp/agno pair in the btree_cur union. Make them use the same bc_private.a union member so that code for these two short form btree implementations can be shared. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31788a Signed-off-by: Christoph Hellwig Signed-off-by: Tim Shimmin Signed-off-by: David Chinner Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_btree.c | 18 +++++++++--------- fs/xfs/xfs_btree.h | 8 ++------ fs/xfs/xfs_ialloc_btree.c | 30 +++++++++++++++--------------- 3 files changed, 26 insertions(+), 30 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 2b0d454..cc593a8 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c @@ -570,6 +570,13 @@ xfs_btree_init_cursor( cur->bc_private.a.agbp = agbp; cur->bc_private.a.agno = agno; break; + case XFS_BTNUM_INO: + /* + * Inode allocation btree fields. + */ + cur->bc_private.a.agbp = agbp; + cur->bc_private.a.agno = agno; + break; case XFS_BTNUM_BMAP: /* * Bmap btree fields. @@ -582,13 +589,6 @@ xfs_btree_init_cursor( cur->bc_private.b.flags = 0; cur->bc_private.b.whichfork = whichfork; break; - case XFS_BTNUM_INO: - /* - * Inode allocation btree fields. - */ - cur->bc_private.i.agbp = agbp; - cur->bc_private.i.agno = agno; - break; default: ASSERT(0); } @@ -863,12 +863,12 @@ xfs_btree_readahead_core( case XFS_BTNUM_INO: i = XFS_BUF_TO_INOBT_BLOCK(cur->bc_bufs[lev]); if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(i->bb_leftsib) != NULLAGBLOCK) { - xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno, + xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, be32_to_cpu(i->bb_leftsib), 1); rval++; } if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(i->bb_rightsib) != NULLAGBLOCK) { - xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno, + xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, be32_to_cpu(i->bb_rightsib), 1); rval++; } diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h index 7440b78..1f528a2 100644 --- a/fs/xfs/xfs_btree.h +++ b/fs/xfs/xfs_btree.h @@ -158,8 +158,8 @@ typedef struct xfs_btree_cur __uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */ xfs_btnum_t bc_btnum; /* identifies which btree type */ union { - struct { /* needed for BNO, CNT */ - struct xfs_buf *agbp; /* agf buffer pointer */ + struct { /* needed for BNO, CNT, INO */ + struct xfs_buf *agbp; /* agf/agi buffer pointer */ xfs_agnumber_t agno; /* ag number */ } a; struct { /* needed for BMAP */ @@ -172,10 +172,6 @@ typedef struct xfs_btree_cur char flags; /* flags */ #define XFS_BTCUR_BPRV_WASDEL 1 /* was delayed */ } b; - struct { /* needed for INO */ - struct xfs_buf *agbp; /* agi buffer pointer */ - xfs_agnumber_t agno; /* ag number */ - } i; } bc_private; /* per-btree type data */ } xfs_btree_cur_t; diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c index e5310c90..83502f3 100644 --- a/fs/xfs/xfs_ialloc_btree.c +++ b/fs/xfs/xfs_ialloc_btree.c @@ -181,7 +181,7 @@ xfs_inobt_delrec( * then we can get rid of this level. */ if (numrecs == 1 && level > 0) { - agbp = cur->bc_private.i.agbp; + agbp = cur->bc_private.a.agbp; agi = XFS_BUF_TO_AGI(agbp); /* * pp is still set to the first pointer in the block. @@ -194,7 +194,7 @@ xfs_inobt_delrec( * Free the block. */ if ((error = xfs_free_extent(cur->bc_tp, - XFS_AGB_TO_FSB(mp, cur->bc_private.i.agno, bno), 1))) + XFS_AGB_TO_FSB(mp, cur->bc_private.a.agno, bno), 1))) return error; xfs_trans_binval(cur->bc_tp, bp); xfs_ialloc_log_agi(cur->bc_tp, agbp, @@ -379,7 +379,7 @@ xfs_inobt_delrec( rrecs = be16_to_cpu(right->bb_numrecs); rbp = bp; if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, - cur->bc_private.i.agno, lbno, 0, &lbp, + cur->bc_private.a.agno, lbno, 0, &lbp, XFS_INO_BTREE_REF))) return error; left = XFS_BUF_TO_INOBT_BLOCK(lbp); @@ -401,7 +401,7 @@ xfs_inobt_delrec( lrecs = be16_to_cpu(left->bb_numrecs); lbp = bp; if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, - cur->bc_private.i.agno, rbno, 0, &rbp, + cur->bc_private.a.agno, rbno, 0, &rbp, XFS_INO_BTREE_REF))) return error; right = XFS_BUF_TO_INOBT_BLOCK(rbp); @@ -484,7 +484,7 @@ xfs_inobt_delrec( xfs_buf_t *rrbp; if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, - cur->bc_private.i.agno, be32_to_cpu(left->bb_rightsib), 0, + cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), 0, &rrbp, XFS_INO_BTREE_REF))) return error; rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp); @@ -497,7 +497,7 @@ xfs_inobt_delrec( * Free the deleting block. */ if ((error = xfs_free_extent(cur->bc_tp, XFS_AGB_TO_FSB(mp, - cur->bc_private.i.agno, rbno), 1))) + cur->bc_private.a.agno, rbno), 1))) return error; xfs_trans_binval(cur->bc_tp, rbp); /* @@ -854,7 +854,7 @@ xfs_inobt_lookup( { xfs_agi_t *agi; /* a.g. inode header */ - agi = XFS_BUF_TO_AGI(cur->bc_private.i.agbp); + agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); agno = be32_to_cpu(agi->agi_seqno); agbno = be32_to_cpu(agi->agi_root); } @@ -1089,7 +1089,7 @@ xfs_inobt_lshift( * Set up the left neighbor as "left". */ if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, - cur->bc_private.i.agno, be32_to_cpu(right->bb_leftsib), + cur->bc_private.a.agno, be32_to_cpu(right->bb_leftsib), 0, &lbp, XFS_INO_BTREE_REF))) return error; left = XFS_BUF_TO_INOBT_BLOCK(lbp); @@ -1207,10 +1207,10 @@ xfs_inobt_newroot( /* * Get a block & a buffer. */ - agi = XFS_BUF_TO_AGI(cur->bc_private.i.agbp); + agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); args.tp = cur->bc_tp; args.mp = cur->bc_mp; - args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.i.agno, + args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, be32_to_cpu(agi->agi_root)); args.mod = args.minleft = args.alignment = args.total = args.wasdel = args.isfl = args.userdata = args.minalignslop = 0; @@ -1233,7 +1233,7 @@ xfs_inobt_newroot( */ agi->agi_root = cpu_to_be32(args.agbno); be32_add_cpu(&agi->agi_level, 1); - xfs_ialloc_log_agi(args.tp, cur->bc_private.i.agbp, + xfs_ialloc_log_agi(args.tp, cur->bc_private.a.agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL); /* * At the previous root level there are now two blocks: the old @@ -1376,7 +1376,7 @@ xfs_inobt_rshift( * Set up the right neighbor as "right". */ if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, - cur->bc_private.i.agno, be32_to_cpu(left->bb_rightsib), + cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), 0, &rbp, XFS_INO_BTREE_REF))) return error; right = XFS_BUF_TO_INOBT_BLOCK(rbp); @@ -1492,7 +1492,7 @@ xfs_inobt_split( * Allocate the new block. * If we can't do it, we're toast. Give up. */ - args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.i.agno, lbno); + args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, lbno); args.mod = args.minleft = args.alignment = args.total = args.wasdel = args.isfl = args.userdata = args.minalignslop = 0; args.minlen = args.maxlen = args.prod = 1; @@ -1725,7 +1725,7 @@ xfs_inobt_decrement( agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, cur->bc_ptrs[lev], cur)); if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, - cur->bc_private.i.agno, agbno, 0, &bp, + cur->bc_private.a.agno, agbno, 0, &bp, XFS_INO_BTREE_REF))) return error; lev--; @@ -1897,7 +1897,7 @@ xfs_inobt_increment( agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, cur->bc_ptrs[lev], cur)); if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, - cur->bc_private.i.agno, agbno, 0, &bp, + cur->bc_private.a.agno, agbno, 0, &bp, XFS_INO_BTREE_REF))) return error; lev--; -- cgit v1.1 From d63f154a36c4ec7c2826874371887cecae375ebb Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 13 Aug 2008 16:28:40 +1000 Subject: [XFS] Fix compile failure in xfs_buf_trace() SGI-PV: 957103 SGI-Modid: xfs-linux-melb:xfs-kern:31804a Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_buf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 9f45c74..a01daa7 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -58,7 +58,7 @@ xfs_buf_trace( bp, id, (void *)(unsigned long)bp->b_flags, (void *)(unsigned long)bp->b_hold.counter, - (void *)(unsigned long)bp->b_sema.count.counter, + (void *)(unsigned long)bp->b_sema.count, (void *)current, data, ra, (void *)(unsigned long)((bp->b_file_offset>>32) & 0xffffffff), -- cgit v1.1 From 597bca6378e0273a5d16346c941cab1ec2e0116d Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 13 Aug 2008 16:29:21 +1000 Subject: [XFS] use get_unaligned_* helpers SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31813a Signed-off-by: Harvey Harrison Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 5bb638b..b8444ee 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -580,8 +580,8 @@ xfs_iformat_extents( xfs_validate_extents(ifp, nex, XFS_EXTFMT_INODE(ip)); for (i = 0; i < nex; i++, dp++) { xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i); - ep->l0 = be64_to_cpu(get_unaligned(&dp->l0)); - ep->l1 = be64_to_cpu(get_unaligned(&dp->l1)); + ep->l0 = get_unaligned_be64(&dp->l0); + ep->l1 = get_unaligned_be64(&dp->l1); } XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork); if (whichfork != XFS_DATA_FORK || -- cgit v1.1 From 12017faf387437c01ff63bbe46b629550b15bd70 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 16:34:31 +1000 Subject: [XFS] clean up stale references to semaphores A lot of code has been converted away from semaphores, but there are still comments that reference semaphore behaviour. The log code is the worst offender. Update the comments to reflect what the code really does now. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31814a Signed-off-by: David Chinner Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_vnode.c | 2 +- fs/xfs/xfs_log.c | 67 +++++++++++++++++++++----------------------- fs/xfs/xfs_log_priv.h | 12 ++++---- 3 files changed, 39 insertions(+), 42 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 5cad327..b52528b 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -33,7 +33,7 @@ /* - * Dedicated vnode inactive/reclaim sync semaphores. + * Dedicated vnode inactive/reclaim sync wait queues. * Prime number of hash buckets since address is used as the key. */ #define NVSYNC 37 diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 91b00a5..0816c5d 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -357,11 +357,11 @@ xfs_log_done(xfs_mount_t *mp, * Asynchronous forces are implemented by setting the WANT_SYNC * bit in the appropriate in-core log and then returning. * - * Synchronous forces are implemented with a semaphore. All callers - * to force a given lsn to disk will wait on a semaphore attached to the + * Synchronous forces are implemented with a signal variable. All callers + * to force a given lsn to disk will wait on a the sv attached to the * specific in-core log. When given in-core log finally completes its * write to disk, that thread will wake up all threads waiting on the - * semaphore. + * sv. */ int _xfs_log_force( @@ -707,7 +707,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) if (!(iclog->ic_state == XLOG_STATE_ACTIVE || iclog->ic_state == XLOG_STATE_DIRTY)) { if (!XLOG_FORCED_SHUTDOWN(log)) { - sv_wait(&iclog->ic_forcesema, PMEM, + sv_wait(&iclog->ic_force_wait, PMEM, &log->l_icloglock, s); } else { spin_unlock(&log->l_icloglock); @@ -748,7 +748,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) || iclog->ic_state == XLOG_STATE_DIRTY || iclog->ic_state == XLOG_STATE_IOERROR) ) { - sv_wait(&iclog->ic_forcesema, PMEM, + sv_wait(&iclog->ic_force_wait, PMEM, &log->l_icloglock, s); } else { spin_unlock(&log->l_icloglock); @@ -838,7 +838,7 @@ xfs_log_move_tail(xfs_mount_t *mp, break; tail_lsn = 0; free_bytes -= tic->t_unit_res; - sv_signal(&tic->t_sema); + sv_signal(&tic->t_wait); tic = tic->t_next; } while (tic != log->l_write_headq); } @@ -859,7 +859,7 @@ xfs_log_move_tail(xfs_mount_t *mp, break; tail_lsn = 0; free_bytes -= need_bytes; - sv_signal(&tic->t_sema); + sv_signal(&tic->t_wait); tic = tic->t_next; } while (tic != log->l_reserve_headq); } @@ -1285,8 +1285,8 @@ xlog_alloc_log(xfs_mount_t *mp, ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp)); ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0); - sv_init(&iclog->ic_forcesema, SV_DEFAULT, "iclog-force"); - sv_init(&iclog->ic_writesema, SV_DEFAULT, "iclog-write"); + sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force"); + sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write"); iclogp = &iclog->ic_next; } @@ -1565,8 +1565,8 @@ xlog_dealloc_log(xlog_t *log) iclog = log->l_iclog; for (i=0; il_iclog_bufs; i++) { - sv_destroy(&iclog->ic_forcesema); - sv_destroy(&iclog->ic_writesema); + sv_destroy(&iclog->ic_force_wait); + sv_destroy(&iclog->ic_write_wait); xfs_buf_free(iclog->ic_bp); #ifdef XFS_LOG_TRACE if (iclog->ic_trace != NULL) { @@ -1976,7 +1976,7 @@ xlog_write(xfs_mount_t * mp, /* Clean iclogs starting from the head. This ordering must be * maintained, so an iclog doesn't become ACTIVE beyond one that * is SYNCING. This is also required to maintain the notion that we use - * a counting semaphore to hold off would be writers to the log when every + * a ordered wait queue to hold off would be writers to the log when every * iclog is trying to sync to disk. * * State Change: DIRTY -> ACTIVE @@ -2240,7 +2240,7 @@ xlog_state_do_callback( xlog_state_clean_log(log); /* wake up threads waiting in xfs_log_force() */ - sv_broadcast(&iclog->ic_forcesema); + sv_broadcast(&iclog->ic_force_wait); iclog = iclog->ic_next; } while (first_iclog != iclog); @@ -2302,8 +2302,7 @@ xlog_state_do_callback( * the second completion goes through. * * Callbacks could take time, so they are done outside the scope of the - * global state machine log lock. Assume that the calls to cvsema won't - * take a long time. At least we know it won't sleep. + * global state machine log lock. */ STATIC void xlog_state_done_syncing( @@ -2339,7 +2338,7 @@ xlog_state_done_syncing( * iclog buffer, we wake them all, one will get to do the * I/O, the others get to wait for the result. */ - sv_broadcast(&iclog->ic_writesema); + sv_broadcast(&iclog->ic_write_wait); spin_unlock(&log->l_icloglock); xlog_state_do_callback(log, aborted, iclog); /* also cleans log */ } /* xlog_state_done_syncing */ @@ -2347,11 +2346,9 @@ xlog_state_done_syncing( /* * If the head of the in-core log ring is not (ACTIVE or DIRTY), then we must - * sleep. The flush semaphore is set to the number of in-core buffers and - * decremented around disk syncing. Therefore, if all buffers are syncing, - * this semaphore will cause new writes to sleep until a sync completes. - * Otherwise, this code just does p() followed by v(). This approximates - * a sleep/wakeup except we can't race. + * sleep. We wait on the flush queue on the head iclog as that should be + * the first iclog to complete flushing. Hence if all iclogs are syncing, + * we will wait here and all new writes will sleep until a sync completes. * * The in-core logs are used in a circular fashion. They are not used * out-of-order even when an iclog past the head is free. @@ -2508,7 +2505,7 @@ xlog_grant_log_space(xlog_t *log, goto error_return; XFS_STATS_INC(xs_sleep_logspace); - sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s); + sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); /* * If we got an error, and the filesystem is shutting down, * we'll catch it down below. So just continue... @@ -2534,7 +2531,7 @@ redo: xlog_trace_loggrant(log, tic, "xlog_grant_log_space: sleep 2"); XFS_STATS_INC(xs_sleep_logspace); - sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s); + sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); if (XLOG_FORCED_SHUTDOWN(log)) { spin_lock(&log->l_grant_lock); @@ -2633,7 +2630,7 @@ xlog_regrant_write_log_space(xlog_t *log, if (free_bytes < ntic->t_unit_res) break; free_bytes -= ntic->t_unit_res; - sv_signal(&ntic->t_sema); + sv_signal(&ntic->t_wait); ntic = ntic->t_next; } while (ntic != log->l_write_headq); @@ -2644,7 +2641,7 @@ xlog_regrant_write_log_space(xlog_t *log, xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: sleep 1"); XFS_STATS_INC(xs_sleep_logspace); - sv_wait(&tic->t_sema, PINOD|PLTWAIT, + sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); /* If we're shutting down, this tic is already @@ -2673,7 +2670,7 @@ redo: if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) xlog_ins_ticketq(&log->l_write_headq, tic); XFS_STATS_INC(xs_sleep_logspace); - sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s); + sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); /* If we're shutting down, this tic is already off the queue */ if (XLOG_FORCED_SHUTDOWN(log)) { @@ -2916,7 +2913,7 @@ xlog_state_switch_iclogs(xlog_t *log, * 2. the current iclog is drity, and the previous iclog is in the * active or dirty state. * - * We may sleep (call psema) if: + * We may sleep if: * * 1. the current iclog is not in the active nor dirty state. * 2. the current iclog dirty, and the previous iclog is not in the @@ -3013,7 +3010,7 @@ maybe_sleep: return XFS_ERROR(EIO); } XFS_STATS_INC(xs_log_force_sleep); - sv_wait(&iclog->ic_forcesema, PINOD, &log->l_icloglock, s); + sv_wait(&iclog->ic_force_wait, PINOD, &log->l_icloglock, s); /* * No need to grab the log lock here since we're * only deciding whether or not to return EIO @@ -3096,7 +3093,7 @@ try_again: XLOG_STATE_SYNCING))) { ASSERT(!(iclog->ic_state & XLOG_STATE_IOERROR)); XFS_STATS_INC(xs_log_force_sleep); - sv_wait(&iclog->ic_prev->ic_writesema, PSWP, + sv_wait(&iclog->ic_prev->ic_write_wait, PSWP, &log->l_icloglock, s); *log_flushed = 1; already_slept = 1; @@ -3116,7 +3113,7 @@ try_again: !(iclog->ic_state & (XLOG_STATE_ACTIVE | XLOG_STATE_DIRTY))) { /* - * Don't wait on the forcesema if we know that we've + * Don't wait on completion if we know that we've * gotten a log write error. */ if (iclog->ic_state & XLOG_STATE_IOERROR) { @@ -3124,7 +3121,7 @@ try_again: return XFS_ERROR(EIO); } XFS_STATS_INC(xs_log_force_sleep); - sv_wait(&iclog->ic_forcesema, PSWP, &log->l_icloglock, s); + sv_wait(&iclog->ic_force_wait, PSWP, &log->l_icloglock, s); /* * No need to grab the log lock here since we're * only deciding whether or not to return EIO @@ -3180,7 +3177,7 @@ STATIC void xlog_ticket_put(xlog_t *log, xlog_ticket_t *ticket) { - sv_destroy(&ticket->t_sema); + sv_destroy(&ticket->t_wait); kmem_zone_free(xfs_log_ticket_zone, ticket); } /* xlog_ticket_put */ @@ -3270,7 +3267,7 @@ xlog_ticket_get(xlog_t *log, tic->t_trans_type = 0; if (xflags & XFS_LOG_PERM_RESERV) tic->t_flags |= XLOG_TIC_PERM_RESERV; - sv_init(&(tic->t_sema), SV_DEFAULT, "logtick"); + sv_init(&(tic->t_wait), SV_DEFAULT, "logtick"); xlog_tic_reset_res(tic); @@ -3557,14 +3554,14 @@ xfs_log_force_umount( */ if ((tic = log->l_reserve_headq)) { do { - sv_signal(&tic->t_sema); + sv_signal(&tic->t_wait); tic = tic->t_next; } while (tic != log->l_reserve_headq); } if ((tic = log->l_write_headq)) { do { - sv_signal(&tic->t_sema); + sv_signal(&tic->t_wait); tic = tic->t_next; } while (tic != log->l_write_headq); } diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 6245913..7dcf11e 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -241,7 +241,7 @@ typedef struct xlog_res { } xlog_res_t; typedef struct xlog_ticket { - sv_t t_sema; /* sleep on this semaphore : 20 */ + sv_t t_wait; /* ticket wait queue : 20 */ struct xlog_ticket *t_next; /* :4|8 */ struct xlog_ticket *t_prev; /* :4|8 */ xlog_tid_t t_tid; /* transaction identifier : 4 */ @@ -314,7 +314,7 @@ typedef struct xlog_rec_ext_header { * xlog_rec_header_t into the reserved space. * - ic_data follows, so a write to disk can start at the beginning of * the iclog. - * - ic_forcesema is used to implement synchronous forcing of the iclog to disk. + * - ic_forcewait is used to implement synchronous forcing of the iclog to disk. * - ic_next is the pointer to the next iclog in the ring. * - ic_bp is a pointer to the buffer used to write this incore log to disk. * - ic_log is a pointer back to the global log structure. @@ -339,8 +339,8 @@ typedef struct xlog_rec_ext_header { * and move everything else out to subsequent cachelines. */ typedef struct xlog_iclog_fields { - sv_t ic_forcesema; - sv_t ic_writesema; + sv_t ic_force_wait; + sv_t ic_write_wait; struct xlog_in_core *ic_next; struct xlog_in_core *ic_prev; struct xfs_buf *ic_bp; @@ -377,8 +377,8 @@ typedef struct xlog_in_core { /* * Defines to save our code from this glop. */ -#define ic_forcesema hic_fields.ic_forcesema -#define ic_writesema hic_fields.ic_writesema +#define ic_force_wait hic_fields.ic_force_wait +#define ic_write_wait hic_fields.ic_write_wait #define ic_next hic_fields.ic_next #define ic_prev hic_fields.ic_prev #define ic_bp hic_fields.ic_bp -- cgit v1.1 From b4dd330b9e0c9c78ebff754e72563b148f05e9e0 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 16:36:11 +1000 Subject: [XFS] replace the XFS buf iodone semaphore with a completion The xfs_buf_t b_iodonesema is really just a semaphore that wants to be a completion. Change it to a completion and remove the last user of the sema_t from XFS. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31815a Signed-off-by: David Chinner Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_buf.c | 6 +++--- fs/xfs/linux-2.6/xfs_buf.h | 4 ++-- fs/xfs/xfs_buf_item.c | 2 +- fs/xfs/xfs_rw.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index a01daa7..a0072d9 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -253,7 +253,7 @@ _xfs_buf_initialize( memset(bp, 0, sizeof(xfs_buf_t)); atomic_set(&bp->b_hold, 1); - init_MUTEX_LOCKED(&bp->b_iodonesema); + init_completion(&bp->b_iowait); INIT_LIST_HEAD(&bp->b_list); INIT_LIST_HEAD(&bp->b_hash_list); init_MUTEX_LOCKED(&bp->b_sema); /* held, no waiters */ @@ -1033,7 +1033,7 @@ xfs_buf_ioend( xfs_buf_iodone_work(&bp->b_iodone_work); } } else { - up(&bp->b_iodonesema); + complete(&bp->b_iowait); } } @@ -1271,7 +1271,7 @@ xfs_buf_iowait( XB_TRACE(bp, "iowait", 0); if (atomic_read(&bp->b_io_remaining)) blk_run_address_space(bp->b_target->bt_mapping); - down(&bp->b_iodonesema); + wait_for_completion(&bp->b_iowait); XB_TRACE(bp, "iowaited", (long)bp->b_error); return bp->b_error; } diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index 29d1d4a..fe01099 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h @@ -157,7 +157,7 @@ typedef struct xfs_buf { xfs_buf_iodone_t b_iodone; /* I/O completion function */ xfs_buf_relse_t b_relse; /* releasing function */ xfs_buf_bdstrat_t b_strat; /* pre-write function */ - struct semaphore b_iodonesema; /* Semaphore for I/O waiters */ + struct completion b_iowait; /* queue for I/O waiters */ void *b_fspriv; void *b_fspriv2; void *b_fspriv3; @@ -352,7 +352,7 @@ extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *); #define XFS_BUF_CPSEMA(bp) (xfs_buf_cond_lock(bp) == 0) #define XFS_BUF_VSEMA(bp) xfs_buf_unlock(bp) #define XFS_BUF_PSEMA(bp,x) xfs_buf_lock(bp) -#define XFS_BUF_V_IODONESEMA(bp) up(&bp->b_iodonesema); +#define XFS_BUF_FINISH_IOWAIT(bp) complete(&bp->b_iowait); #define XFS_BUF_SET_TARGET(bp, target) ((bp)->b_target = (target)) #define XFS_BUF_TARGET(bp) ((bp)->b_target) diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index d86ca2c..215c36d 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -1056,7 +1056,7 @@ xfs_buf_iodone_callbacks( anyway. */ XFS_BUF_SET_BRELSE_FUNC(bp,xfs_buf_error_relse); XFS_BUF_DONE(bp); - XFS_BUF_V_IODONESEMA(bp); + XFS_BUF_FINISH_IOWAIT(bp); } return; } diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index b0f31c0..3a82576 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -314,7 +314,7 @@ xfs_bioerror_relse( * ASYNC buffers. */ XFS_BUF_ERROR(bp, EIO); - XFS_BUF_V_IODONESEMA(bp); + XFS_BUF_FINISH_IOWAIT(bp); } else { xfs_buf_relse(bp); } -- cgit v1.1 From c63942d3eeffb98219e05d0976862ab9907d297d Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 16:41:16 +1000 Subject: [XFS] replace inode flush semaphore with a completion Use the new completion flush code to implement the inode flush lock. Removes one of the final users of semaphores in the XFS code base. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31817a Signed-off-by: David Chinner Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_iget.c | 32 ++++++++------------------------ fs/xfs/xfs_inode.c | 11 +++++------ fs/xfs/xfs_inode.h | 25 +++++++++++++++++++++---- fs/xfs/xfs_inode_item.c | 11 +++++------ 4 files changed, 39 insertions(+), 40 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 539c2dd..e229e9e 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -216,7 +216,14 @@ finish_inode: mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); init_waitqueue_head(&ip->i_ipin_wait); atomic_set(&ip->i_pincount, 0); - initnsema(&ip->i_flock, 1, "xfsfino"); + + /* + * Because we want to use a counting completion, complete + * the flush completion once to allow a single access to + * the flush completion without blocking. + */ + init_completion(&ip->i_flush); + complete(&ip->i_flush); if (lock_flags) xfs_ilock(ip, lock_flags); @@ -783,26 +790,3 @@ xfs_isilocked( } #endif -/* - * The following three routines simply manage the i_flock - * semaphore embedded in the inode. This semaphore synchronizes - * processes attempting to flush the in-core inode back to disk. - */ -void -xfs_iflock(xfs_inode_t *ip) -{ - psema(&(ip->i_flock), PINOD|PLTWAIT); -} - -int -xfs_iflock_nowait(xfs_inode_t *ip) -{ - return (cpsema(&(ip->i_flock))); -} - -void -xfs_ifunlock(xfs_inode_t *ip) -{ - ASSERT(issemalocked(&(ip->i_flock))); - vsema(&(ip->i_flock)); -} diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index b8444ee..aea6222 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2626,7 +2626,6 @@ xfs_idestroy( xfs_idestroy_fork(ip, XFS_ATTR_FORK); mrfree(&ip->i_lock); mrfree(&ip->i_iolock); - freesema(&ip->i_flock); #ifdef XFS_INODE_TRACE ktrace_free(ip->i_trace); @@ -3044,10 +3043,10 @@ cluster_corrupt_out: /* * xfs_iflush() will write a modified inode's changes out to the * inode's on disk home. The caller must have the inode lock held - * in at least shared mode and the inode flush semaphore must be - * held as well. The inode lock will still be held upon return from + * in at least shared mode and the inode flush completion must be + * active as well. The inode lock will still be held upon return from * the call and the caller is free to unlock it. - * The inode flush lock will be unlocked when the inode reaches the disk. + * The inode flush will be completed when the inode reaches the disk. * The flags indicate how the inode's buffer should be written out. */ int @@ -3066,7 +3065,7 @@ xfs_iflush( XFS_STATS_INC(xs_iflush_count); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); - ASSERT(issemalocked(&(ip->i_flock))); + ASSERT(!completion_done(&ip->i_flush)); ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || ip->i_d.di_nextents > ip->i_df.if_ext_max); @@ -3229,7 +3228,7 @@ xfs_iflush_int( #endif ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); - ASSERT(issemalocked(&(ip->i_flock))); + ASSERT(!completion_done(&ip->i_flush)); ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || ip->i_d.di_nextents > ip->i_df.if_ext_max); diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 5717244..f771df6 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -223,7 +223,7 @@ typedef struct xfs_inode { struct xfs_inode_log_item *i_itemp; /* logging information */ mrlock_t i_lock; /* inode lock */ mrlock_t i_iolock; /* inode IO lock */ - sema_t i_flock; /* inode flush lock */ + struct completion i_flush; /* inode flush completion q */ atomic_t i_pincount; /* inode pin count */ wait_queue_head_t i_ipin_wait; /* inode pinning wait queue */ spinlock_t i_flags_lock; /* inode i_flags lock */ @@ -482,11 +482,8 @@ int xfs_ilock_nowait(xfs_inode_t *, uint); void xfs_iunlock(xfs_inode_t *, uint); void xfs_ilock_demote(xfs_inode_t *, uint); int xfs_isilocked(xfs_inode_t *, uint); -void xfs_iflock(xfs_inode_t *); -int xfs_iflock_nowait(xfs_inode_t *); uint xfs_ilock_map_shared(xfs_inode_t *); void xfs_iunlock_map_shared(xfs_inode_t *, uint); -void xfs_ifunlock(xfs_inode_t *); void xfs_ireclaim(xfs_inode_t *); int xfs_finish_reclaim(xfs_inode_t *, int, int); int xfs_finish_reclaim_all(struct xfs_mount *, int); @@ -580,6 +577,26 @@ extern struct kmem_zone *xfs_ifork_zone; extern struct kmem_zone *xfs_inode_zone; extern struct kmem_zone *xfs_ili_zone; +/* + * Manage the i_flush queue embedded in the inode. This completion + * queue synchronizes processes attempting to flush the in-core + * inode back to disk. + */ +static inline void xfs_iflock(xfs_inode_t *ip) +{ + wait_for_completion(&ip->i_flush); +} + +static inline int xfs_iflock_nowait(xfs_inode_t *ip) +{ + return try_wait_for_completion(&ip->i_flush); +} + +static inline void xfs_ifunlock(xfs_inode_t *ip) +{ + complete(&ip->i_flush); +} + #endif /* __KERNEL__ */ #endif /* __XFS_INODE_H__ */ diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 0eee08a..97c7452 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -779,11 +779,10 @@ xfs_inode_item_pushbuf( ASSERT(iip->ili_push_owner == current_pid()); /* - * If flushlock isn't locked anymore, chances are that the - * inode flush completed and the inode was taken off the AIL. - * So, just get out. + * If a flush is not in progress anymore, chances are that the + * inode was taken off the AIL. So, just get out. */ - if (!issemalocked(&(ip->i_flock)) || + if (completion_done(&ip->i_flush) || ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) { iip->ili_pushbuf_flag = 0; xfs_iunlock(ip, XFS_ILOCK_SHARED); @@ -805,7 +804,7 @@ xfs_inode_item_pushbuf( * If not, we can flush it async. */ dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) && - issemalocked(&(ip->i_flock))); + !completion_done(&ip->i_flush)); iip->ili_pushbuf_flag = 0; xfs_iunlock(ip, XFS_ILOCK_SHARED); xfs_buftrace("INODE ITEM PUSH", bp); @@ -858,7 +857,7 @@ xfs_inode_item_push( ip = iip->ili_inode; ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED)); - ASSERT(issemalocked(&(ip->i_flock))); + ASSERT(!completion_done(&ip->i_flush)); /* * Since we were able to lock the inode's flush lock and * we found it on the AIL, the inode must be dirty. This -- cgit v1.1 From e1f49cf20cea18e3d1963939fe8612a75e319fbd Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 16:41:43 +1000 Subject: [XFS] replace dquot flush semaphore with a completion Use the new completion flush code to implement the dquot flush lock. Removes one of the final users of semaphores in the XFS code base. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31822a Signed-off-by: David Chinner Signed-off-by: Lachlan McIlroy --- fs/xfs/quota/xfs_dquot.c | 34 ++++++++++++---------------------- fs/xfs/quota/xfs_dquot.h | 29 ++++++++++++++++++----------- fs/xfs/quota/xfs_dquot_item.c | 8 ++++---- fs/xfs/quota/xfs_qm.c | 8 ++++---- 4 files changed, 38 insertions(+), 41 deletions(-) (limited to 'fs') diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 9de42d0..3229057 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -101,9 +101,16 @@ xfs_qm_dqinit( if (brandnewdquot) { dqp->dq_flnext = dqp->dq_flprev = dqp; mutex_init(&dqp->q_qlock); - initnsema(&dqp->q_flock, 1, "fdq"); sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq"); + /* + * Because we want to use a counting completion, complete + * the flush completion once to allow a single access to + * the flush completion without blocking. + */ + init_completion(&dqp->q_flush); + complete(&dqp->q_flush); + #ifdef XFS_DQUOT_TRACE dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_SLEEP); xfs_dqtrace_entry(dqp, "DQINIT"); @@ -150,7 +157,6 @@ xfs_qm_dqdestroy( ASSERT(! XFS_DQ_IS_ON_FREELIST(dqp)); mutex_destroy(&dqp->q_qlock); - freesema(&dqp->q_flock); sv_destroy(&dqp->q_pinwait); #ifdef XFS_DQUOT_TRACE @@ -1211,7 +1217,7 @@ xfs_qm_dqflush( int error; ASSERT(XFS_DQ_IS_LOCKED(dqp)); - ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp)); + ASSERT(!completion_done(&dqp->q_flush)); xfs_dqtrace_entry(dqp, "DQFLUSH"); /* @@ -1348,34 +1354,18 @@ xfs_qm_dqflush_done( xfs_dqfunlock(dqp); } - -int -xfs_qm_dqflock_nowait( - xfs_dquot_t *dqp) -{ - int locked; - - locked = cpsema(&((dqp)->q_flock)); - - /* XXX ifdef these out */ - if (locked) - (dqp)->dq_flags |= XFS_DQ_FLOCKED; - return (locked); -} - - int xfs_qm_dqlock_nowait( xfs_dquot_t *dqp) { - return (mutex_trylock(&((dqp)->q_qlock))); + return mutex_trylock(&dqp->q_qlock); } void xfs_dqlock( xfs_dquot_t *dqp) { - mutex_lock(&(dqp->q_qlock)); + mutex_lock(&dqp->q_qlock); } void @@ -1468,7 +1458,7 @@ xfs_qm_dqpurge( * if we're turning off quotas. Basically, we need this flush * lock, and are willing to block on it. */ - if (! xfs_qm_dqflock_nowait(dqp)) { + if (!xfs_dqflock_nowait(dqp)) { /* * Block on the flush lock after nudging dquot buffer, * if it is incore. diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h index f7393bb..8958d0f 100644 --- a/fs/xfs/quota/xfs_dquot.h +++ b/fs/xfs/quota/xfs_dquot.h @@ -82,7 +82,7 @@ typedef struct xfs_dquot { xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */ xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */ mutex_t q_qlock; /* quota lock */ - sema_t q_flock; /* flush lock */ + struct completion q_flush; /* flush completion queue */ uint q_pincount; /* pin count for this dquot */ sv_t q_pinwait; /* sync var for pinning */ #ifdef XFS_DQUOT_TRACE @@ -113,17 +113,25 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) /* - * The following three routines simply manage the q_flock - * semaphore embedded in the dquot. This semaphore synchronizes - * processes attempting to flush the in-core dquot back to disk. + * Manage the q_flush completion queue embedded in the dquot. This completion + * queue synchronizes processes attempting to flush the in-core dquot back to + * disk. */ -#define xfs_dqflock(dqp) { psema(&((dqp)->q_flock), PINOD | PRECALC);\ - (dqp)->dq_flags |= XFS_DQ_FLOCKED; } -#define xfs_dqfunlock(dqp) { ASSERT(issemalocked(&((dqp)->q_flock))); \ - vsema(&((dqp)->q_flock)); \ - (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); } +static inline void xfs_dqflock(xfs_dquot_t *dqp) +{ + wait_for_completion(&dqp->q_flush); +} + +static inline int xfs_dqflock_nowait(xfs_dquot_t *dqp) +{ + return try_wait_for_completion(&dqp->q_flush); +} + +static inline void xfs_dqfunlock(xfs_dquot_t *dqp) +{ + complete(&dqp->q_flush); +} -#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock))) #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) @@ -167,7 +175,6 @@ extern int xfs_qm_dqflush(xfs_dquot_t *, uint); extern int xfs_qm_dqpurge(xfs_dquot_t *); extern void xfs_qm_dqunpin_wait(xfs_dquot_t *); extern int xfs_qm_dqlock_nowait(xfs_dquot_t *); -extern int xfs_qm_dqflock_nowait(xfs_dquot_t *); extern void xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp); extern void xfs_qm_adjust_dqtimers(xfs_mount_t *, xfs_disk_dquot_t *); diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 08d2fc8..f028644 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c @@ -151,7 +151,7 @@ xfs_qm_dquot_logitem_push( dqp = logitem->qli_dquot; ASSERT(XFS_DQ_IS_LOCKED(dqp)); - ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp)); + ASSERT(!completion_done(&dqp->q_flush)); /* * Since we were able to lock the dquot's flush lock and @@ -245,7 +245,7 @@ xfs_qm_dquot_logitem_pushbuf( * inode flush completed and the inode was taken off the AIL. * So, just get out. */ - if (!issemalocked(&(dqp->q_flock)) || + if (completion_done(&dqp->q_flush) || ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) { qip->qli_pushbuf_flag = 0; xfs_dqunlock(dqp); @@ -258,7 +258,7 @@ xfs_qm_dquot_logitem_pushbuf( if (bp != NULL) { if (XFS_BUF_ISDELAYWRITE(bp)) { dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) && - issemalocked(&(dqp->q_flock))); + !completion_done(&dqp->q_flush)); qip->qli_pushbuf_flag = 0; xfs_dqunlock(dqp); @@ -317,7 +317,7 @@ xfs_qm_dquot_logitem_trylock( return (XFS_ITEM_LOCKED); retval = XFS_ITEM_SUCCESS; - if (! xfs_qm_dqflock_nowait(dqp)) { + if (!xfs_dqflock_nowait(dqp)) { /* * The dquot is already being flushed. It may have been * flushed delayed write, however, and we don't want to diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 021934a..3825d74 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -484,7 +484,7 @@ again: xfs_dqtrace_entry(dqp, "FLUSHALL: DQDIRTY"); /* XXX a sentinel would be better */ recl = XFS_QI_MPLRECLAIMS(mp); - if (! xfs_qm_dqflock_nowait(dqp)) { + if (!xfs_dqflock_nowait(dqp)) { /* * If we can't grab the flush lock then check * to see if the dquot has been flushed delayed @@ -1062,7 +1062,7 @@ xfs_qm_sync( /* XXX a sentinel would be better */ recl = XFS_QI_MPLRECLAIMS(mp); - if (! xfs_qm_dqflock_nowait(dqp)) { + if (!xfs_dqflock_nowait(dqp)) { if (nowait) { xfs_dqunlock(dqp); continue; @@ -2079,7 +2079,7 @@ xfs_qm_shake_freelist( * Try to grab the flush lock. If this dquot is in the process of * getting flushed to disk, we don't want to reclaim it. */ - if (! xfs_qm_dqflock_nowait(dqp)) { + if (!xfs_dqflock_nowait(dqp)) { xfs_dqunlock(dqp); dqp = dqp->dq_flnext; continue; @@ -2257,7 +2257,7 @@ xfs_qm_dqreclaim_one(void) * Try to grab the flush lock. If this dquot is in the process of * getting flushed to disk, we don't want to reclaim it. */ - if (! xfs_qm_dqflock_nowait(dqp)) { + if (!xfs_dqflock_nowait(dqp)) { xfs_dqunlock(dqp); continue; } -- cgit v1.1 From ab4a9b04a33c97dd17495f943447f5a15ecf2b51 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Wed, 13 Aug 2008 16:42:10 +1000 Subject: [XFS] remove the sema_t from XFS. Now that all users of the sema_t are gone from XFS we can finally kill it. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31823a Signed-off-by: David Chinner Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/sema.h | 52 -------------------------------------------- fs/xfs/linux-2.6/xfs_linux.h | 2 +- 2 files changed, 1 insertion(+), 53 deletions(-) delete mode 100644 fs/xfs/linux-2.6/sema.h (limited to 'fs') diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h deleted file mode 100644 index 3abe7e9..0000000 --- a/fs/xfs/linux-2.6/sema.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef __XFS_SUPPORT_SEMA_H__ -#define __XFS_SUPPORT_SEMA_H__ - -#include -#include -#include -#include - -/* - * sema_t structure just maps to struct semaphore in Linux kernel. - */ - -typedef struct semaphore sema_t; - -#define initnsema(sp, val, name) sema_init(sp, val) -#define psema(sp, b) down(sp) -#define vsema(sp) up(sp) -#define freesema(sema) do { } while (0) - -static inline int issemalocked(sema_t *sp) -{ - return down_trylock(sp) || (up(sp), 0); -} - -/* - * Map cpsema (try to get the sema) to down_trylock. We need to switch - * the return values since cpsema returns 1 (acquired) 0 (failed) and - * down_trylock returns the reverse 0 (acquired) 1 (failed). - */ -static inline int cpsema(sema_t *sp) -{ - return down_trylock(sp) ? 0 : 1; -} - -#endif /* __XFS_SUPPORT_SEMA_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 1b8dfdc..3b7c4ff 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -45,13 +45,13 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include -- cgit v1.1 From dff35fd41f252476cba7f761d7204dd9f47d739e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:44:15 +1000 Subject: [XFS] update timestamp in xfs_ialloc manually In xfs_ialloc we just want to set all timestamps to the current time. We don't need to mark the inode dirty like xfs_ichgtime does, and we don't need nor want the opimizations in xfs_ichgtime that I will introduce in the next patch. So just opencode the timestamp update in xfs_ialloc, and remove the new unused XFS_ICHGTIME_ACC case in xfs_ichgtime. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31825a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_iops.c | 17 ----------------- fs/xfs/xfs_inode.c | 9 ++++++++- fs/xfs/xfs_inode.h | 3 +-- fs/xfs/xfs_vnodeops.c | 1 - 4 files changed, 9 insertions(+), 21 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index ace56bd..d6947f8 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -89,12 +89,6 @@ xfs_mark_inode_dirty_sync( * Change the requested timestamp in the given inode. * We don't lock across timestamp updates, and we don't log them but * we do record the fact that there is dirty information in core. - * - * NOTE -- callers MUST combine XFS_ICHGTIME_MOD or XFS_ICHGTIME_CHG - * with XFS_ICHGTIME_ACC to be sure that access time - * update will take. Calling first with XFS_ICHGTIME_ACC - * and then XFS_ICHGTIME_MOD may fail to modify the access - * timestamp if the filesystem is mounted noacctm. */ void xfs_ichgtime( @@ -110,11 +104,6 @@ xfs_ichgtime( ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; } - if (flags & XFS_ICHGTIME_ACC) { - inode->i_atime = tv; - ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec; - ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec; - } if (flags & XFS_ICHGTIME_CHG) { inode->i_ctime = tv; ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec; @@ -149,12 +138,6 @@ xfs_ichgtime_fast( { timespec_t *tvp; - /* - * Atime updates for read() & friends are handled lazily now, and - * explicit updates must go through xfs_ichgtime() - */ - ASSERT((flags & XFS_ICHGTIME_ACC) == 0); - if (flags & XFS_ICHGTIME_MOD) { tvp = &inode->i_mtime; ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index aea6222..41371c5 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1048,6 +1048,7 @@ xfs_ialloc( xfs_inode_t *ip; uint flags; int error; + timespec_t tv; /* * Call the space management code to pick @@ -1128,7 +1129,13 @@ xfs_ialloc( ip->i_size = 0; ip->i_d.di_nextents = 0; ASSERT(ip->i_d.di_nblocks == 0); - xfs_ichgtime(ip, XFS_ICHGTIME_CHG|XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD); + + nanotime(&tv); + ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; + ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; + ip->i_d.di_atime = ip->i_d.di_mtime; + ip->i_d.di_ctime = ip->i_d.di_mtime; + /* * di_gen will have been taken care of in xfs_iread. */ diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index f771df6..1420c49 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -87,8 +87,7 @@ typedef struct xfs_ifork { * Flags for xfs_ichgtime(). */ #define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */ -#define XFS_ICHGTIME_ACC 0x2 /* data fork access timestamp */ -#define XFS_ICHGTIME_CHG 0x4 /* inode field change timestamp */ +#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */ /* * Per-fork incore inode flags. diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 7b967c0..588bb4a 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -513,7 +513,6 @@ xfs_setattr( ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec; ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec; ip->i_update_core = 1; - timeflags &= ~XFS_ICHGTIME_ACC; } if (mask & ATTR_MTIME) { inode->i_mtime = iattr->ia_mtime; -- cgit v1.1 From 8e5975c82f66bce36955f38e9abc259d5143a72a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:45:13 +1000 Subject: [XFS] optimize xfs_ichgtime Port a little optmization from file_update_time to xfs_ichgtime, and only update the timestamp and mark the inode dirty if the timestamp actually changes in the timer tick resultion supported by the running kernel. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31827a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_iops.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index d6947f8..0e7ca21 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -97,17 +97,23 @@ xfs_ichgtime( { struct inode *inode = VFS_I(ip); timespec_t tv; + int sync_it = 0; - nanotime(&tv); - if (flags & XFS_ICHGTIME_MOD) { + tv = current_fs_time(inode->i_sb); + + if ((flags & XFS_ICHGTIME_MOD) && + !timespec_equal(&inode->i_mtime, &tv)) { inode->i_mtime = tv; ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; + sync_it = 1; } - if (flags & XFS_ICHGTIME_CHG) { + if ((flags & XFS_ICHGTIME_CHG) && + !timespec_equal(&inode->i_ctime, &tv)) { inode->i_ctime = tv; ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec; ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec; + sync_it = 1; } /* @@ -119,10 +125,11 @@ xfs_ichgtime( * ensure that the compiler does not reorder the update * of i_update_core above the timestamp updates above. */ - SYNCHRONIZE(); - ip->i_update_core = 1; - if (!(inode->i_state & I_NEW)) + if (sync_it) { + SYNCHRONIZE(); + ip->i_update_core = 1; mark_inode_dirty_sync(inode); + } } /* -- cgit v1.1 From 3a76c1ea07ee4e9da7c8e476e43be7e1b2bf24fb Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:48:12 +1000 Subject: [XFS] stop using file_update_time xfs_ichtime updates the xfs_inode and Linux inode timestamps just fine, no need to call file_update_time and then copy the values over to the XFS inode. The only additional thing in file_update_time are checks not applicable to the write path. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31829a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy Signed-off-by: David Chinner --- fs/xfs/linux-2.6/xfs_iops.c | 39 --------------------------------------- fs/xfs/linux-2.6/xfs_iops.h | 3 --- fs/xfs/linux-2.6/xfs_lrw.c | 4 +--- 3 files changed, 1 insertion(+), 45 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 0e7ca21..91bcd979 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -133,45 +133,6 @@ xfs_ichgtime( } /* - * Variant on the above which avoids querying the system clock - * in situations where we know the Linux inode timestamps have - * just been updated (and so we can update our inode cheaply). - */ -void -xfs_ichgtime_fast( - xfs_inode_t *ip, - struct inode *inode, - int flags) -{ - timespec_t *tvp; - - if (flags & XFS_ICHGTIME_MOD) { - tvp = &inode->i_mtime; - ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; - ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec; - } - if (flags & XFS_ICHGTIME_CHG) { - tvp = &inode->i_ctime; - ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec; - ip->i_d.di_ctime.t_nsec = (__int32_t)tvp->tv_nsec; - } - - /* - * We update the i_update_core field _after_ changing - * the timestamps in order to coordinate properly with - * xfs_iflush() so that we don't lose timestamp updates. - * This keeps us from having to hold the inode lock - * while doing this. We use the SYNCHRONIZE macro to - * ensure that the compiler does not reorder the update - * of i_update_core above the timestamp updates above. - */ - SYNCHRONIZE(); - ip->i_update_core = 1; - if (!(inode->i_state & I_NEW)) - mark_inode_dirty_sync(inode); -} - -/* * Hook in SELinux. This is not quite correct yet, what we really need * here (as we do for default ACLs) is a mechanism by which creation of * these attrs can be journalled at inode creation time (along with the diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index 2204f46..8b1a1e3 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h @@ -26,9 +26,6 @@ extern const struct file_operations xfs_invis_file_operations; extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size); -extern void xfs_ichgtime(struct xfs_inode *, int); -extern void xfs_ichgtime_fast(struct xfs_inode *, struct inode *, int); - extern void xfs_setup_inode(struct xfs_inode *); #endif /* __XFS_IOPS_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index e03e2c3..1957e535 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -674,9 +674,7 @@ start: */ if (likely(!(ioflags & IO_INVIS) && !mnt_want_write(file->f_path.mnt))) { - file_update_time(file); - xfs_ichgtime_fast(xip, inode, - XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); mnt_drop_write(file->f_path.mnt); } -- cgit v1.1 From 77508ec8e6ed72c9ba8ca74248a7aabd664e3f57 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:49:04 +1000 Subject: [XFS] move root inode IRELE into xfs_unmountfs The root inode is allocated in xfs_mountfs so it should be release in xfs_unmountfs. For the unmount case that means we do it after the the xfs_sync(mp, SYNC_WAIT | SYNC_CLOSE) in the forced shutdown case and the dmapi unmount event. Note that both reference the rip variable which might be freed by that time in case inode flushing has kicked in, so strictly speaking this might count as a bug fix SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31830a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_super.c | 4 ---- fs/xfs/xfs_mount.c | 2 ++ 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 0eaad84..9ccbb1c 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1131,8 +1131,6 @@ xfs_fs_put_super( error = xfs_unmount_flush(mp, 0); WARN_ON(error); - IRELE(rip); - /* * If we're forcing a shutdown, typically because of a media error, * we want to make sure we invalidate dirty pages that belong to @@ -1804,8 +1802,6 @@ xfs_fs_fill_super( error = xfs_unmount_flush(mp, 0); WARN_ON(error); - IRELE(mp->m_rootip); - xfs_unmountfs(mp); goto out_free_fsname; } diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 6b43507..73f0ba1 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1250,6 +1250,8 @@ xfs_unmountfs(xfs_mount_t *mp) __uint64_t resblks; int error = 0; + IRELE(mp->m_rootip); + /* * We can potentially deadlock here if we have an inode cluster * that has been freed has it's buffer still pinned in memory because -- cgit v1.1 From 4249023a5d14f28d4e68ba15d24d25c0e5be71a6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:49:32 +1000 Subject: [XFS] cleanup xfs_mountfs Remove all the useless flags and code keyed off it in xfs_mountfs. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31831a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_super.c | 2 +- fs/xfs/quota/xfs_qm.c | 6 ++---- fs/xfs/quota/xfs_qm.h | 2 +- fs/xfs/quota/xfs_qm_bhv.c | 7 +++---- fs/xfs/xfs_log.c | 4 ++-- fs/xfs/xfs_log.h | 2 +- fs/xfs/xfs_log_priv.h | 2 +- fs/xfs/xfs_log_recover.c | 7 ++----- fs/xfs/xfs_mount.c | 30 ++++++++++-------------------- fs/xfs/xfs_mount.h | 15 ++++----------- 10 files changed, 27 insertions(+), 50 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 9ccbb1c..8fdb790 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1722,7 +1722,7 @@ xfs_fs_fill_super( if (error) goto out_free_sb; - error = xfs_mountfs(mp, flags); + error = xfs_mountfs(mp); if (error) goto out_filestream_unmount; diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 3825d74..df0ffef 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -310,8 +310,7 @@ xfs_qm_unmount_quotadestroy( */ void xfs_qm_mount_quotas( - xfs_mount_t *mp, - int mfsi_flags) + xfs_mount_t *mp) { int error = 0; uint sbf; @@ -346,8 +345,7 @@ xfs_qm_mount_quotas( /* * If any of the quotas are not consistent, do a quotacheck. */ - if (XFS_QM_NEED_QUOTACHECK(mp) && - !(mfsi_flags & XFS_MFSI_NO_QUOTACHECK)) { + if (XFS_QM_NEED_QUOTACHECK(mp)) { error = xfs_qm_quotacheck(mp); if (error) { /* Quotacheck failed and disabled quotas. */ diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h index cd2300e..44f2534 100644 --- a/fs/xfs/quota/xfs_qm.h +++ b/fs/xfs/quota/xfs_qm.h @@ -165,7 +165,7 @@ typedef struct xfs_dquot_acct { #define XFS_QM_RELE(xqm) ((xqm)->qm_nrefs--) extern void xfs_qm_destroy_quotainfo(xfs_mount_t *); -extern void xfs_qm_mount_quotas(xfs_mount_t *, int); +extern void xfs_qm_mount_quotas(xfs_mount_t *); extern int xfs_qm_quotacheck(xfs_mount_t *); extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *); extern int xfs_qm_unmount_quotas(xfs_mount_t *); diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index f4f6c4c..eea2e60 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -162,7 +162,7 @@ xfs_qm_newmount( * mounting, and get on with the boring life * without disk quotas. */ - xfs_qm_mount_quotas(mp, 0); + xfs_qm_mount_quotas(mp); } else { /* * Clear the quota flags, but remember them. This @@ -184,13 +184,12 @@ STATIC int xfs_qm_endmount( xfs_mount_t *mp, uint needquotamount, - uint quotaflags, - int mfsi_flags) + uint quotaflags) { if (needquotamount) { ASSERT(mp->m_qflags == 0); mp->m_qflags = quotaflags; - xfs_qm_mount_quotas(mp, mfsi_flags); + xfs_qm_mount_quotas(mp); } #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 0816c5d..9c23864 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -588,12 +588,12 @@ error: * mp - ubiquitous xfs mount point structure */ int -xfs_log_mount_finish(xfs_mount_t *mp, int mfsi_flags) +xfs_log_mount_finish(xfs_mount_t *mp) { int error; if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) - error = xlog_recover_finish(mp->m_log, mfsi_flags); + error = xlog_recover_finish(mp->m_log); else { error = 0; ASSERT(mp->m_flags & XFS_MOUNT_RDONLY); diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index d1d678e..d47b91f 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h @@ -149,7 +149,7 @@ int xfs_log_mount(struct xfs_mount *mp, struct xfs_buftarg *log_target, xfs_daddr_t start_block, int num_bblocks); -int xfs_log_mount_finish(struct xfs_mount *mp, int); +int xfs_log_mount_finish(struct xfs_mount *mp); void xfs_log_move_tail(struct xfs_mount *mp, xfs_lsn_t tail_lsn); int xfs_log_notify(struct xfs_mount *mp, diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 7dcf11e..c8a5b22 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -468,7 +468,7 @@ extern int xlog_find_tail(xlog_t *log, xfs_daddr_t *head_blk, xfs_daddr_t *tail_blk); extern int xlog_recover(xlog_t *log); -extern int xlog_recover_finish(xlog_t *log, int mfsi_flags); +extern int xlog_recover_finish(xlog_t *log); extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int); extern void xlog_recover_process_iunlinks(xlog_t *log); diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 9eb722e..82d46ce 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3940,8 +3940,7 @@ xlog_recover( */ int xlog_recover_finish( - xlog_t *log, - int mfsi_flags) + xlog_t *log) { /* * Now we're ready to do the transactions needed for the @@ -3969,9 +3968,7 @@ xlog_recover_finish( xfs_log_force(log->l_mp, (xfs_lsn_t)0, (XFS_LOG_FORCE | XFS_LOG_SYNC)); - if ( (mfsi_flags & XFS_MFSI_NOUNLINK) == 0 ) { - xlog_recover_process_iunlinks(log); - } + xlog_recover_process_iunlinks(log); xlog_recover_check_summary(log); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 73f0ba1..06f0a73 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -697,11 +697,11 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount) * Update alignment values based on mount options and sb values */ STATIC int -xfs_update_alignment(xfs_mount_t *mp, int mfsi_flags, __uint64_t *update_flags) +xfs_update_alignment(xfs_mount_t *mp, __uint64_t *update_flags) { xfs_sb_t *sbp = &(mp->m_sb); - if (mp->m_dalign && !(mfsi_flags & XFS_MFSI_SECOND)) { + if (mp->m_dalign) { /* * If stripe unit and stripe width are not multiples * of the fs blocksize turn off alignment. @@ -857,7 +857,7 @@ xfs_set_inoalignment(xfs_mount_t *mp) * Check that the data (and log if separate) are an ok size. */ STATIC int -xfs_check_sizes(xfs_mount_t *mp, int mfsi_flags) +xfs_check_sizes(xfs_mount_t *mp) { xfs_buf_t *bp; xfs_daddr_t d; @@ -880,8 +880,7 @@ xfs_check_sizes(xfs_mount_t *mp, int mfsi_flags) return error; } - if (((mfsi_flags & XFS_MFSI_CLIENT) == 0) && - mp->m_logdev_targp != mp->m_ddev_targp) { + if (mp->m_logdev_targp != mp->m_ddev_targp) { d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { cmn_err(CE_WARN, "XFS: size check 3 failed"); @@ -916,8 +915,7 @@ xfs_check_sizes(xfs_mount_t *mp, int mfsi_flags) */ int xfs_mountfs( - xfs_mount_t *mp, - int mfsi_flags) + xfs_mount_t *mp) { xfs_sb_t *sbp = &(mp->m_sb); xfs_inode_t *rip; @@ -978,7 +976,7 @@ xfs_mountfs( * allocator alignment is within an ag, therefore ag has * to be aligned at stripe boundary. */ - error = xfs_update_alignment(mp, mfsi_flags, &update_flags); + error = xfs_update_alignment(mp, &update_flags); if (error) goto error1; @@ -997,8 +995,7 @@ xfs_mountfs( * since a single partition filesystem is identical to a single * partition volume/filesystem. */ - if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && - (mp->m_flags & XFS_MOUNT_NOUUID) == 0) { + if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) { if (xfs_uuid_mount(mp)) { error = XFS_ERROR(EINVAL); goto error1; @@ -1026,7 +1023,7 @@ xfs_mountfs( /* * Check that the data (and log if separate) are an ok size. */ - error = xfs_check_sizes(mp, mfsi_flags); + error = xfs_check_sizes(mp); if (error) goto error1; @@ -1040,13 +1037,6 @@ xfs_mountfs( } /* - * For client case we are done now - */ - if (mfsi_flags & XFS_MFSI_CLIENT) { - return 0; - } - - /* * Copies the low order bits of the timestamp and the randomly * set "sequence" number out of a UUID. */ @@ -1183,7 +1173,7 @@ xfs_mountfs( * delayed until after the root and real-time bitmap inodes * were consistently read in. */ - error = xfs_log_mount_finish(mp, mfsi_flags); + error = xfs_log_mount_finish(mp); if (error) { cmn_err(CE_WARN, "XFS: log mount finish failed"); goto error4; @@ -1192,7 +1182,7 @@ xfs_mountfs( /* * Complete the quota initialisation, post-log-replay component. */ - error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags); + error = XFS_QM_MOUNT(mp, quotamount, quotaflags); if (error) goto error4; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 5269bd6e..02c16b9 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -114,7 +114,7 @@ struct xfs_dqtrxops; struct xfs_quotainfo; typedef int (*xfs_qminit_t)(struct xfs_mount *, uint *, uint *); -typedef int (*xfs_qmmount_t)(struct xfs_mount *, uint, uint, int); +typedef int (*xfs_qmmount_t)(struct xfs_mount *, uint, uint); typedef int (*xfs_qmunmount_t)(struct xfs_mount *); typedef void (*xfs_qmdone_t)(struct xfs_mount *); typedef void (*xfs_dqrele_t)(struct xfs_dquot *); @@ -158,8 +158,8 @@ typedef struct xfs_qmops { #define XFS_QM_INIT(mp, mnt, fl) \ (*(mp)->m_qm_ops->xfs_qminit)(mp, mnt, fl) -#define XFS_QM_MOUNT(mp, mnt, fl, mfsi_flags) \ - (*(mp)->m_qm_ops->xfs_qmmount)(mp, mnt, fl, mfsi_flags) +#define XFS_QM_MOUNT(mp, mnt, fl) \ + (*(mp)->m_qm_ops->xfs_qmmount)(mp, mnt, fl) #define XFS_QM_UNMOUNT(mp) \ (*(mp)->m_qm_ops->xfs_qmunmount)(mp) #define XFS_QM_DONE(mp) \ @@ -442,13 +442,6 @@ void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname, /* * Flags for xfs_mountfs */ -#define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */ -#define XFS_MFSI_CLIENT 0x02 /* Is a client -- skip lots of stuff */ -/* XFS_MFSI_RRINODES */ -#define XFS_MFSI_NOUNLINK 0x08 /* Skip unlinked inode processing in */ - /* log recovery */ -#define XFS_MFSI_NO_QUOTACHECK 0x10 /* Skip quotacheck processing */ -/* XFS_MFSI_CONVERT_SUNIT */ #define XFS_MFSI_QUIET 0x40 /* Be silent if mount errors found */ #define XFS_DADDR_TO_AGNO(mp,d) xfs_daddr_to_agno(mp,d) @@ -517,7 +510,7 @@ typedef struct xfs_mod_sb { extern void xfs_mod_sb(xfs_trans_t *, __int64_t); extern int xfs_log_sbcount(xfs_mount_t *, uint); -extern int xfs_mountfs(xfs_mount_t *mp, int); +extern int xfs_mountfs(xfs_mount_t *mp); extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); extern int xfs_unmountfs(xfs_mount_t *); -- cgit v1.1 From 41b5c2e77a0221cf07ac127afa122add67ac5418 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:49:57 +1000 Subject: [XFS] xfs_unmountfs should return void xfs_unmounts can't and shouldn't return errors so declare it as returning void. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31833a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_mount.c | 12 +++++------- fs/xfs/xfs_mount.h | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 06f0a73..7f50272 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1229,16 +1229,15 @@ xfs_mountfs( } /* - * xfs_unmountfs - * * This flushes out the inodes,dquots and the superblock, unmounts the * log and makes sure that incore structures are freed. */ -int -xfs_unmountfs(xfs_mount_t *mp) +void +xfs_unmountfs( + struct xfs_mount *mp) { - __uint64_t resblks; - int error = 0; + __uint64_t resblks; + int error; IRELE(mp->m_rootip); @@ -1311,7 +1310,6 @@ xfs_unmountfs(xfs_mount_t *mp) xfs_errortag_clearall(mp, 0); #endif xfs_mount_free(mp); - return 0; } STATIC void diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 02c16b9..f3c1024 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -513,7 +513,7 @@ extern int xfs_log_sbcount(xfs_mount_t *, uint); extern int xfs_mountfs(xfs_mount_t *mp); extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); -extern int xfs_unmountfs(xfs_mount_t *); +extern void xfs_unmountfs(xfs_mount_t *); extern int xfs_unmountfs_writesb(xfs_mount_t *); extern int xfs_unmount_flush(xfs_mount_t *, int); extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int); -- cgit v1.1 From 6203300e5e9121440b27d3ed0b9fe2a64cb62b53 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:50:21 +1000 Subject: [XFS] don't call xfs_freesb from xfs_unmountfs xfs_readsb is called before xfs_mount so xfs_freesb should be called after xfs_unmountfs, too. This means it now happens after a few things during the of xfs_unmount which all have nothing to do with the superblock. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31835a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/linux-2.6/xfs_super.c | 3 ++- fs/xfs/xfs_mount.c | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 8fdb790..73c65f1 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1147,6 +1147,7 @@ xfs_fs_put_super( } xfs_unmountfs(mp); + xfs_freesb(mp); xfs_icsb_destroy_counters(mp); xfs_close_devices(mp); xfs_qmops_put(mp); @@ -1803,7 +1804,7 @@ xfs_fs_fill_super( WARN_ON(error); xfs_unmountfs(mp); - goto out_free_fsname; + goto out_free_sb; } STATIC int diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 7f50272..4d41615 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1296,8 +1296,6 @@ xfs_unmountfs( xfs_unmountfs_wait(mp); /* wait for async bufs */ xfs_log_unmount(mp); /* Done! No more fs ops. */ - xfs_freesb(mp); - /* * All inodes from this mount point should be freed. */ -- cgit v1.1 From ff4f038c6bbb27044a84adbcd27bc237d7237e66 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:50:47 +1000 Subject: [XFS] refactor xfs_mount_free xfs_mount_free mostly frees the perag data, which is something that is duplicated in the mount error path. Move the XFS_QM_DONE call to the caller and remove the useless mutex_destroy/spinlock_destroy calls so that we can re-use it for the mount error path. Also rename it to xfs_free_perag to reflect what it does. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31836a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_mount.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 4d41615..081fb6a 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -128,7 +128,7 @@ static const struct { * initialized. */ STATIC void -xfs_mount_free( +xfs_free_perag( xfs_mount_t *mp) { if (mp->m_perag) { @@ -139,13 +139,6 @@ xfs_mount_free( kmem_free(mp->m_perag[agno].pagb_list); kmem_free(mp->m_perag); } - - spinlock_destroy(&mp->m_ail_lock); - spinlock_destroy(&mp->m_sb_lock); - mutex_destroy(&mp->m_ilock); - mutex_destroy(&mp->m_growlock); - if (mp->m_quotainfo) - XFS_QM_DONE(mp); } /* @@ -922,7 +915,6 @@ xfs_mountfs( __uint64_t resblks; __int64_t update_flags = 0LL; uint quotamount, quotaflags; - int agno; int uuid_mounted = 0; int error = 0; @@ -1216,12 +1208,7 @@ xfs_mountfs( error3: xfs_log_unmount_dealloc(mp); error2: - for (agno = 0; agno < sbp->sb_agcount; agno++) - if (mp->m_perag[agno].pagb_list) - kmem_free(mp->m_perag[agno].pagb_list); - kmem_free(mp->m_perag); - mp->m_perag = NULL; - /* FALLTHROUGH */ + xfs_free_perag(mp); error1: if (uuid_mounted) uuid_table_remove(&mp->m_sb.sb_uuid); @@ -1307,7 +1294,9 @@ xfs_unmountfs( #if defined(DEBUG) xfs_errortag_clearall(mp, 0); #endif - xfs_mount_free(mp); + xfs_free_perag(mp); + if (mp->m_quotainfo) + XFS_QM_DONE(mp); } STATIC void -- cgit v1.1 From d62c251fe4a06144255291cffd68cbadf3bf002f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 13 Aug 2008 16:51:29 +1000 Subject: [XFS] use KM_MAYFAIL in xfs_mountfs Use KM_MAYFAIL for the m_perag allocation, we can deal with the error easily and blocking forever during mount is not a good idea either. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31837a Signed-off-by: Christoph Hellwig Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_mount.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 081fb6a..a4503f5 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1052,8 +1052,10 @@ xfs_mountfs( * Allocate and initialize the per-ag data. */ init_rwsem(&mp->m_peraglock); - mp->m_perag = - kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP); + mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), + KM_MAYFAIL); + if (!mp->m_perag) + goto error1; mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount); -- cgit v1.1 From 5695ef46ef02ba1c6658daa46e6879a2d4f52f5f Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 13 Aug 2008 16:51:57 +1000 Subject: [XFS] Use KM_NOFS for debug trace buffers Use KM_NOFS to prevent recursion back into the filesystem which can cause deadlocks. In the case of xfs_iread() we hold the lock on the inode cluster buffer while allocating memory for the trace buffers. If we recurse back into XFS to flush data that may require a transaction to allocate extents which needs log space. This can deadlock with the xfsaild thread which can't push the tail of the log because it is trying to get the inode cluster buffer lock. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31838a Signed-off-by: Lachlan McIlroy Signed-off-by: David Chinner --- fs/xfs/linux-2.6/xfs_buf.c | 2 +- fs/xfs/quota/xfs_dquot.c | 2 +- fs/xfs/xfs_buf_item.c | 2 +- fs/xfs/xfs_filestream.c | 2 +- fs/xfs/xfs_inode.c | 12 ++++++------ fs/xfs/xfs_log.c | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index a0072d9..986061a 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -1795,7 +1795,7 @@ int __init xfs_buf_init(void) { #ifdef XFS_BUF_TRACE - xfs_buf_trace_buf = ktrace_alloc(XFS_BUF_TRACE_SIZE, KM_SLEEP); + xfs_buf_trace_buf = ktrace_alloc(XFS_BUF_TRACE_SIZE, KM_NOFS); #endif xfs_buf_zone = kmem_zone_init_flags(sizeof(xfs_buf_t), "xfs_buf", diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 3229057..f2705f2 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -112,7 +112,7 @@ xfs_qm_dqinit( complete(&dqp->q_flush); #ifdef XFS_DQUOT_TRACE - dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_SLEEP); + dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_NOFS); xfs_dqtrace_entry(dqp, "DQINIT"); #endif } else { diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 215c36d..608c30c 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -737,7 +737,7 @@ xfs_buf_item_init( bip->bli_format.blf_len = (ushort)BTOBB(XFS_BUF_COUNT(bp)); bip->bli_format.blf_map_size = map_size; #ifdef XFS_BLI_TRACE - bip->bli_trace = ktrace_alloc(XFS_BLI_TRACE_SIZE, KM_SLEEP); + bip->bli_trace = ktrace_alloc(XFS_BLI_TRACE_SIZE, KM_NOFS); #endif #ifdef XFS_TRANS_DEBUG diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index c38fd14..f3bb75d 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c @@ -400,7 +400,7 @@ xfs_filestream_init(void) if (!item_zone) return -ENOMEM; #ifdef XFS_FILESTREAMS_TRACE - xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_SLEEP); + xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_NOFS); #endif return 0; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 41371c5..358511b 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -835,22 +835,22 @@ xfs_iread( * Do this before xfs_iformat in case it adds entries. */ #ifdef XFS_INODE_TRACE - ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_SLEEP); + ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_NOFS); #endif #ifdef XFS_BMAP_TRACE - ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP); + ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_NOFS); #endif #ifdef XFS_BMBT_TRACE - ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_SLEEP); + ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_NOFS); #endif #ifdef XFS_RW_TRACE - ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_SLEEP); + ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_NOFS); #endif #ifdef XFS_ILOCK_TRACE - ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_SLEEP); + ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_NOFS); #endif #ifdef XFS_DIR2_TRACE - ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_SLEEP); + ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); #endif /* diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 9c23864..1f6f780 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -160,7 +160,7 @@ void xlog_trace_iclog(xlog_in_core_t *iclog, uint state) { if (!iclog->ic_trace) - iclog->ic_trace = ktrace_alloc(256, KM_SLEEP); + iclog->ic_trace = ktrace_alloc(256, KM_NOFS); ktrace_enter(iclog->ic_trace, (void *)((unsigned long)state), (void *)((unsigned long)current_pid()), -- cgit v1.1 From c94312de223644e2f18e7064ae8cafa14e5c6ef6 Mon Sep 17 00:00:00 2001 From: Ruben Porras Date: Wed, 13 Aug 2008 16:52:25 +1000 Subject: [XFS] Make xfs_bmap_*_count_leaves void. xfs_bmap_count_leaves and xfs_bmap_disk_count_leaves always return always 0, make them void. SGI-PV: 981498 SGI-Modid: xfs-linux-melb:xfs-kern:31844a Signed-off-by: Ruben Porras Signed-off-by: Donald Douwsma Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_bmap.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 3d6a2ce..a1aab92 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -384,14 +384,14 @@ xfs_bmap_count_tree( int levelin, int *count); -STATIC int +STATIC void xfs_bmap_count_leaves( xfs_ifork_t *ifp, xfs_extnum_t idx, int numrecs, int *count); -STATIC int +STATIC void xfs_bmap_disk_count_leaves( xfs_extnum_t idx, xfs_bmbt_block_t *block, @@ -6367,13 +6367,9 @@ xfs_bmap_count_blocks( mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) { - if (unlikely(xfs_bmap_count_leaves(ifp, 0, + xfs_bmap_count_leaves(ifp, 0, ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t), - count) < 0)) { - XFS_ERROR_REPORT("xfs_bmap_count_blocks(1)", - XFS_ERRLEVEL_LOW, mp); - return XFS_ERROR(EFSCORRUPTED); - } + count); return 0; } @@ -6454,13 +6450,7 @@ xfs_bmap_count_tree( for (;;) { nextbno = be64_to_cpu(block->bb_rightsib); numrecs = be16_to_cpu(block->bb_numrecs); - if (unlikely(xfs_bmap_disk_count_leaves(0, - block, numrecs, count) < 0)) { - xfs_trans_brelse(tp, bp); - XFS_ERROR_REPORT("xfs_bmap_count_tree(2)", - XFS_ERRLEVEL_LOW, mp); - return XFS_ERROR(EFSCORRUPTED); - } + xfs_bmap_disk_count_leaves(0, block, numrecs, count); xfs_trans_brelse(tp, bp); if (nextbno == NULLFSBLOCK) break; @@ -6478,7 +6468,7 @@ xfs_bmap_count_tree( /* * Count leaf blocks given a range of extent records. */ -STATIC int +STATIC void xfs_bmap_count_leaves( xfs_ifork_t *ifp, xfs_extnum_t idx, @@ -6491,14 +6481,13 @@ xfs_bmap_count_leaves( xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b); *count += xfs_bmbt_get_blockcount(frp); } - return 0; } /* * Count leaf blocks given a range of extent records originally * in btree format. */ -STATIC int +STATIC void xfs_bmap_disk_count_leaves( xfs_extnum_t idx, xfs_bmbt_block_t *block, @@ -6512,5 +6501,4 @@ xfs_bmap_disk_count_leaves( frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, idx + b); *count += xfs_bmbt_disk_get_blockcount(frp); } - return 0; } -- cgit v1.1 From c6a7b0f8a49aa71792dd108efc535435f462bf79 Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Wed, 13 Aug 2008 16:52:50 +1000 Subject: [XFS] Fix use after free in xfs_log_done(). The ticket allocation code got reworked in 2.6.26 and we now free tickets whereas before we used to cache them so the use-after-free went undetected. SGI-PV: 985525 SGI-Modid: xfs-linux-melb:xfs-kern:31877a Signed-off-by: Lachlan McIlroy Signed-off-by: David Chinner --- fs/xfs/xfs_log.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 1f6f780..ccba14e 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -336,15 +336,12 @@ xfs_log_done(xfs_mount_t *mp, } else { xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)"); xlog_regrant_reserve_log_space(log, ticket); - } - - /* If this ticket was a permanent reservation and we aren't - * trying to release it, reset the inited flags; so next time - * we write, a start record will be written out. - */ - if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) && - (flags & XFS_LOG_REL_PERM_RESERV) == 0) + /* If this ticket was a permanent reservation and we aren't + * trying to release it, reset the inited flags; so next time + * we write, a start record will be written out. + */ ticket->t_flags |= XLOG_TIC_INITED; + } return lsn; } /* xfs_log_done */ -- cgit v1.1 From ce769caa50a3fc835b4fc1a6e1463ada127a2e8a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 18 Jul 2008 12:54:21 +0300 Subject: UBIFS: print volume name as well We encouredge people to mount using volume name, not device numbers. So print the name of the mounted UBI volume, not just IDs. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index ca1e2d4..43af934 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1122,8 +1122,8 @@ static int mount_ubifs(struct ubifs_info *c) if (err) goto out_infos; - ubifs_msg("mounted UBI device %d, volume %d", c->vi.ubi_num, - c->vi.vol_id); + ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"", + c->vi.ubi_num, c->vi.vol_id, c->vi.name); if (mounted_read_only) ubifs_msg("mounted read-only"); x = (long long)c->main_lebs * c->leb_size; -- cgit v1.1 From 182854b46f9feb6f1b03abe747bb2beeebf2adb0 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 18 Jul 2008 18:54:29 +0300 Subject: UBIFS: fix budgeting calculations The 'ubifs_release_dirty_inode_budget()' was buggy and incorrectly freed the budget, which led to not freeing all dirty data budget. This patch fixes that. Also, this patch fixes ubifs_mkdir() which passed 1 in dirty_ino_d, which makes no sense. Well, it is harmless though. Also, add few more useful assertions. And improve few debugging messages. Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 5 +++-- fs/ubifs/dir.c | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index d81fb9e..12a1717 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -686,9 +686,10 @@ void ubifs_convert_page_budget(struct ubifs_info *c) void ubifs_release_dirty_inode_budget(struct ubifs_info *c, struct ubifs_inode *ui) { - struct ubifs_budget_req req = {.dd_growth = c->inode_budget, - .dirtied_ino_d = ui->data_len}; + struct ubifs_budget_req req; + memset(&req, 0, sizeof(struct ubifs_budget_req)); + req.dd_growth = c->inode_budget + ui->data_len; ubifs_release_budget(c, &req); } diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index e90374b..a79e850 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -727,8 +727,7 @@ static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, int mode) struct ubifs_inode *dir_ui = ubifs_inode(dir); struct ubifs_info *c = dir->i_sb->s_fs_info; int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); - struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, - .dirtied_ino_d = 1 }; + struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 }; /* * Budget request settings: new inode, new direntry and changing parent -- cgit v1.1 From 7d32c2bb143fa1ca3b0c420feb08a832d65395be Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 18 Jul 2008 18:54:29 +0300 Subject: UBIFS: improve debugging 1. Print inode mode in some of debugging messages 2. Add few more useful assertions Signed-off-by: Artem Bityutskiy --- fs/ubifs/file.c | 3 ++- fs/ubifs/super.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 8565e58..01598f2 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -941,7 +941,8 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; struct ubifs_info *c = inode->i_sb->s_fs_info; - dbg_gen("ino %lu, ia_valid %#x", inode->i_ino, attr->ia_valid); + dbg_gen("ino %lu, mode %#x, ia_valid %#x", + inode->i_ino, inode->i_mode, attr->ia_valid); err = inode_change_ok(inode, attr); if (err) return err; diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 43af934..06e3b22a 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -299,7 +299,7 @@ static int ubifs_write_inode(struct inode *inode, int wait) return 0; } - dbg_gen("inode %lu", inode->i_ino); + dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode); err = ubifs_jnl_write_inode(c, inode, 0); if (err) ubifs_err("can't write inode %lu, error %d", inode->i_ino, err); @@ -323,9 +323,10 @@ static void ubifs_delete_inode(struct inode *inode) */ goto out; - dbg_gen("inode %lu", inode->i_ino); + dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode); ubifs_assert(!atomic_read(&inode->i_count)); ubifs_assert(inode->i_nlink == 0); + ubifs_assert(!ubifs_inode(inode)->dirty); truncate_inode_pages(&inode->i_data, 0); if (is_bad_inode(inode)) @@ -1469,6 +1470,7 @@ static void ubifs_put_super(struct super_block *sb) */ ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); ubifs_assert(c->budg_idx_growth == 0); + ubifs_assert(c->budg_dd_growth == 0); ubifs_assert(c->budg_data_growth == 0); /* -- cgit v1.1 From 1e0f358e29cc91c8eb09e10cbf1f6bb58a62c795 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 21 Jul 2008 10:59:53 +0300 Subject: UBIFS: free budget in delete_inode as well Although the inode is marked as clean when it is being deleted, it might stay and be used as orphan, and be marked as dirty. So we have to free the budget when we delete it. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 06e3b22a..884beed 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -314,8 +314,9 @@ static void ubifs_delete_inode(struct inode *inode) { int err; struct ubifs_info *c = inode->i_sb->s_fs_info; + struct ubifs_inode *ui = ubifs_inode(inode); - if (ubifs_inode(inode)->xattr) + if (ui->xattr) /* * Extended attribute inode deletions are fully handled in * 'ubifs_removexattr()'. These inodes are special and have @@ -326,13 +327,12 @@ static void ubifs_delete_inode(struct inode *inode) dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode); ubifs_assert(!atomic_read(&inode->i_count)); ubifs_assert(inode->i_nlink == 0); - ubifs_assert(!ubifs_inode(inode)->dirty); truncate_inode_pages(&inode->i_data, 0); if (is_bad_inode(inode)) goto out; - ubifs_inode(inode)->ui_size = inode->i_size = 0; + ui->ui_size = inode->i_size = 0; err = ubifs_jnl_write_inode(c, inode, 1); if (err) /* @@ -341,6 +341,8 @@ static void ubifs_delete_inode(struct inode *inode) */ ubifs_err("can't write inode %lu, error %d", inode->i_ino, err); out: + if (ui->dirty) + ubifs_release_dirty_inode_budget(c, ui); clear_inode(inode); } -- cgit v1.1 From 16dfd804b44ef7156d1c201f100bd0d9dc6b7c4b Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 18 Jul 2008 16:47:41 +0300 Subject: UBIFS: fix error return in failure mode UBIFS recovery testing debug facility simulates media failures. When simulating an IO error, the error code returned must be -EIO but it was not always if the user switched off the debug recovery testing option at the same time. Signed-off-by: Adrian Hunter --- fs/ubifs/debug.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 4e3aaeb..0adfb29 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2208,16 +2208,17 @@ int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, int offset, int len, int dtype) { - int err; + int err, failing; if (in_failure_mode(desc)) return -EIO; - if (do_fail(desc, lnum, 1)) + failing = do_fail(desc, lnum, 1); + if (failing) cut_data(buf, len); err = ubi_leb_write(desc, lnum, buf, offset, len, dtype); if (err) return err; - if (in_failure_mode(desc)) + if (failing) return -EIO; return 0; } -- cgit v1.1 From 2fb42b11f61cbcef7dfc225c1d26c4511436583d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 18 Jul 2008 17:56:37 +0300 Subject: UBIFS: ensure UBIFS switches to read-only on error UBI transparently handles write errors by automatically copying and remapping the affected eraseblock. If UBI is unable to do that, for example its pool of eraseblocks reserved for bad block handling is empty, then the error is propagated to UBIFS. UBIFS must protect the media from falling into an inconsistent state by immediately switching to read-only mode. In the case of log updates, this was not being done. Signed-off-by: Adrian Hunter --- fs/ubifs/log.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c index 36857b9..e14829e 100644 --- a/fs/ubifs/log.c +++ b/fs/ubifs/log.c @@ -317,6 +317,8 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs) return 0; out_unlock: + if (err != -EAGAIN) + ubifs_ro_mode(c, err); mutex_unlock(&c->log_mutex); kfree(ref); kfree(bud); -- cgit v1.1 From ff46d7b3e0870a70331b069372c36fbc43018c2d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 21 Jul 2008 15:39:05 +0300 Subject: UBIFS: make ubifs_ro_mode() not inline We use ubifs_ro_mode() quite a lot, and not in fast-path, so there is no reason to blow the code up by having it inlined. Also, we usually want R/O mode change to be seen to other CPUs as soon as possible, so when we make this a function call, we will automatically have a memory barrier. Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/io.c | 14 ++++++++++++++ fs/ubifs/misc.h | 14 -------------- fs/ubifs/ubifs.h | 1 + 3 files changed, 15 insertions(+), 14 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 3374f91..054363f 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -54,6 +54,20 @@ #include "ubifs.h" /** + * ubifs_ro_mode - switch UBIFS to read read-only mode. + * @c: UBIFS file-system description object + * @err: error code which is the reason of switching to R/O mode + */ +void ubifs_ro_mode(struct ubifs_info *c, int err) +{ + if (!c->ro_media) { + c->ro_media = 1; + ubifs_warn("switched to read-only mode, error %d", err); + dbg_dump_stack(); + } +} + +/** * ubifs_check_node - check node. * @c: UBIFS file-system description object * @buf: node to check diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h index 4beccfc..cd83ffc 100644 --- a/fs/ubifs/misc.h +++ b/fs/ubifs/misc.h @@ -80,20 +80,6 @@ static inline struct ubifs_inode *ubifs_inode(const struct inode *inode) } /** - * ubifs_ro_mode - switch UBIFS to read read-only mode. - * @c: UBIFS file-system description object - * @err: error code which is the reason of switching to R/O mode - */ -static inline void ubifs_ro_mode(struct ubifs_info *c, int err) -{ - if (!c->ro_media) { - c->ro_media = 1; - ubifs_warn("switched to read-only mode, error %d", err); - dbg_dump_stack(); - } -} - -/** * ubifs_compr_present - check if compressor was compiled in. * @compr_type: compressor type to check * diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index e4f89f2..c488d43 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1346,6 +1346,7 @@ extern struct backing_dev_info ubifs_backing_dev_info; extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; /* io.c */ +void ubifs_ro_mode(struct ubifs_info *c, int err); int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len); int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs, int dtype); -- cgit v1.1 From fbfa6c884aae2aff479eb8c996c564b1a34eae30 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 22 Jul 2008 11:52:52 +0300 Subject: UBIFS: do not write orphans back Orphan inodes are deleted inodes which will disappear after FS re-mount. There is not need to write orphan inodes back, because they are not needed on the flash media. So optimize orphans a little by not writing them back. Just mark them as clean, free the budget, and report success to VFS. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 884beed..13e90b0 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -278,7 +278,7 @@ static void ubifs_destroy_inode(struct inode *inode) */ static int ubifs_write_inode(struct inode *inode, int wait) { - int err; + int err = 0; struct ubifs_info *c = inode->i_sb->s_fs_info; struct ubifs_inode *ui = ubifs_inode(inode); @@ -299,10 +299,18 @@ static int ubifs_write_inode(struct inode *inode, int wait) return 0; } - dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode); - err = ubifs_jnl_write_inode(c, inode, 0); - if (err) - ubifs_err("can't write inode %lu, error %d", inode->i_ino, err); + /* + * As an optimization, do not write orphan inodes to the media just + * because this is not needed. + */ + dbg_gen("inode %lu, mode %#x, nlink %u", + inode->i_ino, (int)inode->i_mode, inode->i_nlink); + if (inode->i_nlink) { + err = ubifs_jnl_write_inode(c, inode, 0); + if (err) + ubifs_err("can't write inode %lu, error %d", + inode->i_ino, err); + } ui->dirty = 0; mutex_unlock(&ui->ui_mutex); -- cgit v1.1 From 1f28681ad34a0c7e51dc5070c84b53f7bd34f44c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 22 Jul 2008 12:06:13 +0300 Subject: UBIFS: remove unneeded function parameter Simplify 'ubifs_jnl_write_inode()' by removing the 'deletion' parameter which is not really needed because we may test inode->i_nlink and check whether this is a deletion or not. Signed-off-by: Artem Bityutskiy --- fs/ubifs/journal.c | 19 +++++++------------ fs/ubifs/super.c | 4 ++-- fs/ubifs/ubifs.h | 3 +-- 3 files changed, 10 insertions(+), 16 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 283155a..666ad82 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -750,30 +750,25 @@ out_free: * ubifs_jnl_write_inode - flush inode to the journal. * @c: UBIFS file-system description object * @inode: inode to flush - * @deletion: inode has been deleted * * This function writes inode @inode to the journal. If the inode is * synchronous, it also synchronizes the write-buffer. Returns zero in case of * success and a negative error code in case of failure. */ -int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode, - int deletion) +int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) { - int err, len, lnum, offs, sync = 0; + int err, lnum, offs; struct ubifs_ino_node *ino; struct ubifs_inode *ui = ubifs_inode(inode); + int sync = 0, len = UBIFS_INO_NODE_SZ, last_reference = !inode->i_nlink; - dbg_jnl("ino %lu%s", inode->i_ino, - deletion ? " (last reference)" : ""); - if (deletion) - ubifs_assert(inode->i_nlink == 0); + dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink); - len = UBIFS_INO_NODE_SZ; /* * If the inode is being deleted, do not write the attached data. No * need to synchronize the write-buffer either. */ - if (!deletion) { + if (!last_reference) { len += ui->data_len; sync = IS_SYNC(inode); } @@ -786,7 +781,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode, if (err) goto out_free; - pack_inode(c, ino, inode, 1, deletion); + pack_inode(c, ino, inode, 1, last_reference); err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync); if (err) goto out_release; @@ -795,7 +790,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode, inode->i_ino); release_head(c, BASEHD); - if (deletion) { + if (last_reference) { err = ubifs_tnc_remove_ino(c, inode->i_ino); if (err) goto out_ro; diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 13e90b0..cf1fb6c 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -306,7 +306,7 @@ static int ubifs_write_inode(struct inode *inode, int wait) dbg_gen("inode %lu, mode %#x, nlink %u", inode->i_ino, (int)inode->i_mode, inode->i_nlink); if (inode->i_nlink) { - err = ubifs_jnl_write_inode(c, inode, 0); + err = ubifs_jnl_write_inode(c, inode); if (err) ubifs_err("can't write inode %lu, error %d", inode->i_ino, err); @@ -341,7 +341,7 @@ static void ubifs_delete_inode(struct inode *inode) goto out; ui->ui_size = inode->i_size = 0; - err = ubifs_jnl_write_inode(c, inode, 1); + err = ubifs_jnl_write_inode(c, inode); if (err) /* * Worst case we have a lost orphan inode wasting space, so a diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index c488d43..6ddd1de 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1400,8 +1400,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, int deletion, int xent); int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, const union ubifs_key *key, const void *buf, int len); -int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode, - int last_reference); +int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode); int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, const struct dentry *old_dentry, const struct inode *new_dir, -- cgit v1.1 From fd6c6b51e3677937090314b20b00f2194900d81b Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 22 Jul 2008 12:19:09 +0300 Subject: UBIFS: remove another unneeded function parameter The 'last_reference' parameter of 'pack_inode()' is not really needed because 'inode->i_nlink' may be tested instead. Zap it. Signed-off-by: Artem Bityutskiy --- fs/ubifs/journal.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 666ad82..3bc3fc9 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -447,13 +447,11 @@ static int get_dent_type(int mode) * @ino: buffer in which to pack inode node * @inode: inode to pack * @last: indicates the last node of the group - * @last_reference: non-zero if this is a deletion inode */ static void pack_inode(struct ubifs_info *c, struct ubifs_ino_node *ino, - const struct inode *inode, int last, - int last_reference) + const struct inode *inode, int last) { - int data_len = 0; + int data_len = 0, last_reference = !inode->i_nlink; struct ubifs_inode *ui = ubifs_inode(inode); ino->ch.node_type = UBIFS_INO_NODE; @@ -596,9 +594,9 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, ubifs_prep_grp_node(c, dent, dlen, 0); ino = (void *)dent + aligned_dlen; - pack_inode(c, ino, inode, 0, last_reference); + pack_inode(c, ino, inode, 0); ino = (void *)ino + aligned_ilen; - pack_inode(c, ino, dir, 1, 0); + pack_inode(c, ino, dir, 1); if (last_reference) { err = ubifs_add_orphan(c, inode->i_ino); @@ -781,7 +779,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) if (err) goto out_free; - pack_inode(c, ino, inode, 1, last_reference); + pack_inode(c, ino, inode, 1); err = write_head(c, BASEHD, ino, len, &lnum, &offs, sync); if (err) goto out_release; @@ -912,16 +910,16 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, p = (void *)dent2 + aligned_dlen2; if (new_inode) { - pack_inode(c, p, new_inode, 0, last_reference); + pack_inode(c, p, new_inode, 0); p += ALIGN(ilen, 8); } if (!move) - pack_inode(c, p, old_dir, 1, 0); + pack_inode(c, p, old_dir, 1); else { - pack_inode(c, p, old_dir, 0, 0); + pack_inode(c, p, old_dir, 0); p += ALIGN(plen, 8); - pack_inode(c, p, new_dir, 1, 0); + pack_inode(c, p, new_dir, 1); } if (last_reference) { @@ -1126,7 +1124,7 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, if (err) goto out_free; - pack_inode(c, ino, inode, 0, 0); + pack_inode(c, ino, inode, 0); ubifs_prep_grp_node(c, trun, UBIFS_TRUN_NODE_SZ, dlen ? 0 : 1); if (dlen) ubifs_prep_grp_node(c, dn, dlen, 1); @@ -1246,9 +1244,9 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host, ubifs_prep_grp_node(c, xent, xlen, 0); ino = (void *)xent + aligned_xlen; - pack_inode(c, ino, inode, 0, 1); + pack_inode(c, ino, inode, 0); ino = (void *)ino + UBIFS_INO_NODE_SZ; - pack_inode(c, ino, host, 1, 0); + pack_inode(c, ino, host, 1); err = write_head(c, BASEHD, xent, len, &lnum, &xent_offs, sync); if (!sync && !err) @@ -1339,8 +1337,8 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, if (err) goto out_free; - pack_inode(c, ino, host, 0, 0); - pack_inode(c, (void *)ino + aligned_len1, inode, 1, 0); + pack_inode(c, ino, host, 0); + pack_inode(c, (void *)ino + aligned_len1, inode, 1); err = write_head(c, BASEHD, ino, aligned_len, &lnum, &offs, 0); if (!sync && !err) { -- cgit v1.1 From 014eb04b03202dc75c1c749df4246d98045f5e69 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 21 Jul 2008 17:14:29 +0300 Subject: UBIFS: increment commit number earlier Increment the commit number at the beginnig of the commit, instead of doing this after the commit. This is needed for further optimizations. Signed-off-by: Artem Bityutskiy --- fs/ubifs/commit.c | 3 ++- fs/ubifs/log.c | 2 +- fs/ubifs/orphan.c | 4 ++-- fs/ubifs/ubifs.h | 3 ++- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c index 3b51631..0a6aa2c 100644 --- a/fs/ubifs/commit.c +++ b/fs/ubifs/commit.c @@ -74,6 +74,7 @@ static int do_commit(struct ubifs_info *c) goto out_up; } + c->cmt_no += 1; err = ubifs_gc_start_commit(c); if (err) goto out_up; @@ -115,7 +116,7 @@ static int do_commit(struct ubifs_info *c) goto out; mutex_lock(&c->mst_mutex); - c->mst_node->cmt_no = cpu_to_le64(++c->cmt_no); + c->mst_node->cmt_no = cpu_to_le64(c->cmt_no); c->mst_node->log_lnum = cpu_to_le32(new_ltail_lnum); c->mst_node->root_lnum = cpu_to_le32(zroot.lnum); c->mst_node->root_offs = cpu_to_le32(zroot.offs); diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c index e14829e..3e0aa73 100644 --- a/fs/ubifs/log.c +++ b/fs/ubifs/log.c @@ -412,7 +412,7 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum) return -ENOMEM; cs->ch.node_type = UBIFS_CS_NODE; - cs->cmt_no = cpu_to_le64(c->cmt_no + 1); + cs->cmt_no = cpu_to_le64(c->cmt_no); ubifs_prepare_node(c, cs, UBIFS_CS_NODE_SZ, 0); /* diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index 3afeb92..02d3462 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c @@ -310,10 +310,10 @@ static int write_orph_node(struct ubifs_info *c, int atomic) c->cmt_orphans -= cnt; spin_unlock(&c->orphan_lock); if (c->cmt_orphans) - orph->cmt_no = cpu_to_le64(c->cmt_no + 1); + orph->cmt_no = cpu_to_le64(c->cmt_no); else /* Mark the last node of the commit */ - orph->cmt_no = cpu_to_le64((c->cmt_no + 1) | (1ULL << 63)); + orph->cmt_no = cpu_to_le64((c->cmt_no) | (1ULL << 63)); ubifs_assert(c->ohead_offs + len <= c->leb_size); ubifs_assert(c->ohead_lnum >= c->orph_first); ubifs_assert(c->ohead_lnum <= c->orph_last); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 6ddd1de..21502b6 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -865,7 +865,8 @@ struct ubifs_mount_opts { * @highest_inum: highest used inode number * @vfs_gen: VFS inode generation counter * @max_sqnum: current global sequence number - * @cmt_no: commit number (last successfully completed commit) + * @cmt_no: commit number of the last successfully completed commit, protected + * by @commit_sem * @cnt_lock: protects @highest_inum, @vfs_gen, and @max_sqnum counters * @fmt_version: UBIFS on-flash format version * @uuid: UUID from super block -- cgit v1.1 From de94eb558b542873d3f6f9ede1b8575fb5662248 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 22 Jul 2008 13:06:20 +0300 Subject: UBIFS: optimize deletions Every time anything is deleted, UBIFS writes the deletion inode node twice - once in 'ubifs_jnl_update()' and the second time in 'ubifs_jnl_write_inode()'. However, the second write is not needed if no commit happened after 'ubifs_jnl_update()'. This patch checks that condition and avoids writing the deletion inode for the second time. Signed-off-by: Artem Bityutskiy --- fs/ubifs/journal.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ubifs/super.c | 6 ++++-- fs/ubifs/ubifs.h | 12 ++++++++--- 3 files changed, 73 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 3bc3fc9..0bcee7d 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -604,6 +604,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, release_head(c, BASEHD); goto out_finish; } + ui->del_cmtno = c->cmt_no; } err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync); @@ -821,6 +822,64 @@ out_free: } /** + * ubifs_jnl_write_inode - delete an inode. + * @c: UBIFS file-system description object + * @inode: inode to delete + * + * This function deletes inode @inode which includes removing it from orphans, + * deleting it from TNC and, in some cases, writing a deletion inode to the + * journal. + * + * When regular file inodes are unlinked or a directory inode is removed, the + * 'ubifs_jnl_update()' function write corresponding deletion inode and + * direntry to the media, and adds the inode to orphans. After this, when the + * last reference to this inode has been dropped, this function is called. In + * general, it has to write one more deletion inode to the media, because if + * a commit happened between 'ubifs_jnl_update()' and + * 'ubifs_jnl_delete_inode()', the deletion inode is not in the journal + * anymore, and in fact it might be not on the flash anymore, becouse it might + * have been garbage-collected already. And for optimization reasond UBIFS does + * not read the orphan area if it has been unmounted cleanly, so it would have + * no indication in the journal that there is a deleted inode which has to be + * removed from TNC. + * + * However, if there was no commit between 'ubifs_jnl_update()' and + * 'ubifs_jnl_delete_inode()', then there is no need to write the deletion + * inode to the media for the second time. And this is quite typical case. + * + * This function returns zero in case of success and a negative error code in + * case of failure. + */ +int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode) +{ + int err; + struct ubifs_inode *ui = ubifs_inode(inode); + + ubifs_assert(inode->i_nlink == 0); + + if (ui->del_cmtno != c->cmt_no) + /* A commit happened for sure */ + return ubifs_jnl_write_inode(c, inode); + + down_read(&c->commit_sem); + /* + * Check commit number again, because the first test has been done + * without @c->commit_sem, so a commit might have happened. + */ + if (ui->del_cmtno != c->cmt_no) { + up_read(&c->commit_sem); + return ubifs_jnl_write_inode(c, inode); + } + + ubifs_delete_orphan(c, inode->i_ino); + err = ubifs_tnc_remove_ino(c, inode->i_ino); + if (err) + ubifs_ro_mode(c, err); + up_read(&c->commit_sem); + return err; +} + +/** * ubifs_jnl_rename - rename a directory entry. * @c: UBIFS file-system description object * @old_dir: parent inode of directory entry to rename @@ -928,6 +987,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, release_head(c, BASEHD); goto out_finish; } + new_ui->del_cmtno = c->cmt_no; } err = write_head(c, BASEHD, dent, len, &lnum, &offs, sync); diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index cf1fb6c..6cc4175 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -341,13 +341,15 @@ static void ubifs_delete_inode(struct inode *inode) goto out; ui->ui_size = inode->i_size = 0; - err = ubifs_jnl_write_inode(c, inode); + err = ubifs_jnl_delete_inode(c, inode); if (err) /* * Worst case we have a lost orphan inode wasting space, so a * simple error message is ok here. */ - ubifs_err("can't write inode %lu, error %d", inode->i_ino, err); + ubifs_err("can't delete inode %lu, error %d", + inode->i_ino, err); + out: if (ui->dirty) ubifs_release_dirty_inode_budget(c, ui); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 21502b6..dfb4b93 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -322,6 +322,8 @@ struct ubifs_gced_idx_leb { * struct ubifs_inode - UBIFS in-memory inode description. * @vfs_inode: VFS inode description object * @creat_sqnum: sequence number at time of creation + * @del_cmtno: commit number corresponding to the time the inode was deleted, + * protected by @c->commit_sem; * @xattr_size: summarized size of all extended attributes in bytes * @xattr_cnt: count of extended attributes this inode has * @xattr_names: sum of lengths of all extended attribute names belonging to @@ -372,7 +374,10 @@ struct ubifs_gced_idx_leb { */ struct ubifs_inode { struct inode vfs_inode; - unsigned long long creat_sqnum; + union { + unsigned long long creat_sqnum; + unsigned long long del_cmtno; + }; unsigned int xattr_size; unsigned int xattr_cnt; unsigned int xattr_names; @@ -779,7 +784,7 @@ struct ubifs_compressor { /** * struct ubifs_budget_req - budget requirements of an operation. * - * @fast: non-zero if the budgeting should try to aquire budget quickly and + * @fast: non-zero if the budgeting should try to acquire budget quickly and * should not try to call write-back * @recalculate: non-zero if @idx_growth, @data_growth, and @dd_growth fields * have to be re-calculated @@ -860,7 +865,7 @@ struct ubifs_mount_opts { * struct ubifs_info - UBIFS file-system description data structure * (per-superblock). * @vfs_sb: VFS @struct super_block object - * @bdi: backing device info object to make VFS happy and disable readahead + * @bdi: backing device info object to make VFS happy and disable read-ahead * * @highest_inum: highest used inode number * @vfs_gen: VFS inode generation counter @@ -1402,6 +1407,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, const union ubifs_key *key, const void *buf, int len); int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode); +int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode); int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir, const struct dentry *old_dentry, const struct inode *new_dir, -- cgit v1.1 From bc813355c704e5916a86dd4b96fd226bfa3fc6ca Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 23 Jul 2008 15:23:11 +0300 Subject: UBIFS: do not union creat_sqnum and del_cmtno The values in these two fields need to be preserved independently and so a union cannot be used. Signed-off-by: Adrian Hunter --- fs/ubifs/ubifs.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index dfb4b93..d342c69 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -374,10 +374,8 @@ struct ubifs_gced_idx_leb { */ struct ubifs_inode { struct inode vfs_inode; - union { - unsigned long long creat_sqnum; - unsigned long long del_cmtno; - }; + unsigned long long creat_sqnum; + unsigned long long del_cmtno; unsigned int xattr_size; unsigned int xattr_cnt; unsigned int xattr_names; -- cgit v1.1 From 7d62ff2c396470bb62a3853f14d3962eac1da974 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 23 Jul 2008 15:48:39 +0300 Subject: UBIFS: fix typos in comments Signed-off-by: Adrian Hunter --- fs/ubifs/journal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 0bcee7d..25de6fd 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -822,7 +822,7 @@ out_free: } /** - * ubifs_jnl_write_inode - delete an inode. + * ubifs_jnl_delete_inode - delete an inode. * @c: UBIFS file-system description object * @inode: inode to delete * @@ -831,21 +831,21 @@ out_free: * journal. * * When regular file inodes are unlinked or a directory inode is removed, the - * 'ubifs_jnl_update()' function write corresponding deletion inode and + * 'ubifs_jnl_update()' function writes a corresponding deletion inode and * direntry to the media, and adds the inode to orphans. After this, when the * last reference to this inode has been dropped, this function is called. In * general, it has to write one more deletion inode to the media, because if * a commit happened between 'ubifs_jnl_update()' and * 'ubifs_jnl_delete_inode()', the deletion inode is not in the journal - * anymore, and in fact it might be not on the flash anymore, becouse it might - * have been garbage-collected already. And for optimization reasond UBIFS does + * anymore, and in fact it might not be on the flash anymore, because it might + * have been garbage-collected already. And for optimization reasons UBIFS does * not read the orphan area if it has been unmounted cleanly, so it would have * no indication in the journal that there is a deleted inode which has to be * removed from TNC. * * However, if there was no commit between 'ubifs_jnl_update()' and * 'ubifs_jnl_delete_inode()', then there is no need to write the deletion - * inode to the media for the second time. And this is quite typical case. + * inode to the media for the second time. And this is quite a typical case. * * This function returns zero in case of success and a negative error code in * case of failure. -- cgit v1.1 From f769108424a19c7758546d1d7d19f098b1a33759 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 23 Jul 2008 16:55:55 +0300 Subject: UBIFS: correct orphan deletion order The debug function that checks orphans, does so using the TNC mutex. That means it will not see a correct picture if the inode is removed from the orphan tree before it is removed from TNC. Signed-off-by: Adrian Hunter --- fs/ubifs/journal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 25de6fd..acdae00 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -871,10 +871,11 @@ int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode) return ubifs_jnl_write_inode(c, inode); } - ubifs_delete_orphan(c, inode->i_ino); err = ubifs_tnc_remove_ino(c, inode->i_ino); if (err) ubifs_ro_mode(c, err); + else + ubifs_delete_orphan(c, inode->i_ino); up_read(&c->commit_sem); return err; } -- cgit v1.1 From 547000da6412c45456ff2ff44a171d01027bd727 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 24 Jul 2008 14:42:05 +0300 Subject: UBIFS: improve budgeting checks Budgeting is a crucial UBIFS subsystem - add more assertions to improve requests checking. This is not compiled in when UBIFS debugging is disabled. Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 12 ++++++++++++ fs/ubifs/ubifs.h | 8 +++++++- 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 12a1717..f5afce5 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -543,6 +543,12 @@ int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req) int err, idx_growth, data_growth, dd_growth; struct retries_info ri; + ubifs_assert(req->new_page <= 1); + ubifs_assert(req->dirtied_page <= 1); + ubifs_assert(req->new_dent <= 1); + ubifs_assert(req->mod_dent <= 1); + ubifs_assert(req->new_ino <= 1); + ubifs_assert(req->new_ino_d <= UBIFS_MAX_INO_DATA); ubifs_assert(req->dirtied_ino <= 4); ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4); @@ -618,6 +624,12 @@ again: */ void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req) { + ubifs_assert(req->new_page <= 1); + ubifs_assert(req->dirtied_page <= 1); + ubifs_assert(req->new_dent <= 1); + ubifs_assert(req->mod_dent <= 1); + ubifs_assert(req->new_ino <= 1); + ubifs_assert(req->new_ino_d <= UBIFS_MAX_INO_DATA); ubifs_assert(req->dirtied_ino <= 4); ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4); if (!req->recalculate) { diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index d342c69..565dca2 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -812,17 +812,23 @@ struct ubifs_compressor { struct ubifs_budget_req { unsigned int fast:1; unsigned int recalculate:1; +#ifndef UBIFS_DEBUG unsigned int new_page:1; unsigned int dirtied_page:1; unsigned int new_dent:1; unsigned int mod_dent:1; unsigned int new_ino:1; unsigned int new_ino_d:13; -#ifndef UBIFS_DEBUG unsigned int dirtied_ino:4; unsigned int dirtied_ino_d:15; #else /* Not bit-fields to check for overflows */ + unsigned int new_page; + unsigned int dirtied_page; + unsigned int new_dent; + unsigned int mod_dent; + unsigned int new_ino; + unsigned int new_ino_d; unsigned int dirtied_ino; unsigned int dirtied_ino_d; #endif -- cgit v1.1 From dab4b4d2f915a65022343012a795f4ae4ae7e83c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 24 Jul 2008 14:52:45 +0300 Subject: UBIFS: align inode data to eight UBIFS aligns node lengths to 8, so budgeting has to do the same. Well, direntry, inode, and page budgets are already aligned, but not inode data budget (e.g., data in special devices or symlinks). Do this for inode data as well. Also, add corresponding debugging checks. Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 10 +++++++++- fs/ubifs/dir.c | 10 ++++++---- fs/ubifs/file.c | 4 ++-- fs/ubifs/ubifs.h | 4 ++++ fs/ubifs/xattr.c | 4 ++-- 5 files changed, 23 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index f5afce5..a3978ba 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -551,6 +551,8 @@ int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req) ubifs_assert(req->new_ino_d <= UBIFS_MAX_INO_DATA); ubifs_assert(req->dirtied_ino <= 4); ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4); + ubifs_assert(!(req->new_ino_d & 7)); + ubifs_assert(!(req->dirtied_ino_d & 7)); data_growth = calc_data_growth(c, req); dd_growth = calc_dd_growth(c, req); @@ -632,6 +634,8 @@ void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req) ubifs_assert(req->new_ino_d <= UBIFS_MAX_INO_DATA); ubifs_assert(req->dirtied_ino <= 4); ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4); + ubifs_assert(!(req->new_ino_d & 7)); + ubifs_assert(!(req->dirtied_ino_d & 7)); if (!req->recalculate) { ubifs_assert(req->idx_growth >= 0); ubifs_assert(req->data_growth >= 0); @@ -659,7 +663,11 @@ void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req) ubifs_assert(c->budg_idx_growth >= 0); ubifs_assert(c->budg_data_growth >= 0); + ubifs_assert(c->budg_dd_growth >= 0); ubifs_assert(c->min_idx_lebs < c->main_lebs); + ubifs_assert(!(c->budg_idx_growth & 7)); + ubifs_assert(!(c->budg_data_growth & 7)); + ubifs_assert(!(c->budg_dd_growth & 7)); spin_unlock(&c->space_lock); } @@ -701,7 +709,7 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c, struct ubifs_budget_req req; memset(&req, 0, sizeof(struct ubifs_budget_req)); - req.dd_growth = c->inode_budget + ui->data_len; + req.dd_growth = c->inode_budget + ALIGN(ui->data_len, 8); ubifs_release_budget(c, &req); } diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index a79e850..eba3a8a 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -525,7 +525,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, struct ubifs_inode *dir_ui = ubifs_inode(dir); int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 2, - .dirtied_ino_d = ui->data_len }; + .dirtied_ino_d = ALIGN(ui->data_len, 8) }; /* * Budget request settings: new direntry, changing the target inode, @@ -788,7 +788,8 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry, int sz_change = CALC_DENT_SIZE(dentry->d_name.len); int err, devlen = 0; struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, - .new_ino_d = devlen, .dirtied_ino = 1 }; + .new_ino_d = ALIGN(devlen, 8), + .dirtied_ino = 1 }; /* * Budget request settings: new inode, new direntry and changing parent @@ -862,7 +863,8 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry, int err, len = strlen(symname); int sz_change = CALC_DENT_SIZE(dentry->d_name.len); struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, - .new_ino_d = len, .dirtied_ino = 1 }; + .new_ino_d = ALIGN(len, 8), + .dirtied_ino = 1 }; /* * Budget request settings: new inode, new direntry and changing parent @@ -1011,7 +1013,7 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1, .dirtied_ino = 3 }; struct ubifs_budget_req ino_req = { .dirtied_ino = 1, - .dirtied_ino_d = old_inode_ui->data_len }; + .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) }; struct timespec time; /* diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 01598f2..9fecab2 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -890,7 +890,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode, loff_t new_size = attr->ia_size; struct ubifs_inode *ui = ubifs_inode(inode); struct ubifs_budget_req req = { .dirtied_ino = 1, - .dirtied_ino_d = ui->data_len }; + .dirtied_ino_d = ALIGN(ui->data_len, 8) }; err = ubifs_budget_space(c, &req); if (err) @@ -1052,7 +1052,7 @@ static int update_mctime(struct ubifs_info *c, struct inode *inode) if (mctime_update_needed(inode, &now)) { int err, release; struct ubifs_budget_req req = { .dirtied_ino = 1, - .dirtied_ino_d = ui->data_len }; + .dirtied_ino_d = ALIGN(ui->data_len, 8) }; err = ubifs_budget_space(c, &req); if (err) diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 565dca2..73ca8a0 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -808,6 +808,10 @@ struct ubifs_compressor { * An inode may contain 4KiB of data at max., thus the widths of @new_ino_d * is 13 bits, and @dirtied_ino_d - 15, because up to 4 inodes may be made * dirty by the re-name operation. + * + * Note, UBIFS aligns node lengths to 8-bytes boundary, so the requester has to + * make sure the amount of inode data which contribute to @new_ino_d and + * @dirtied_ino_d fields are aligned. */ struct ubifs_budget_req { unsigned int fast:1; diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index 1388a07..39e831d 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -103,8 +103,8 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, struct inode *inode; struct ubifs_inode *ui, *host_ui = ubifs_inode(host); struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, - .new_ino_d = size, .dirtied_ino = 1, - .dirtied_ino_d = host_ui->data_len}; + .new_ino_d = size, .dirtied_ino = 1, + .dirtied_ino_d = ALIGN(host_ui->data_len, 8)}; if (host_ui->xattr_cnt >= MAX_XATTRS_PER_INODE) return -ENOSPC; -- cgit v1.1 From 1de9415906bccab51fb74c6adf575948610f0909 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 25 Jul 2008 12:58:38 +0300 Subject: UBIFS: print pid in dump function Useful when something fails and there are many processes racing. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 0adfb29..b9cb774 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -568,8 +568,8 @@ void dbg_dump_budget_req(const struct ubifs_budget_req *req) void dbg_dump_lstats(const struct ubifs_lp_stats *lst) { spin_lock(&dbg_lock); - printk(KERN_DEBUG "Lprops statistics: empty_lebs %d, idx_lebs %d\n", - lst->empty_lebs, lst->idx_lebs); + printk(KERN_DEBUG "(pid %d) Lprops statistics: empty_lebs %d, " + "idx_lebs %d\n", current->pid, lst->empty_lebs, lst->idx_lebs); printk(KERN_DEBUG "\ttaken_empty_lebs %d, total_free %lld, " "total_dirty %lld\n", lst->taken_empty_lebs, lst->total_free, lst->total_dirty); @@ -587,8 +587,8 @@ void dbg_dump_budg(struct ubifs_info *c) struct ubifs_gced_idx_leb *idx_gc; spin_lock(&dbg_lock); - printk(KERN_DEBUG "Budgeting info: budg_data_growth %lld, " - "budg_dd_growth %lld, budg_idx_growth %lld\n", + printk(KERN_DEBUG "(pid %d) Budgeting info: budg_data_growth %lld, " + "budg_dd_growth %lld, budg_idx_growth %lld\n", current->pid, c->budg_data_growth, c->budg_dd_growth, c->budg_idx_growth); printk(KERN_DEBUG "\tdata budget sum %lld, total budget sum %lld, " "freeable_cnt %d\n", c->budg_data_growth + c->budg_dd_growth, @@ -634,7 +634,7 @@ void dbg_dump_lprops(struct ubifs_info *c) struct ubifs_lprops lp; struct ubifs_lp_stats lst; - printk(KERN_DEBUG "Dumping LEB properties\n"); + printk(KERN_DEBUG "(pid %d) Dumping LEB properties\n", current->pid); ubifs_get_lp_stats(c, &lst); dbg_dump_lstats(&lst); @@ -655,7 +655,7 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum) if (dbg_failure_mode) return; - printk(KERN_DEBUG "Dumping LEB %d\n", lnum); + printk(KERN_DEBUG "(pid %d) Dumping LEB %d\n", current->pid, lnum); sleb = ubifs_scan(c, lnum, 0, c->dbg_buf); if (IS_ERR(sleb)) { @@ -720,8 +720,8 @@ void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat) { int i; - printk(KERN_DEBUG "Dumping heap cat %d (%d elements)\n", - cat, heap->cnt); + printk(KERN_DEBUG "(pid %d) Dumping heap cat %d (%d elements)\n", + current->pid, cat, heap->cnt); for (i = 0; i < heap->cnt; i++) { struct ubifs_lprops *lprops = heap->arr[i]; @@ -736,7 +736,7 @@ void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, { int i; - printk(KERN_DEBUG "Dumping pnode:\n"); + printk(KERN_DEBUG "(pid %d) Dumping pnode:\n", current->pid); printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n", (size_t)pnode, (size_t)parent, (size_t)pnode->cnext); printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n", @@ -755,7 +755,7 @@ void dbg_dump_tnc(struct ubifs_info *c) int level; printk(KERN_DEBUG "\n"); - printk(KERN_DEBUG "Dumping the TNC tree\n"); + printk(KERN_DEBUG "(pid %d) Dumping the TNC tree\n", current->pid); znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL); level = znode->level; printk(KERN_DEBUG "== Level %d ==\n", level); -- cgit v1.1 From b364b41aeb0289be402be83eebca92eb90bfcb8b Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 25 Jul 2008 14:38:51 +0300 Subject: UBIFS: reserve more space for index At the moment UBIFS reserves twice old index size space for the index. But this is not enough in some cases, because if the indexing node are very fragmented and there are many small gaps, while the dirty index has big znodes - in-the-gaps method would fail. Thus, reserve trise as more, in which case we are guaranteed that we can commit in any case. Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 8 ++++---- fs/ubifs/find.c | 9 +++++++-- fs/ubifs/misc.h | 2 +- fs/ubifs/ubifs-media.h | 4 ++-- 4 files changed, 14 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index a3978ba..323d83a 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -263,8 +263,8 @@ int ubifs_calc_min_idx_lebs(struct ubifs_info *c) idx_size = c->old_idx_sz + c->budg_idx_growth + c->budg_uncommitted_idx; - /* And make sure we have twice the index size of space reserved */ - idx_size <<= 1; + /* And make sure we have trice the index size of space reserved */ + idx_size = idx_size + (idx_size << 1); /* * We do not maintain 'old_idx_size' as 'old_idx_lebs'/'old_idx_bytes' @@ -388,11 +388,11 @@ static int can_use_rp(struct ubifs_info *c) * This function makes sure UBIFS has enough free eraseblocks for index growth * and data. * - * When budgeting index space, UBIFS reserves twice as more LEBs as the index + * When budgeting index space, UBIFS reserves trice as more LEBs as the index * would take if it was consolidated and written to the flash. This guarantees * that the "in-the-gaps" commit method always succeeds and UBIFS will always * be able to commit dirty index. So this function basically adds amount of - * budgeted index space to the size of the current index, multiplies this by 2, + * budgeted index space to the size of the current index, multiplies this by 3, * and makes sure this does not exceed the amount of free eraseblocks. * * Notes about @c->min_idx_lebs and @c->lst.idx_lebs variables: diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index 10394c5..c70c767 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -290,9 +290,14 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, idx_lp = idx_heap->arr[0]; sum = idx_lp->free + idx_lp->dirty; /* - * Since we reserve twice as more space for the index than it + * Since we reserve trice as more space for the index than it * actually takes, it does not make sense to pick indexing LEBs - * with less than half LEB of dirty space. + * with less than, say, half LEB of dirty space. May be half is + * not the optimal boundary - this should be tested and + * checked. This boundary should determine how much we use + * in-the-gaps to consolidate the index comparing to how much + * we use garbage collector to consolidate it. The "half" + * criteria just feels to be fine. */ if (sum < min_space || sum < c->half_leb_size) idx_lp = NULL; diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h index cd83ffc..87dabf9 100644 --- a/fs/ubifs/misc.h +++ b/fs/ubifs/misc.h @@ -308,7 +308,7 @@ static inline long long ubifs_reported_space(const struct ubifs_info *c, { int divisor, factor; - divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz << 1); + divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz * 3); factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ; do_div(free, divisor); diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index 0cc7da9..bd2121f 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h @@ -228,10 +228,10 @@ enum { /* Minimum number of orphan area logical eraseblocks */ #define UBIFS_MIN_ORPH_LEBS 1 /* - * Minimum number of main area logical eraseblocks (buds, 2 for the index, 1 + * Minimum number of main area logical eraseblocks (buds, 3 for the index, 1 * for GC, 1 for deletions, and at least 1 for committed data). */ -#define UBIFS_MIN_MAIN_LEBS (UBIFS_MIN_BUD_LEBS + 5) +#define UBIFS_MIN_MAIN_LEBS (UBIFS_MIN_BUD_LEBS + 6) /* Minimum number of logical eraseblocks */ #define UBIFS_MIN_LEB_CNT (UBIFS_SB_LEBS + UBIFS_MST_LEBS + \ -- cgit v1.1 From 0010f18afc5f8ba25e1d20e3165894c32a65af02 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 25 Jul 2008 16:39:44 +0300 Subject: UBIFS: minor tweaks in commit No functional changes, just lessen the amount of indentations. Signed-off-by: Artem Bityutskiy --- fs/ubifs/tnc_commit.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index 8117e65..8ac76b1 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c @@ -372,26 +372,25 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) written = layout_leb_in_gaps(c, p); if (written < 0) { err = written; - if (err == -ENOSPC) { - if (!dbg_force_in_the_gaps_enabled) { - /* - * Do not print scary warnings if the - * debugging option which forces - * in-the-gaps is enabled. - */ - ubifs_err("out of space"); - spin_lock(&c->space_lock); - dbg_dump_budg(c); - spin_unlock(&c->space_lock); - dbg_dump_lprops(c); - } - /* Try to commit anyway */ - err = 0; - break; + if (err != -ENOSPC) { + kfree(c->gap_lebs); + c->gap_lebs = NULL; + return err; } - kfree(c->gap_lebs); - c->gap_lebs = NULL; - return err; + if (!dbg_force_in_the_gaps_enabled) { + /* + * Do not print scary warnings if the debugging + * option which forces in-the-gaps is enabled. + */ + ubifs_err("out of space"); + spin_lock(&c->space_lock); + dbg_dump_budg(c); + spin_unlock(&c->space_lock); + dbg_dump_lprops(c); + } + /* Try to commit anyway */ + err = 0; + break; } p++; cnt -= written; -- cgit v1.1 From 22bc7fa8c5da09805edc6a6199ce81373b2c207d Mon Sep 17 00:00:00 2001 From: Zoltan Sogor Date: Mon, 28 Jul 2008 16:28:49 +0200 Subject: UBIFS: support splice_write Signed-off-by: Zoltan Sogor Signed-off-by: Artem Bityutskiy --- fs/ubifs/file.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 9fecab2..4071d1c 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -1271,6 +1271,7 @@ struct file_operations ubifs_file_operations = { .fsync = ubifs_fsync, .unlocked_ioctl = ubifs_ioctl, .splice_read = generic_file_splice_read, + .splice_write = generic_file_splice_write, #ifdef CONFIG_COMPAT .compat_ioctl = ubifs_compat_ioctl, #endif -- cgit v1.1 From 3a13252c6f3a029ac992a36910e945f361482797 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 30 Jul 2008 12:18:02 +0300 Subject: UBIFS: correct spelling of "thrice". Signed-off-by: Adrian Hunter --- fs/ubifs/budget.c | 4 ++-- fs/ubifs/find.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 323d83a..15409815 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -263,7 +263,7 @@ int ubifs_calc_min_idx_lebs(struct ubifs_info *c) idx_size = c->old_idx_sz + c->budg_idx_growth + c->budg_uncommitted_idx; - /* And make sure we have trice the index size of space reserved */ + /* And make sure we have thrice the index size of space reserved */ idx_size = idx_size + (idx_size << 1); /* @@ -388,7 +388,7 @@ static int can_use_rp(struct ubifs_info *c) * This function makes sure UBIFS has enough free eraseblocks for index growth * and data. * - * When budgeting index space, UBIFS reserves trice as more LEBs as the index + * When budgeting index space, UBIFS reserves thrice as many LEBs as the index * would take if it was consolidated and written to the flash. This guarantees * that the "in-the-gaps" commit method always succeeds and UBIFS will always * be able to commit dirty index. So this function basically adds amount of diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index c70c767..adee7b5 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -290,7 +290,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, idx_lp = idx_heap->arr[0]; sum = idx_lp->free + idx_lp->dirty; /* - * Since we reserve trice as more space for the index than it + * Since we reserve thrice as much space for the index than it * actually takes, it does not make sense to pick indexing LEBs * with less than, say, half LEB of dirty space. May be half is * not the optimal boundary - this should be tested and -- cgit v1.1 From 81ffa38e1558f54db190e2d11e7260ab09c4acf2 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 1 Aug 2008 15:35:08 +0300 Subject: UBIFS: always set i_generation to 0 UBIFS does not presently re-use inode numbers, so leaving i_generation zero is most appropriate for now. Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/dir.c | 1 - fs/ubifs/super.c | 2 -- fs/ubifs/ubifs.h | 4 +--- 3 files changed, 1 insertion(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index eba3a8a..0d1ab89 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -165,7 +165,6 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, } inode->i_ino = ++c->highest_inum; - inode->i_generation = ++c->vfs_gen; /* * The creation sequence number remains with this inode for its * lifetime. All nodes for this inode have a greater sequence number, diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 6cc4175..2c268a4 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -1671,7 +1670,6 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) INIT_LIST_HEAD(&c->orph_new); c->highest_inum = UBIFS_FIRST_INO; - get_random_bytes(&c->vfs_gen, sizeof(int)); c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; ubi_get_volume_info(ubi, &c->vi); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 73ca8a0..f2dd749 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -876,11 +876,10 @@ struct ubifs_mount_opts { * @bdi: backing device info object to make VFS happy and disable read-ahead * * @highest_inum: highest used inode number - * @vfs_gen: VFS inode generation counter * @max_sqnum: current global sequence number * @cmt_no: commit number of the last successfully completed commit, protected * by @commit_sem - * @cnt_lock: protects @highest_inum, @vfs_gen, and @max_sqnum counters + * @cnt_lock: protects @highest_inum and @max_sqnum counters * @fmt_version: UBIFS on-flash format version * @uuid: UUID from super block * @@ -1117,7 +1116,6 @@ struct ubifs_info { struct backing_dev_info bdi; ino_t highest_inum; - unsigned int vfs_gen; unsigned long long max_sqnum; unsigned long long cmt_no; spinlock_t cnt_lock; -- cgit v1.1 From 840dc6b891d521f18bf081bd5a32e4a1f8110abc Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 1 Aug 2008 18:13:37 +0300 Subject: UBIFS: improve arguments checking in debugging messages Use "if (0) printk()" construct in debugging print macros to make the debugging messages be checked even if debugging is off. This patch also removes some unneeded spaces and blank lines. Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.h | 143 +++++++++++++++++++++++++++---------------------------- 1 file changed, 69 insertions(+), 74 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 3c4f1e9..50315fc 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h @@ -27,7 +27,7 @@ #define UBIFS_DBG(op) op -#define ubifs_assert(expr) do { \ +#define ubifs_assert(expr) do { \ if (unlikely(!(expr))) { \ printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \ __func__, __LINE__, current->pid); \ @@ -73,50 +73,50 @@ const char *dbg_key_str1(const struct ubifs_info *c, const union ubifs_key *key); /* - * DBGKEY macros require dbg_lock to be held, which it is in the dbg message + * DBGKEY macros require @dbg_lock to be held, which it is in the dbg message * macros. */ #define DBGKEY(key) dbg_key_str0(c, (key)) #define DBGKEY1(key) dbg_key_str1(c, (key)) /* General messages */ -#define dbg_gen(fmt, ...) dbg_do_msg(UBIFS_MSG_GEN, fmt, ##__VA_ARGS__) +#define dbg_gen(fmt, ...) dbg_do_msg(UBIFS_MSG_GEN, fmt, ##__VA_ARGS__) /* Additional journal messages */ -#define dbg_jnl(fmt, ...) dbg_do_msg(UBIFS_MSG_JNL, fmt, ##__VA_ARGS__) +#define dbg_jnl(fmt, ...) dbg_do_msg(UBIFS_MSG_JNL, fmt, ##__VA_ARGS__) /* Additional TNC messages */ -#define dbg_tnc(fmt, ...) dbg_do_msg(UBIFS_MSG_TNC, fmt, ##__VA_ARGS__) +#define dbg_tnc(fmt, ...) dbg_do_msg(UBIFS_MSG_TNC, fmt, ##__VA_ARGS__) /* Additional lprops messages */ -#define dbg_lp(fmt, ...) dbg_do_msg(UBIFS_MSG_LP, fmt, ##__VA_ARGS__) +#define dbg_lp(fmt, ...) dbg_do_msg(UBIFS_MSG_LP, fmt, ##__VA_ARGS__) /* Additional LEB find messages */ -#define dbg_find(fmt, ...) dbg_do_msg(UBIFS_MSG_FIND, fmt, ##__VA_ARGS__) +#define dbg_find(fmt, ...) dbg_do_msg(UBIFS_MSG_FIND, fmt, ##__VA_ARGS__) /* Additional mount messages */ -#define dbg_mnt(fmt, ...) dbg_do_msg(UBIFS_MSG_MNT, fmt, ##__VA_ARGS__) +#define dbg_mnt(fmt, ...) dbg_do_msg(UBIFS_MSG_MNT, fmt, ##__VA_ARGS__) /* Additional I/O messages */ -#define dbg_io(fmt, ...) dbg_do_msg(UBIFS_MSG_IO, fmt, ##__VA_ARGS__) +#define dbg_io(fmt, ...) dbg_do_msg(UBIFS_MSG_IO, fmt, ##__VA_ARGS__) /* Additional commit messages */ -#define dbg_cmt(fmt, ...) dbg_do_msg(UBIFS_MSG_CMT, fmt, ##__VA_ARGS__) +#define dbg_cmt(fmt, ...) dbg_do_msg(UBIFS_MSG_CMT, fmt, ##__VA_ARGS__) /* Additional budgeting messages */ -#define dbg_budg(fmt, ...) dbg_do_msg(UBIFS_MSG_BUDG, fmt, ##__VA_ARGS__) +#define dbg_budg(fmt, ...) dbg_do_msg(UBIFS_MSG_BUDG, fmt, ##__VA_ARGS__) /* Additional log messages */ -#define dbg_log(fmt, ...) dbg_do_msg(UBIFS_MSG_LOG, fmt, ##__VA_ARGS__) +#define dbg_log(fmt, ...) dbg_do_msg(UBIFS_MSG_LOG, fmt, ##__VA_ARGS__) /* Additional gc messages */ -#define dbg_gc(fmt, ...) dbg_do_msg(UBIFS_MSG_GC, fmt, ##__VA_ARGS__) +#define dbg_gc(fmt, ...) dbg_do_msg(UBIFS_MSG_GC, fmt, ##__VA_ARGS__) /* Additional scan messages */ -#define dbg_scan(fmt, ...) dbg_do_msg(UBIFS_MSG_SCAN, fmt, ##__VA_ARGS__) +#define dbg_scan(fmt, ...) dbg_do_msg(UBIFS_MSG_SCAN, fmt, ##__VA_ARGS__) /* Additional recovery messages */ -#define dbg_rcvry(fmt, ...) dbg_do_msg(UBIFS_MSG_RCVRY, fmt, ##__VA_ARGS__) +#define dbg_rcvry(fmt, ...) dbg_do_msg(UBIFS_MSG_RCVRY, fmt, ##__VA_ARGS__) /* * Debugging message type flags (must match msg_type_names in debug.c). @@ -239,34 +239,23 @@ typedef int (*dbg_leaf_callback)(struct ubifs_info *c, struct ubifs_zbranch *zbr, void *priv); typedef int (*dbg_znode_callback)(struct ubifs_info *c, struct ubifs_znode *znode, void *priv); - int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb, dbg_znode_callback znode_cb, void *priv); /* Checking functions */ int dbg_check_lprops(struct ubifs_info *c); - int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot); int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot); - int dbg_check_cats(struct ubifs_info *c); - int dbg_check_ltab(struct ubifs_info *c); - int dbg_check_synced_i_size(struct inode *inode); - int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir); - int dbg_check_tnc(struct ubifs_info *c, int extra); - int dbg_check_idx_size(struct ubifs_info *c, long long idx_size); - int dbg_check_filesystem(struct ubifs_info *c); - void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat, int add_pos); - int dbg_check_lprops(struct ubifs_info *c); int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode, int row, int col); @@ -329,71 +318,77 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum, #else /* !CONFIG_UBIFS_FS_DEBUG */ #define UBIFS_DBG(op) -#define ubifs_assert(expr) ({}) -#define ubifs_assert_cmt_locked(c) + +/* Use "if (0)" to make compiler check arguments even if debugging is off */ +#define ubifs_assert(expr) do { \ + if (0 && (expr)) \ + printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \ + __func__, __LINE__, current->pid); \ +} while (0) + +#define dbg_err(fmt, ...) do { \ + if (0) \ + ubifs_err(fmt, ##__VA_ARGS__); \ +} while (0) + +#define dbg_msg(fmt, ...) do { \ + if (0) \ + printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", \ + current->pid, __func__, ##__VA_ARGS__); \ +} while (0) + #define dbg_dump_stack() -#define dbg_err(fmt, ...) ({}) -#define dbg_msg(fmt, ...) ({}) -#define dbg_key(c, key, fmt, ...) ({}) - -#define dbg_gen(fmt, ...) ({}) -#define dbg_jnl(fmt, ...) ({}) -#define dbg_tnc(fmt, ...) ({}) -#define dbg_lp(fmt, ...) ({}) -#define dbg_find(fmt, ...) ({}) -#define dbg_mnt(fmt, ...) ({}) -#define dbg_io(fmt, ...) ({}) -#define dbg_cmt(fmt, ...) ({}) -#define dbg_budg(fmt, ...) ({}) -#define dbg_log(fmt, ...) ({}) -#define dbg_gc(fmt, ...) ({}) -#define dbg_scan(fmt, ...) ({}) -#define dbg_rcvry(fmt, ...) ({}) - -#define dbg_ntype(type) "" -#define dbg_cstate(cmt_state) "" -#define dbg_get_key_dump(c, key) ({}) -#define dbg_dump_inode(c, inode) ({}) -#define dbg_dump_node(c, node) ({}) -#define dbg_dump_budget_req(req) ({}) -#define dbg_dump_lstats(lst) ({}) -#define dbg_dump_budg(c) ({}) -#define dbg_dump_lprop(c, lp) ({}) -#define dbg_dump_lprops(c) ({}) -#define dbg_dump_leb(c, lnum) ({}) -#define dbg_dump_znode(c, znode) ({}) -#define dbg_dump_heap(c, heap, cat) ({}) -#define dbg_dump_pnode(c, pnode, parent, iip) ({}) -#define dbg_dump_tnc(c) ({}) -#define dbg_dump_index(c) ({}) +#define ubifs_assert_cmt_locked(c) -#define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0 +#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_jnl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_tnc(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_lp(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_find(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_mnt(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_cmt(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_budg(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_log(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_gc(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_scan(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) +#define dbg_rcvry(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) + +#define DBGKEY(key) ((char *)(key)) +#define DBGKEY1(key) ((char *)(key)) + +#define dbg_ntype(type) "" +#define dbg_cstate(cmt_state) "" +#define dbg_get_key_dump(c, key) ({}) +#define dbg_dump_inode(c, inode) ({}) +#define dbg_dump_node(c, node) ({}) +#define dbg_dump_budget_req(req) ({}) +#define dbg_dump_lstats(lst) ({}) +#define dbg_dump_budg(c) ({}) +#define dbg_dump_lprop(c, lp) ({}) +#define dbg_dump_lprops(c) ({}) +#define dbg_dump_leb(c, lnum) ({}) +#define dbg_dump_znode(c, znode) ({}) +#define dbg_dump_heap(c, heap, cat) ({}) +#define dbg_dump_pnode(c, pnode, parent, iip) ({}) +#define dbg_dump_tnc(c) ({}) +#define dbg_dump_index(c) ({}) +#define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0 #define dbg_old_index_check_init(c, zroot) 0 #define dbg_check_old_index(c, zroot) 0 - #define dbg_check_cats(c) 0 - #define dbg_check_ltab(c) 0 - #define dbg_check_synced_i_size(inode) 0 - #define dbg_check_dir_size(c, dir) 0 - #define dbg_check_tnc(c, x) 0 - #define dbg_check_idx_size(c, idx_size) 0 - #define dbg_check_filesystem(c) 0 - #define dbg_check_heap(c, heap, cat, add_pos) ({}) - #define dbg_check_lprops(c) 0 #define dbg_check_lpt_nodes(c, cnode, row, col) 0 - #define dbg_force_in_the_gaps_enabled 0 #define dbg_force_in_the_gaps() 0 - #define dbg_failure_mode 0 #define dbg_failure_mode_registration(c) ({}) #define dbg_failure_mode_deregistration(c) ({}) -- cgit v1.1 From 5acd6ff8ac09eb71f3aef2ccccefab658be8aff4 Mon Sep 17 00:00:00 2001 From: Zoltan Sogor Date: Tue, 12 Aug 2008 13:54:54 +0300 Subject: UBIFS: fix budgeting request alignment in xattr code Data length has to be aligned in the budgeting request. Code in xattr.c did not do this. Signed-off-by: Zoltan Sogor Signed-off-by: Artem Bityutskiy --- fs/ubifs/xattr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index 39e831d..6f493de 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -103,8 +103,8 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, struct inode *inode; struct ubifs_inode *ui, *host_ui = ubifs_inode(host); struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, - .new_ino_d = size, .dirtied_ino = 1, - .dirtied_ino_d = ALIGN(host_ui->data_len, 8)}; + .new_ino_d = ALIGN(size, 8), .dirtied_ino = 1, + .dirtied_ino_d = ALIGN(host_ui->data_len, 8) }; if (host_ui->xattr_cnt >= MAX_XATTRS_PER_INODE) return -ENOSPC; @@ -200,7 +200,7 @@ static int change_xattr(struct ubifs_info *c, struct inode *host, struct ubifs_inode *host_ui = ubifs_inode(host); struct ubifs_inode *ui = ubifs_inode(inode); struct ubifs_budget_req req = { .dirtied_ino = 2, - .dirtied_ino_d = size + host_ui->data_len }; + .dirtied_ino_d = ALIGN(size, 8) + ALIGN(host_ui->data_len, 8) }; ubifs_assert(ui->data_len == inode->i_size); err = ubifs_budget_space(c, &req); @@ -497,8 +497,8 @@ static int remove_xattr(struct ubifs_info *c, struct inode *host, int err; struct ubifs_inode *host_ui = ubifs_inode(host); struct ubifs_inode *ui = ubifs_inode(inode); - struct ubifs_budget_req req = { .dirtied_ino = 1, .mod_dent = 1, - .dirtied_ino_d = host_ui->data_len }; + struct ubifs_budget_req req = { .dirtied_ino = 2, .mod_dent = 1, + .dirtied_ino_d = ALIGN(host_ui->data_len, 8) }; ubifs_assert(ui->data_len == inode->i_size); -- cgit v1.1 From 0a883a05c54b326bcf99c0902af28dae0386be0a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 13 Aug 2008 14:13:26 +0300 Subject: UBIFS: few commentary fixes Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 8 ++++---- fs/ubifs/ubifs.h | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 2c268a4..f71e6b8 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -148,7 +148,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum) if (err) goto out_invalid; - /* Disable readahead */ + /* Disable read-ahead */ inode->i_mapping->backing_dev_info = &c->bdi; switch (inode->i_mode & S_IFMT) { @@ -344,7 +344,7 @@ static void ubifs_delete_inode(struct inode *inode) if (err) /* * Worst case we have a lost orphan inode wasting space, so a - * simple error message is ok here. + * simple error message is OK here. */ ubifs_err("can't delete inode %lu, error %d", inode->i_ino, err); @@ -1683,10 +1683,10 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) } /* - * UBIFS provids 'backing_dev_info' in order to disable readahead. For + * UBIFS provides 'backing_dev_info' in order to disable read-ahead. For * UBIFS, I/O is not deferred, it is done immediately in readpage, * which means the user would have to wait not just for their own I/O - * but the readahead I/O as well i.e. completely pointless. + * but the read-ahead I/O as well i.e. completely pointless. * * Read-ahead will be disabled because @c->bdi.ra_pages is 0. */ diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index f2dd749..d7f706f 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -20,8 +20,6 @@ * Adrian Hunter */ -/* Implementation version 0.7 */ - #ifndef __UBIFS_H__ #define __UBIFS_H__ -- cgit v1.1 From 720b499c806200d06f4f22c668d46db784117089 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 13 Aug 2008 16:16:31 +0300 Subject: UBIFS: remove unneeded check Commit d70b67c8bc72ee23b55381bd6a884f4796692f77 fixed VFS and it never calls FS lookup function in deleted directories now. We may remove corresponding UBIFS check. Signed-off-by: Artem Bityutskiy --- fs/ubifs/dir.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 0d1ab89..5c96f1f 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -219,15 +219,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name); if (err) { - /* - * Do not hash the direntry if parent 'i_nlink' is zero, because - * this has side-effects - '->delete_inode()' call will not be - * called for the parent orphan inode, because 'd_count' of its - * direntry will stay 1 (it'll be negative direntry I guess) - * and prevent 'iput_final()' until the dentry is destroyed due - * to unmount or memory pressure. - */ - if (err == -ENOENT && dir->i_nlink != 0) { + if (err == -ENOENT) { dbg_gen("not found"); goto done; } -- cgit v1.1 From cb980d9a3ec3d39e30e0a4c473df528c09e0dcf3 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 29 Jul 2008 15:21:19 -0500 Subject: dlm: add missing kfrees A couple of unlikely error conditions were missing a kfree on the error exit path. Reported-by: Juha Leppanen Signed-off-by: David Teigland --- fs/dlm/user.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 929e48ae7..34f14a1 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -527,8 +527,10 @@ static ssize_t device_write(struct file *file, const char __user *buf, k32buf = (struct dlm_write_request32 *)kbuf; kbuf = kmalloc(count + 1 + (sizeof(struct dlm_write_request) - sizeof(struct dlm_write_request32)), GFP_KERNEL); - if (!kbuf) + if (!kbuf) { + kfree(k32buf); return -ENOMEM; + } if (proc) set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags); @@ -539,8 +541,10 @@ static ssize_t device_write(struct file *file, const char __user *buf, /* do we really need this? can a write happen after a close? */ if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) && - (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))) - return -EINVAL; + (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))) { + error = -EINVAL; + goto out_free; + } sigfillset(&allsigs); sigprocmask(SIG_BLOCK, &allsigs, &tmpsig); -- cgit v1.1 From 51409340d240dabe66adb49f645588c3a802d055 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Thu, 31 Jul 2008 09:31:53 -0500 Subject: dlm: rename structs Add a dlm_ prefix to the struct names in config.c. This resolves a conflict with struct node in particular, when include/linux/node.h happens to be included. Reported-by: Andrew Morton Signed-off-by: David Teigland --- fs/dlm/config.c | 203 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 107 insertions(+), 96 deletions(-) (limited to 'fs') diff --git a/fs/dlm/config.c b/fs/dlm/config.c index c4e7d72..89d2fb7 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. ** ** This copyrighted material is made available to anyone wishing to use, ** modify, copy, or redistribute it subject to the terms and conditions @@ -30,16 +30,16 @@ static struct config_group *space_list; static struct config_group *comm_list; -static struct comm *local_comm; +static struct dlm_comm *local_comm; -struct clusters; -struct cluster; -struct spaces; -struct space; -struct comms; -struct comm; -struct nodes; -struct node; +struct dlm_clusters; +struct dlm_cluster; +struct dlm_spaces; +struct dlm_space; +struct dlm_comms; +struct dlm_comm; +struct dlm_nodes; +struct dlm_node; static struct config_group *make_cluster(struct config_group *, const char *); static void drop_cluster(struct config_group *, struct config_item *); @@ -68,17 +68,22 @@ static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, static ssize_t store_node(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len); -static ssize_t comm_nodeid_read(struct comm *cm, char *buf); -static ssize_t comm_nodeid_write(struct comm *cm, const char *buf, size_t len); -static ssize_t comm_local_read(struct comm *cm, char *buf); -static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len); -static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len); -static ssize_t node_nodeid_read(struct node *nd, char *buf); -static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len); -static ssize_t node_weight_read(struct node *nd, char *buf); -static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len); - -struct cluster { +static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf); +static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf, + size_t len); +static ssize_t comm_local_read(struct dlm_comm *cm, char *buf); +static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf, + size_t len); +static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, + size_t len); +static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf); +static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf, + size_t len); +static ssize_t node_weight_read(struct dlm_node *nd, char *buf); +static ssize_t node_weight_write(struct dlm_node *nd, const char *buf, + size_t len); + +struct dlm_cluster { struct config_group group; unsigned int cl_tcp_port; unsigned int cl_buffer_size; @@ -109,11 +114,11 @@ enum { struct cluster_attribute { struct configfs_attribute attr; - ssize_t (*show)(struct cluster *, char *); - ssize_t (*store)(struct cluster *, const char *, size_t); + ssize_t (*show)(struct dlm_cluster *, char *); + ssize_t (*store)(struct dlm_cluster *, const char *, size_t); }; -static ssize_t cluster_set(struct cluster *cl, unsigned int *cl_field, +static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field, int *info_field, int check_zero, const char *buf, size_t len) { @@ -134,12 +139,12 @@ static ssize_t cluster_set(struct cluster *cl, unsigned int *cl_field, } #define CLUSTER_ATTR(name, check_zero) \ -static ssize_t name##_write(struct cluster *cl, const char *buf, size_t len) \ +static ssize_t name##_write(struct dlm_cluster *cl, const char *buf, size_t len) \ { \ return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name, \ check_zero, buf, len); \ } \ -static ssize_t name##_read(struct cluster *cl, char *buf) \ +static ssize_t name##_read(struct dlm_cluster *cl, char *buf) \ { \ return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name); \ } \ @@ -181,8 +186,8 @@ enum { struct comm_attribute { struct configfs_attribute attr; - ssize_t (*show)(struct comm *, char *); - ssize_t (*store)(struct comm *, const char *, size_t); + ssize_t (*show)(struct dlm_comm *, char *); + ssize_t (*store)(struct dlm_comm *, const char *, size_t); }; static struct comm_attribute comm_attr_nodeid = { @@ -222,8 +227,8 @@ enum { struct node_attribute { struct configfs_attribute attr; - ssize_t (*show)(struct node *, char *); - ssize_t (*store)(struct node *, const char *, size_t); + ssize_t (*show)(struct dlm_node *, char *); + ssize_t (*store)(struct dlm_node *, const char *, size_t); }; static struct node_attribute node_attr_nodeid = { @@ -248,26 +253,26 @@ static struct configfs_attribute *node_attrs[] = { NULL, }; -struct clusters { +struct dlm_clusters { struct configfs_subsystem subsys; }; -struct spaces { +struct dlm_spaces { struct config_group ss_group; }; -struct space { +struct dlm_space { struct config_group group; struct list_head members; struct mutex members_lock; int members_count; }; -struct comms { +struct dlm_comms { struct config_group cs_group; }; -struct comm { +struct dlm_comm { struct config_item item; int nodeid; int local; @@ -275,11 +280,11 @@ struct comm { struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT]; }; -struct nodes { +struct dlm_nodes { struct config_group ns_group; }; -struct node { +struct dlm_node { struct config_item item; struct list_head list; /* space->members */ int nodeid; @@ -372,38 +377,40 @@ static struct config_item_type node_type = { .ct_owner = THIS_MODULE, }; -static struct cluster *to_cluster(struct config_item *i) +static struct dlm_cluster *to_cluster(struct config_item *i) { - return i ? container_of(to_config_group(i), struct cluster, group):NULL; + return i ? container_of(to_config_group(i), struct dlm_cluster, group) : + NULL; } -static struct space *to_space(struct config_item *i) +static struct dlm_space *to_space(struct config_item *i) { - return i ? container_of(to_config_group(i), struct space, group) : NULL; + return i ? container_of(to_config_group(i), struct dlm_space, group) : + NULL; } -static struct comm *to_comm(struct config_item *i) +static struct dlm_comm *to_comm(struct config_item *i) { - return i ? container_of(i, struct comm, item) : NULL; + return i ? container_of(i, struct dlm_comm, item) : NULL; } -static struct node *to_node(struct config_item *i) +static struct dlm_node *to_node(struct config_item *i) { - return i ? container_of(i, struct node, item) : NULL; + return i ? container_of(i, struct dlm_node, item) : NULL; } static struct config_group *make_cluster(struct config_group *g, const char *name) { - struct cluster *cl = NULL; - struct spaces *sps = NULL; - struct comms *cms = NULL; + struct dlm_cluster *cl = NULL; + struct dlm_spaces *sps = NULL; + struct dlm_comms *cms = NULL; void *gps = NULL; - cl = kzalloc(sizeof(struct cluster), GFP_KERNEL); + cl = kzalloc(sizeof(struct dlm_cluster), GFP_KERNEL); gps = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); - sps = kzalloc(sizeof(struct spaces), GFP_KERNEL); - cms = kzalloc(sizeof(struct comms), GFP_KERNEL); + sps = kzalloc(sizeof(struct dlm_spaces), GFP_KERNEL); + cms = kzalloc(sizeof(struct dlm_comms), GFP_KERNEL); if (!cl || !gps || !sps || !cms) goto fail; @@ -443,7 +450,7 @@ static struct config_group *make_cluster(struct config_group *g, static void drop_cluster(struct config_group *g, struct config_item *i) { - struct cluster *cl = to_cluster(i); + struct dlm_cluster *cl = to_cluster(i); struct config_item *tmp; int j; @@ -461,20 +468,20 @@ static void drop_cluster(struct config_group *g, struct config_item *i) static void release_cluster(struct config_item *i) { - struct cluster *cl = to_cluster(i); + struct dlm_cluster *cl = to_cluster(i); kfree(cl->group.default_groups); kfree(cl); } static struct config_group *make_space(struct config_group *g, const char *name) { - struct space *sp = NULL; - struct nodes *nds = NULL; + struct dlm_space *sp = NULL; + struct dlm_nodes *nds = NULL; void *gps = NULL; - sp = kzalloc(sizeof(struct space), GFP_KERNEL); + sp = kzalloc(sizeof(struct dlm_space), GFP_KERNEL); gps = kcalloc(2, sizeof(struct config_group *), GFP_KERNEL); - nds = kzalloc(sizeof(struct nodes), GFP_KERNEL); + nds = kzalloc(sizeof(struct dlm_nodes), GFP_KERNEL); if (!sp || !gps || !nds) goto fail; @@ -500,7 +507,7 @@ static struct config_group *make_space(struct config_group *g, const char *name) static void drop_space(struct config_group *g, struct config_item *i) { - struct space *sp = to_space(i); + struct dlm_space *sp = to_space(i); struct config_item *tmp; int j; @@ -517,16 +524,16 @@ static void drop_space(struct config_group *g, struct config_item *i) static void release_space(struct config_item *i) { - struct space *sp = to_space(i); + struct dlm_space *sp = to_space(i); kfree(sp->group.default_groups); kfree(sp); } static struct config_item *make_comm(struct config_group *g, const char *name) { - struct comm *cm; + struct dlm_comm *cm; - cm = kzalloc(sizeof(struct comm), GFP_KERNEL); + cm = kzalloc(sizeof(struct dlm_comm), GFP_KERNEL); if (!cm) return ERR_PTR(-ENOMEM); @@ -539,7 +546,7 @@ static struct config_item *make_comm(struct config_group *g, const char *name) static void drop_comm(struct config_group *g, struct config_item *i) { - struct comm *cm = to_comm(i); + struct dlm_comm *cm = to_comm(i); if (local_comm == cm) local_comm = NULL; dlm_lowcomms_close(cm->nodeid); @@ -550,16 +557,16 @@ static void drop_comm(struct config_group *g, struct config_item *i) static void release_comm(struct config_item *i) { - struct comm *cm = to_comm(i); + struct dlm_comm *cm = to_comm(i); kfree(cm); } static struct config_item *make_node(struct config_group *g, const char *name) { - struct space *sp = to_space(g->cg_item.ci_parent); - struct node *nd; + struct dlm_space *sp = to_space(g->cg_item.ci_parent); + struct dlm_node *nd; - nd = kzalloc(sizeof(struct node), GFP_KERNEL); + nd = kzalloc(sizeof(struct dlm_node), GFP_KERNEL); if (!nd) return ERR_PTR(-ENOMEM); @@ -578,8 +585,8 @@ static struct config_item *make_node(struct config_group *g, const char *name) static void drop_node(struct config_group *g, struct config_item *i) { - struct space *sp = to_space(g->cg_item.ci_parent); - struct node *nd = to_node(i); + struct dlm_space *sp = to_space(g->cg_item.ci_parent); + struct dlm_node *nd = to_node(i); mutex_lock(&sp->members_lock); list_del(&nd->list); @@ -591,11 +598,11 @@ static void drop_node(struct config_group *g, struct config_item *i) static void release_node(struct config_item *i) { - struct node *nd = to_node(i); + struct dlm_node *nd = to_node(i); kfree(nd); } -static struct clusters clusters_root = { +static struct dlm_clusters clusters_root = { .subsys = { .su_group = { .cg_item = { @@ -625,7 +632,7 @@ void dlm_config_exit(void) static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a, char *buf) { - struct cluster *cl = to_cluster(i); + struct dlm_cluster *cl = to_cluster(i); struct cluster_attribute *cla = container_of(a, struct cluster_attribute, attr); return cla->show ? cla->show(cl, buf) : 0; @@ -635,7 +642,7 @@ static ssize_t store_cluster(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len) { - struct cluster *cl = to_cluster(i); + struct dlm_cluster *cl = to_cluster(i); struct cluster_attribute *cla = container_of(a, struct cluster_attribute, attr); return cla->store ? cla->store(cl, buf, len) : -EINVAL; @@ -644,7 +651,7 @@ static ssize_t store_cluster(struct config_item *i, static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, char *buf) { - struct comm *cm = to_comm(i); + struct dlm_comm *cm = to_comm(i); struct comm_attribute *cma = container_of(a, struct comm_attribute, attr); return cma->show ? cma->show(cm, buf) : 0; @@ -653,29 +660,31 @@ static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len) { - struct comm *cm = to_comm(i); + struct dlm_comm *cm = to_comm(i); struct comm_attribute *cma = container_of(a, struct comm_attribute, attr); return cma->store ? cma->store(cm, buf, len) : -EINVAL; } -static ssize_t comm_nodeid_read(struct comm *cm, char *buf) +static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf) { return sprintf(buf, "%d\n", cm->nodeid); } -static ssize_t comm_nodeid_write(struct comm *cm, const char *buf, size_t len) +static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf, + size_t len) { cm->nodeid = simple_strtol(buf, NULL, 0); return len; } -static ssize_t comm_local_read(struct comm *cm, char *buf) +static ssize_t comm_local_read(struct dlm_comm *cm, char *buf) { return sprintf(buf, "%d\n", cm->local); } -static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len) +static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf, + size_t len) { cm->local= simple_strtol(buf, NULL, 0); if (cm->local && !local_comm) @@ -683,7 +692,7 @@ static ssize_t comm_local_write(struct comm *cm, const char *buf, size_t len) return len; } -static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len) +static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len) { struct sockaddr_storage *addr; @@ -705,7 +714,7 @@ static ssize_t comm_addr_write(struct comm *cm, const char *buf, size_t len) static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, char *buf) { - struct node *nd = to_node(i); + struct dlm_node *nd = to_node(i); struct node_attribute *nda = container_of(a, struct node_attribute, attr); return nda->show ? nda->show(nd, buf) : 0; @@ -714,29 +723,31 @@ static ssize_t show_node(struct config_item *i, struct configfs_attribute *a, static ssize_t store_node(struct config_item *i, struct configfs_attribute *a, const char *buf, size_t len) { - struct node *nd = to_node(i); + struct dlm_node *nd = to_node(i); struct node_attribute *nda = container_of(a, struct node_attribute, attr); return nda->store ? nda->store(nd, buf, len) : -EINVAL; } -static ssize_t node_nodeid_read(struct node *nd, char *buf) +static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf) { return sprintf(buf, "%d\n", nd->nodeid); } -static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len) +static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf, + size_t len) { nd->nodeid = simple_strtol(buf, NULL, 0); return len; } -static ssize_t node_weight_read(struct node *nd, char *buf) +static ssize_t node_weight_read(struct dlm_node *nd, char *buf) { return sprintf(buf, "%d\n", nd->weight); } -static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len) +static ssize_t node_weight_write(struct dlm_node *nd, const char *buf, + size_t len) { nd->weight = simple_strtol(buf, NULL, 0); return len; @@ -746,7 +757,7 @@ static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len) * Functions for the dlm to get the info that's been configured */ -static struct space *get_space(char *name) +static struct dlm_space *get_space(char *name) { struct config_item *i; @@ -760,15 +771,15 @@ static struct space *get_space(char *name) return to_space(i); } -static void put_space(struct space *sp) +static void put_space(struct dlm_space *sp) { config_item_put(&sp->group.cg_item); } -static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr) +static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr) { struct config_item *i; - struct comm *cm = NULL; + struct dlm_comm *cm = NULL; int found = 0; if (!comm_list) @@ -801,7 +812,7 @@ static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr) return cm; } -static void put_comm(struct comm *cm) +static void put_comm(struct dlm_comm *cm) { config_item_put(&cm->item); } @@ -810,8 +821,8 @@ static void put_comm(struct comm *cm) int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, int **new_out, int *new_count_out) { - struct space *sp; - struct node *nd; + struct dlm_space *sp; + struct dlm_node *nd; int i = 0, rv = 0, ids_count = 0, new_count = 0; int *ids, *new; @@ -874,8 +885,8 @@ int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out, int dlm_node_weight(char *lsname, int nodeid) { - struct space *sp; - struct node *nd; + struct dlm_space *sp; + struct dlm_node *nd; int w = -EEXIST; sp = get_space(lsname); @@ -897,7 +908,7 @@ int dlm_node_weight(char *lsname, int nodeid) int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr) { - struct comm *cm = get_comm(nodeid, NULL); + struct dlm_comm *cm = get_comm(nodeid, NULL); if (!cm) return -EEXIST; if (!cm->addr_count) @@ -909,7 +920,7 @@ int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr) int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid) { - struct comm *cm = get_comm(0, addr); + struct dlm_comm *cm = get_comm(0, addr); if (!cm) return -EEXIST; *nodeid = cm->nodeid; -- cgit v1.1 From 9e2b2dc4133f65272a6d3c5dcb2ce63f8a87cae9 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 13 Aug 2008 16:20:04 +0100 Subject: CRED: Introduce credential access wrappers The patches that are intended to introduce copy-on-write credentials for 2.6.28 require abstraction of access to some fields of the task structure, particularly for the case of one task accessing another's credentials where RCU will have to be observed. Introduced here are trivial no-op versions of the desired accessors for current and other tasks so that other subsystems can start to be converted over more easily. Wrappers are introduced into a new header (linux/cred.h) for UID/GID, EUID/EGID, SUID/SGID, FSUID/FSGID, cap_effective and current's subscribed user_struct. These wrappers are macros because the ordering between header files mitigates against making them inline functions. linux/cred.h is #included from linux/sched.h. Further, XFS is modified such that it no longer defines and uses parameterised versions of current_fs[ug]id(), thus getting rid of the namespace collision otherwise incurred. Signed-off-by: David Howells Signed-off-by: James Morris --- fs/xfs/linux-2.6/xfs_linux.h | 2 -- fs/xfs/xfs_inode.c | 4 ++-- fs/xfs/xfs_vnodeops.c | 8 ++++---- 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 3b7c4ff..cc0f7b3 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -126,8 +126,6 @@ #define current_cpu() (raw_smp_processor_id()) #define current_pid() (current->pid) -#define current_fsuid(cred) (current->fsuid) -#define current_fsgid(cred) (current->fsgid) #define current_test_flags(f) (current->flags & (f)) #define current_set_flags_nested(sp, f) \ (*(sp) = current->flags, current->flags |= (f)) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 358511b..00e80df 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1081,8 +1081,8 @@ xfs_ialloc( ip->i_d.di_onlink = 0; ip->i_d.di_nlink = nlink; ASSERT(ip->i_d.di_nlink == nlink); - ip->i_d.di_uid = current_fsuid(cr); - ip->i_d.di_gid = current_fsgid(cr); + ip->i_d.di_uid = current_fsuid(); + ip->i_d.di_gid = current_fsgid(); ip->i_d.di_projid = prid; memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 588bb4a..aa238c8 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -182,7 +182,7 @@ xfs_setattr( xfs_ilock(ip, lock_flags); /* boolean: are we the file owner? */ - file_owner = (current_fsuid(credp) == ip->i_d.di_uid); + file_owner = (current_fsuid() == ip->i_d.di_uid); /* * Change various properties of a file. @@ -1533,7 +1533,7 @@ xfs_create( * Make sure that we have allocated dquot(s) on disk. */ error = XFS_QM_DQVOPALLOC(mp, dp, - current_fsuid(credp), current_fsgid(credp), prid, + current_fsuid(), current_fsgid(), prid, XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp); if (error) goto std_return; @@ -2269,7 +2269,7 @@ xfs_mkdir( * Make sure that we have allocated dquot(s) on disk. */ error = XFS_QM_DQVOPALLOC(mp, dp, - current_fsuid(credp), current_fsgid(credp), prid, + current_fsuid(), current_fsgid(), prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); if (error) goto std_return; @@ -2495,7 +2495,7 @@ xfs_symlink( * Make sure that we have allocated dquot(s) on disk. */ error = XFS_QM_DQVOPALLOC(mp, dp, - current_fsuid(credp), current_fsgid(credp), prid, + current_fsuid(), current_fsgid(), prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); if (error) goto std_return; -- cgit v1.1 From ad661334b8ae421154b121ee6ad3b56807adbf11 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 12 Aug 2008 14:14:40 +0000 Subject: [CIFS] mount of IPC$ breaks with iget patch In looking at network named pipe support on cifs, I noticed that Dave Howell's iget patch: iget: stop CIFS from using iget() and read_inode() broke mounts to IPC$ (the interprocess communication share), and don't handle the error case (when getting info on the root inode fails). Thanks to Gunter who noted a typo in a debug line in the original version of this patch. CC: David Howells CC: Gunter Kukkukk CC: Stable Kernel Signed-off-by: Steve French --- fs/cifs/inode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 28a2209..8482868 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -649,6 +649,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino) inode->i_fop = &simple_dir_operations; inode->i_uid = cifs_sb->mnt_uid; inode->i_gid = cifs_sb->mnt_gid; + } else if (rc) { _FreeXid(xid); iget_failed(inode); return ERR_PTR(rc); -- cgit v1.1 From c78c7e35a4709b55d3126624662c8f6d7e3d1a5e Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 12 Aug 2008 16:30:12 +0300 Subject: UBIFS: xattr bugfixes Xattr code has not been tested for a while and there were serveral bugs. One of them is using wrong inode in 'ubifs_jnl_change_xattr()'. The other is a deadlock in 'ubifs_setxattr()': the i_mutex is locked in 'cap_inode_need_killpriv()' path, so deadlock happens when 'ubifs_setxattr()' tries to lock it again. Thanks to Zoltan Sogor for finding these bugs. Signed-off-by: Artem Bityutskiy --- fs/ubifs/journal.c | 2 +- fs/ubifs/xattr.c | 44 +++++++++++++++++--------------------------- 2 files changed, 18 insertions(+), 28 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index acdae00..22993f8 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -1374,7 +1374,7 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode, const struct inode *host) { int err, len1, len2, aligned_len, aligned_len1, lnum, offs; - struct ubifs_inode *host_ui = ubifs_inode(inode); + struct ubifs_inode *host_ui = ubifs_inode(host); struct ubifs_ino_node *ino; union ubifs_key key; int sync = IS_DIRSYNC(host); diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index 6f493de..649bec7 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -61,7 +61,7 @@ /* * Limit the number of extended attributes per inode so that the total size - * (xattr_size) is guaranteeded to fit in an 'unsigned int'. + * (@xattr_size) is guaranteeded to fit in an 'unsigned int'. */ #define MAX_XATTRS_PER_INODE 65535 @@ -110,7 +110,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, return -ENOSPC; /* * Linux limits the maximum size of the extended attribute names list - * to %XATTR_LIST_MAX. This means we should not allow creating more* + * to %XATTR_LIST_MAX. This means we should not allow creating more * extended attributes if the name list becomes larger. This limitation * is artificial for UBIFS, though. */ @@ -128,7 +128,6 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, goto out_budg; } - mutex_lock(&host_ui->ui_mutex); /* Re-define all operations to be "nothing" */ inode->i_mapping->a_ops = &none_address_operations; inode->i_op = &none_inode_operations; @@ -141,23 +140,19 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, ui->data = kmalloc(size, GFP_NOFS); if (!ui->data) { err = -ENOMEM; - goto out_unlock; + goto out_free; } - memcpy(ui->data, value, size); + inode->i_size = ui->ui_size = size; + ui->data_len = size; + + mutex_lock(&host_ui->ui_mutex); host->i_ctime = ubifs_current_time(host); host_ui->xattr_cnt += 1; host_ui->xattr_size += CALC_DENT_SIZE(nm->len); host_ui->xattr_size += CALC_XATTR_BYTES(size); host_ui->xattr_names += nm->len; - /* - * We do not use i_size_write() because nobody can race with us as we - * are holding host @host->i_mutex - every xattr operation for this - * inode is serialized by it. - */ - inode->i_size = ui->ui_size = size; - ui->data_len = size; err = ubifs_jnl_update(c, host, nm, inode, 0, 1); if (err) goto out_cancel; @@ -172,8 +167,8 @@ out_cancel: host_ui->xattr_cnt -= 1; host_ui->xattr_size -= CALC_DENT_SIZE(nm->len); host_ui->xattr_size -= CALC_XATTR_BYTES(size); -out_unlock: mutex_unlock(&host_ui->ui_mutex); +out_free: make_bad_inode(inode); iput(inode); out_budg: @@ -207,22 +202,21 @@ static int change_xattr(struct ubifs_info *c, struct inode *host, if (err) return err; - mutex_lock(&host_ui->ui_mutex); - host->i_ctime = ubifs_current_time(host); - host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len); - host_ui->xattr_size += CALC_XATTR_BYTES(size); - kfree(ui->data); ui->data = kmalloc(size, GFP_NOFS); if (!ui->data) { err = -ENOMEM; - goto out_unlock; + goto out_free; } - memcpy(ui->data, value, size); inode->i_size = ui->ui_size = size; ui->data_len = size; + mutex_lock(&host_ui->ui_mutex); + host->i_ctime = ubifs_current_time(host); + host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len); + host_ui->xattr_size += CALC_XATTR_BYTES(size); + /* * It is important to write the host inode after the xattr inode * because if the host inode gets synchronized (via 'fsync()'), then @@ -240,9 +234,9 @@ static int change_xattr(struct ubifs_info *c, struct inode *host, out_cancel: host_ui->xattr_size -= CALC_XATTR_BYTES(size); host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len); - make_bad_inode(inode); -out_unlock: mutex_unlock(&host_ui->ui_mutex); + make_bad_inode(inode); +out_free: ubifs_release_budget(c, &req); return err; } @@ -312,6 +306,7 @@ int ubifs_setxattr(struct dentry *dentry, const char *name, dbg_gen("xattr '%s', host ino %lu ('%.*s'), size %zd", name, host->i_ino, dentry->d_name.len, dentry->d_name.name, size); + ubifs_assert(mutex_is_locked(&host->i_mutex)); if (size > UBIFS_MAX_INO_DATA) return -ERANGE; @@ -384,7 +379,6 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, if (!xent) return -ENOMEM; - mutex_lock(&host->i_mutex); xent_key_init(c, &key, host->i_ino, &nm); err = ubifs_tnc_lookup_nm(c, &key, xent, &nm); if (err) { @@ -419,7 +413,6 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, out_iput: iput(inode); out_unlock: - mutex_unlock(&host->i_mutex); kfree(xent); return err; } @@ -449,8 +442,6 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) return -ERANGE; lowest_xent_key(c, &key, host->i_ino); - - mutex_lock(&host->i_mutex); while (1) { int type; @@ -479,7 +470,6 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) pxent = xent; key_read(c, &xent->key, &key); } - mutex_unlock(&host->i_mutex); kfree(pxent); if (err != -ENOENT) { -- cgit v1.1 From 7d455e0030eeab820773e7786605be4d9e56a04b Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 15 Aug 2008 00:40:43 -0700 Subject: fs/inode.c: properly init address_space->writeback_index write_cache_pages() uses i_mapping->writeback_index to pick up where it left off the last time a given inode was found by pdflush or balance_dirty_pages (or anyone else who sets wbc->range_cyclic) alloc_inode() should set it to a sane value so that writeback doesn't start in the middle of a file. It is somewhat difficult to notice the bug since write_cache_pages will loop around to the start of the file and the elevator helps hide the resulting seeks. For whatever reason, Btrfs hits this often. Unpatched, untarring 30 copies of the linux kernel in series runs at 47MB/s on a single sata drive. With this fix, it jumps to 62MB/s. Signed-off-by: Chris Mason Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/inode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/inode.c b/fs/inode.c index b6726f6..0487ddb 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -166,6 +166,7 @@ static struct inode *alloc_inode(struct super_block *sb) mapping_set_gfp_mask(mapping, GFP_HIGHUSER_PAGECACHE); mapping->assoc_mapping = NULL; mapping->backing_dev_info = &default_backing_dev_info; + mapping->writeback_index = 0; /* * If the block_device provides a backing_dev_info for client -- cgit v1.1 From c963343a1150106819773e828c9b237ed977615b Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 15 Aug 2008 00:40:46 -0700 Subject: omfs: fix potential oops when directory size is corrupted Testing with a modified fsfuzzer reveals a couple of locations in omfs where filesystem variables are ultimately used as loop counters with insufficient sanity checking. In this case, dir->i_size is used to compute the number of buckets in the directory hash. If too large, readdir will overrun a buffer. Since it's an invariant that dir->i_size is equal to the sysblock size, and we already sanity check that, just use that value instead. This fixes the following oops: BUG: unable to handle kernel paging request at c978e004 IP: [] omfs_readdir+0x18e/0x32f Oops: 0000 [#1] PREEMPT DEBUG_PAGEALLOC Modules linked in: Pid: 4796, comm: ls Not tainted (2.6.27-rc2 #12) EIP: 0060:[] EFLAGS: 00010287 CPU: 0 EIP is at omfs_readdir+0x18e/0x32f EAX: c978d000 EBX: 00000000 ECX: cbfcfaf8 EDX: cb2cf100 ESI: 00001000 EDI: 00000800 EBP: cb2d3f68 ESP: cb2d3f0c DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068 Process ls (pid: 4796, ti=cb2d3000 task=cb175f40 task.ti=cb2d3000) Stack: 00000002 00000000 00000000 c018a820 cb2d3f94 cb2cf100 cbfb0000 ffffff10 cbfb3b80 cbfcfaf8 000001c9 00000a09 00000000 00000000 00000000 cbfcfbc8 c9697000 cbfb3b80 22222222 00001000 c08e6cd0 cb2cf100 cbfb3b80 cb2d3f88 Call Trace: [] ? filldir64+0x0/0xcd [] ? vfs_readdir+0x56/0x82 [] ? filldir64+0x0/0xcd [] ? sys_getdents64+0x5e/0xa0 [] ? sysenter_do_call+0x12/0x31 ======================= Code: 00 89 f0 89 f3 0f ac f8 14 81 e3 ff ff 0f 00 48 8d 14 c5 b8 01 00 00 89 45 cc 89 55 f0 e9 8c 01 00 00 8b 4d c8 8b 75 f0 8b 41 18 <8b> 54 30 04 8b 04 30 31 f6 89 5d dc 89 d1 8b 55 b8 0f c8 0f c9 Reported-by: Eric Sesterhenn Signed-off-by: Bob Copeland Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/omfs/inode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c index a95fe59..d29047b 100644 --- a/fs/omfs/inode.c +++ b/fs/omfs/inode.c @@ -232,8 +232,7 @@ struct inode *omfs_iget(struct super_block *sb, ino_t ino) inode->i_mode = S_IFDIR | (S_IRWXUGO & ~sbi->s_dmask); inode->i_op = &omfs_dir_inops; inode->i_fop = &omfs_dir_operations; - inode->i_size = be32_to_cpu(oi->i_head.h_body_size) + - sizeof(struct omfs_header); + inode->i_size = sbi->s_sys_blocksize; inc_nlink(inode); break; case OMFS_FILE: -- cgit v1.1 From 9419fc1c957d600093baaea247fef23cca3b4e93 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Fri, 15 Aug 2008 00:40:47 -0700 Subject: omfs: fix oops when file metadata is corrupted A fuzzed fileystem image failed with OMFS when the extent count was used in a loop without being checked against the max number of extents. It also provoked a signed division for an array index that was checked as if unsigned, leading to index by -1. omfsck will be updated to fix these cases, in the meantime bail out gracefully. Reported-by: Eric Sesterhenn Signed-off-by: Bob Copeland Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/omfs/bitmap.c | 5 +++-- fs/omfs/file.c | 33 ++++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/omfs/bitmap.c b/fs/omfs/bitmap.c index 697663b..e1c0ec0 100644 --- a/fs/omfs/bitmap.c +++ b/fs/omfs/bitmap.c @@ -92,7 +92,7 @@ int omfs_allocate_block(struct super_block *sb, u64 block) struct buffer_head *bh; struct omfs_sb_info *sbi = OMFS_SB(sb); int bits_per_entry = 8 * sb->s_blocksize; - int map, bit; + unsigned int map, bit; int ret = 0; u64 tmp; @@ -176,7 +176,8 @@ int omfs_clear_range(struct super_block *sb, u64 block, int count) struct omfs_sb_info *sbi = OMFS_SB(sb); int bits_per_entry = 8 * sb->s_blocksize; u64 tmp; - int map, bit, ret; + unsigned int map, bit; + int ret; tmp = block; bit = do_div(tmp, bits_per_entry); diff --git a/fs/omfs/file.c b/fs/omfs/file.c index 7e24990..834b233 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c @@ -26,6 +26,13 @@ static int omfs_sync_file(struct file *file, struct dentry *dentry, return err ? -EIO : 0; } +static u32 omfs_max_extents(struct omfs_sb_info *sbi, int offset) +{ + return (sbi->s_sys_blocksize - offset - + sizeof(struct omfs_extent)) / + sizeof(struct omfs_extent_entry) + 1; +} + void omfs_make_empty_table(struct buffer_head *bh, int offset) { struct omfs_extent *oe = (struct omfs_extent *) &bh->b_data[offset]; @@ -45,6 +52,7 @@ int omfs_shrink_inode(struct inode *inode) struct buffer_head *bh; u64 next, last; u32 extent_count; + u32 max_extents; int ret; /* traverse extent table, freeing each entry that is greater @@ -62,15 +70,18 @@ int omfs_shrink_inode(struct inode *inode) goto out; oe = (struct omfs_extent *)(&bh->b_data[OMFS_EXTENT_START]); + max_extents = omfs_max_extents(sbi, OMFS_EXTENT_START); for (;;) { - if (omfs_is_bad(sbi, (struct omfs_header *) bh->b_data, next)) { - brelse(bh); - goto out; - } + if (omfs_is_bad(sbi, (struct omfs_header *) bh->b_data, next)) + goto out_brelse; extent_count = be32_to_cpu(oe->e_extent_count); + + if (extent_count > max_extents) + goto out_brelse; + last = next; next = be64_to_cpu(oe->e_next); entry = &oe->e_entry; @@ -98,10 +109,14 @@ int omfs_shrink_inode(struct inode *inode) if (!bh) goto out; oe = (struct omfs_extent *) (&bh->b_data[OMFS_EXTENT_CONT]); + max_extents = omfs_max_extents(sbi, OMFS_EXTENT_CONT); } ret = 0; out: return ret; +out_brelse: + brelse(bh); + return ret; } static void omfs_truncate(struct inode *inode) @@ -154,9 +169,7 @@ static int omfs_grow_extent(struct inode *inode, struct omfs_extent *oe, goto out; } } - max_count = (sbi->s_sys_blocksize - OMFS_EXTENT_START - - sizeof(struct omfs_extent)) / - sizeof(struct omfs_extent_entry) + 1; + max_count = omfs_max_extents(sbi, OMFS_EXTENT_START); /* TODO: add a continuation block here */ if (be32_to_cpu(oe->e_extent_count) > max_count-1) @@ -225,6 +238,7 @@ static int omfs_get_block(struct inode *inode, sector_t block, sector_t next, offset; int ret; u64 new_block; + u32 max_extents; int extent_count; struct omfs_extent *oe; struct omfs_extent_entry *entry; @@ -238,6 +252,7 @@ static int omfs_get_block(struct inode *inode, sector_t block, goto out; oe = (struct omfs_extent *)(&bh->b_data[OMFS_EXTENT_START]); + max_extents = omfs_max_extents(sbi, OMFS_EXTENT_START); next = inode->i_ino; for (;;) { @@ -249,6 +264,9 @@ static int omfs_get_block(struct inode *inode, sector_t block, next = be64_to_cpu(oe->e_next); entry = &oe->e_entry; + if (extent_count > max_extents) + goto out_brelse; + offset = find_block(inode, entry, block, extent_count, &remain); if (offset > 0) { ret = 0; @@ -266,6 +284,7 @@ static int omfs_get_block(struct inode *inode, sector_t block, if (!bh) goto out; oe = (struct omfs_extent *) (&bh->b_data[OMFS_EXTENT_CONT]); + max_extents = omfs_max_extents(sbi, OMFS_EXTENT_CONT); } if (create) { ret = omfs_grow_extent(inode, oe, &new_block); -- cgit v1.1 From aab3a8c7a3a6a001dd439ed00d4db17a1059803e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Tue, 19 Aug 2008 14:23:37 +0000 Subject: [CIFS] reindent misindented statement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: Steve French --- fs/cifs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8482868..9c548f1 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -546,7 +546,8 @@ int cifs_get_inode_info(struct inode **pinode, if ((inode->i_mode & S_IWUGO) == 0 && (attr & ATTR_READONLY) == 0) inode->i_mode |= (S_IWUGO & default_mode); - inode->i_mode &= ~S_IFMT; + + inode->i_mode &= ~S_IFMT; } /* clear write bits if ATTR_READONLY is set */ if (attr & ATTR_READONLY) -- cgit v1.1 From cb7691b648bddbfaf6dd8d8068273dbb18d2484c Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 18 Aug 2008 15:41:05 -0400 Subject: cifs: add local server pointer to cifs_setup_session cifs_setup_session references pSesInfo->server several times. That pointer shouldn't change during the life of the function so grab it once and store it in a local var. This makes the code look a little cleaner too. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'fs') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 0711db6..4c13bcd 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3598,19 +3598,21 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, char ntlm_session_key[CIFS_SESS_KEY_SIZE]; bool ntlmv2_flag = false; int first_time = 0; + struct TCP_Server_Info *server = pSesInfo->server; /* what if server changes its buffer size after dropping the session? */ - if (pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { + if (server->maxBuf == 0) /* no need to send on reconnect */ { rc = CIFSSMBNegotiate(xid, pSesInfo); - if (rc == -EAGAIN) /* retry only once on 1st time connection */ { + if (rc == -EAGAIN) { + /* retry only once on 1st time connection */ rc = CIFSSMBNegotiate(xid, pSesInfo); if (rc == -EAGAIN) rc = -EHOSTDOWN; } if (rc == 0) { spin_lock(&GlobalMid_Lock); - if (pSesInfo->server->tcpStatus != CifsExiting) - pSesInfo->server->tcpStatus = CifsGood; + if (server->tcpStatus != CifsExiting) + server->tcpStatus = CifsGood; else rc = -EHOSTDOWN; spin_unlock(&GlobalMid_Lock); @@ -3623,23 +3625,22 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, goto ss_err_exit; pSesInfo->flags = 0; - pSesInfo->capabilities = pSesInfo->server->capabilities; + pSesInfo->capabilities = server->capabilities; if (linuxExtEnabled == 0) pSesInfo->capabilities &= (~CAP_UNIX); /* pSesInfo->sequence_number = 0;*/ cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", - pSesInfo->server->secMode, - pSesInfo->server->capabilities, - pSesInfo->server->timeAdj)); + server->secMode, server->capabilities, server->timeAdj)); + if (experimEnabled < 2) rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); else if (extended_security && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) - && (pSesInfo->server->secType == NTLMSSP)) { + && (server->secType == NTLMSSP)) { rc = -EOPNOTSUPP; } else if (extended_security && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) - && (pSesInfo->server->secType == RawNTLMSSP)) { + && (server->secType == RawNTLMSSP)) { cFYI(1, ("NTLMSSP sesssetup")); rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, nls_info); @@ -3668,12 +3669,12 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, } else { SMBNTencrypt(pSesInfo->password, - pSesInfo->server->cryptKey, + server->cryptKey, ntlm_session_key); if (first_time) cifs_calculate_mac_key( - &pSesInfo->server->mac_signing_key, + &server->mac_signing_key, ntlm_session_key, pSesInfo->password); } @@ -3686,13 +3687,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, nls_info); } } else { /* old style NTLM 0.12 session setup */ - SMBNTencrypt(pSesInfo->password, pSesInfo->server->cryptKey, + SMBNTencrypt(pSesInfo->password, server->cryptKey, ntlm_session_key); if (first_time) - cifs_calculate_mac_key( - &pSesInfo->server->mac_signing_key, - ntlm_session_key, pSesInfo->password); + cifs_calculate_mac_key(&server->mac_signing_key, + ntlm_session_key, + pSesInfo->password); rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info); } -- cgit v1.1 From c16fefa56334e8d0197492607e473fdbb813073f Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 19 Aug 2008 19:35:33 +0000 Subject: [CIFS] distinguish between Kerberos and MSKerberos in upcall Properly handle MSKRB5 by passing sec=mskrb5 to the upcall so that the spengo blob can be generated appropriately. Also, make decode_negTokenInit prefer whichever mechanism is first in the list. Needed for some NetApp servers, and possibly some older versions of Windows which treat the two KRB5 mechanisms differently. Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/asn1.c | 11 ++++++++--- fs/cifs/cifs_spnego.c | 4 +++- fs/cifs/cifsglob.h | 3 ++- fs/cifs/sess.c | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 5fabd2c..1b09f16 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -476,6 +476,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, unsigned int cls, con, tag, oidlen, rc; bool use_ntlmssp = false; bool use_kerberos = false; + bool use_mskerberos = false; *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/ @@ -574,10 +575,12 @@ decode_negTokenInit(unsigned char *security_blob, int length, *(oid + 1), *(oid + 2), *(oid + 3))); if (compare_oid(oid, oidlen, MSKRB5_OID, - MSKRB5_OID_LEN)) - use_kerberos = true; + MSKRB5_OID_LEN) && + !use_kerberos) + use_mskerberos = true; else if (compare_oid(oid, oidlen, KRB5_OID, - KRB5_OID_LEN)) + KRB5_OID_LEN) && + !use_mskerberos) use_kerberos = true; else if (compare_oid(oid, oidlen, NTLMSSP_OID, NTLMSSP_OID_LEN)) @@ -630,6 +633,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, if (use_kerberos) *secType = Kerberos; + else if (use_mskerberos) + *secType = MSKerberos; else if (use_ntlmssp) *secType = NTLMSSP; diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 2434ab0..117ef4b 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c @@ -114,9 +114,11 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) dp = description + strlen(description); - /* for now, only sec=krb5 is valid */ + /* for now, only sec=krb5 and sec=mskrb5 are valid */ if (server->secType == Kerberos) sprintf(dp, ";sec=krb5"); + else if (server->secType == MSKerberos) + sprintf(dp, ";sec=mskrb5"); else goto out; diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 7e1cf26..8dfd6f2 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -80,7 +80,8 @@ enum securityEnum { NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ RawNTLMSSP, /* NTLMSSP without SPNEGO */ NTLMSSP, /* NTLMSSP via SPNEGO */ - Kerberos /* Kerberos via SPNEGO */ + Kerberos, /* Kerberos via SPNEGO */ + MSKerberos, /* MS Kerberos via SPNEGO */ }; enum protocolEnum { diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index ed150ef..3188e4d 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -505,7 +505,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); } else ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else if (type == Kerberos) { + } else if (type == Kerberos || type == MSKerberos) { #ifdef CONFIG_CIFS_UPCALL struct cifs_spnego_msg *msg; spnego_key = cifs_get_spnego_key(ses); -- cgit v1.1 From 3d2af3465e91335bd1dbf36b19e92079d901409f Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 19 Aug 2008 20:51:09 +0000 Subject: [CIFS] Kerberos support not considered experimental anymore Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/Kconfig | 1 - fs/cifs/README | 30 ++++++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/Kconfig b/fs/Kconfig index d387358..f042710 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1984,7 +1984,6 @@ config CIFS_EXPERIMENTAL config CIFS_UPCALL bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" - depends on CIFS_EXPERIMENTAL depends on KEYS help Enables an upcall mechanism for CIFS which accesses diff --git a/fs/cifs/README b/fs/cifs/README index 2bd6fe5..68b5c11 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -642,8 +642,30 @@ The statistics for the number of total SMBs and oplock breaks are different in that they represent all for that share, not just those for which the server returned success. -Also note that "cat /proc/fs/cifs/DebugData" will display information about +Also note that "cat /proc/fs/cifs/DebugData" will display information about the active sessions and the shares that are mounted. -Enabling Kerberos (extended security) works when CONFIG_CIFS_EXPERIMENTAL is -on but requires a user space helper (from the Samba project). NTLM and NTLMv2 and -LANMAN support do not require this helper. + +Enabling Kerberos (extended security) works but requires version 1.2 or later +of the helper program cifs.upcall to be present and to be configured in the +/etc/request-key.conf file. The cifs.upcall helper program is from the Samba +project(http://www.samba.org). NTLM and NTLMv2 and LANMAN support do not +require this helper. Note that NTLMv2 security (which does not require the +cifs.upcall helper program), instead of using Kerberos, is sufficient for +some use cases. + +Enabling DFS support (used to access shares transparently in an MS-DFS +global name space) requires that CONFIG_CIFS_EXPERIMENTAL be enabled. In +addition, DFS support for target shares which are specified as UNC +names which begin with host names (rather than IP addresses) requires +a user space helper (such as cifs.upcall) to be present in order to +translate host names to ip address, and the user space helper must also +be configured in the file /etc/request-key.conf + +To use cifs Kerberos and DFS support, the Linux keyutils package should be +installed and something like the following lines should be added to the +/etc/request-key.conf file: + +create cifs.spnego * * /usr/local/sbin/cifs.upcall %k +create dns_resolver * * /usr/local/sbin/cifs.upcall %k + + -- cgit v1.1 From 5f22ca9b13551debea77a407a8d06cd9c6f15238 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 20 Aug 2008 08:31:19 -0700 Subject: vfat: fix 'sync' mount deadlock due to BKL->lock_super conversion There was another FAT BKL conversion deadlock reported by Bart Trojanowski due to the BKL being used as a recursive lock by FAT, which was missed because it only triggers with 'sync' (or 'dirsync') mounts. The recursion worked for the BKL, but after the conversion to lock_super (which uses a mutex), it just deadlocks. Thanks to Bart for debugging this and testing the fix. The lock debugging information from the original report: ============================================= [ INFO: possible recursive locking detected ] 2.6.27-rc3-bisect-00448-ga7f5aaf #16 --------------------------------------------- mv/4020 is trying to acquire lock: (&type->s_lock_key#9){--..}, at: [] lock_super+0x1e/0x20 but task is already holding lock: (&type->s_lock_key#9){--..}, at: [] lock_super+0x1e/0x20 other info that might help us debug this: 3 locks held by mv/4020: #0: (&sb->s_type->i_mutex_key#9/1){--..}, at: [] do_unlinkat+0x66/0x140 #1: (&sb->s_type->i_mutex_key#9){--..}, at: [] vfs_unlink+0x84/0x110 #2: (&type->s_lock_key#9){--..}, at: [] lock_super+0x1e/0x20 stack backtrace: Pid: 4020, comm: mv Not tainted 2.6.27-rc3-bisect-00448-ga7f5aaf #16 [] validate_chain+0x984/0xea0 [] ? native_sched_clock+0x0/0xf0 [] __lock_acquire+0x2ec/0x9b0 [] lock_acquire+0x6f/0x90 [] ? lock_super+0x1e/0x20 [] mutex_lock_nested+0xad/0x300 [] ? lock_super+0x1e/0x20 [] ? lock_super+0x1e/0x20 [] lock_super+0x1e/0x20 [] fat_write_inode+0x60/0x2b0 [fat] [] ? _spin_unlock_irqrestore+0x48/0x80 [] ? fat_sync_inode+0x3/0x20 [fat] [] fat_sync_inode+0x12/0x20 [fat] [] fat_remove_entries+0xbe/0x120 [fat] [] vfat_unlink+0x5f/0x90 [vfat] [] ? vfat_unlink+0x0/0x90 [vfat] [] vfs_unlink+0x98/0x110 [] do_unlinkat+0x130/0x140 [] ? audit_syscall_entry+0x105/0x150 [] sys_unlinkat+0x3b/0x40 [] sysenter_do_call+0x12/0x3f ======================= where the deadlock is due to the nesting of lock_super from vfat_unlink to fat_write_inode: - do_unlinkat - vfs_unlink - vfat_unlink * lock_super - fat_remove_entries - fat_sync_inode - fat_write_inode * lock_super and the fix is to simply remove the use of lock_super() in fat_write_inode. The lock_super() there had been just an automatic conversion of the kernel lock to the superblock lock, but no locking was actually needed there, since the code in fat_write_inode already protected all relevant accesses with a spinlock (sbi->inode_hash_lock to be exact). The only code inside the BKL (and thus the superblock lock) was accesses tp local variables or calls to functions that have long been SMP-safe (i.e. sb_bread, mark_buffe_dirty and brlese). Bart reports: "Looks good. I ran 10 parallel processes creating 1M files truncating them, writing to them again and then deleting them. This patch fixes the issue I ran into. Signed-off-by: Bart Trojanowski " Reported-and-tested-by: Bart Trojanowski Signed-off-by: Linus Torvalds --- fs/fat/inode.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 6d266d7..80ff338 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -562,26 +562,23 @@ static int fat_write_inode(struct inode *inode, int wait) struct buffer_head *bh; struct msdos_dir_entry *raw_entry; loff_t i_pos; - int err = 0; + int err; retry: i_pos = MSDOS_I(inode)->i_pos; if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) return 0; - lock_super(sb); bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); if (!bh) { printk(KERN_ERR "FAT: unable to read inode block " "for updating (i_pos %lld)\n", i_pos); - err = -EIO; - goto out; + return -EIO; } spin_lock(&sbi->inode_hash_lock); if (i_pos != MSDOS_I(inode)->i_pos) { spin_unlock(&sbi->inode_hash_lock); brelse(bh); - unlock_super(sb); goto retry; } @@ -607,11 +604,10 @@ retry: } spin_unlock(&sbi->inode_hash_lock); mark_buffer_dirty(bh); + err = 0; if (wait) err = sync_dirty_buffer(bh); brelse(bh); -out: - unlock_super(sb); return err; } -- cgit v1.1 From 1804dc6e145f3f24a8c94deddfc0a986d380a27f Mon Sep 17 00:00:00 2001 From: Clement Calmels Date: Wed, 20 Aug 2008 14:09:00 -0700 Subject: /proc/self/maps doesn't display the real file offset This addresses http://bugzilla.kernel.org/show_bug.cgi?id=11318 In function show_map (file: fs/proc/task_mmu.c), if vma->vm_pgoff > 2^20 than (vma->vm_pgoff << PAGE_SIZE) is greater than 2^32 (with PAGE_SIZE equal to 4096 (i.e. 2^12). The next seq_printf use an unsigned long for the conversion of (vma->vm_pgoff << PAGE_SIZE), as a result the offset value displayed in /proc/self/maps is truncated if the page offset is greater than 2^20. A test that shows this issue: #define _GNU_SOURCE #include #include #include #include #include #include #include #include #define PAGE_SIZE (getpagesize()) #if __i386__ # define U64_STR "%llx" #elif __x86_64 # define U64_STR "%lx" #else # error "Architecture Unsupported" #endif int main(int argc, char *argv[]) { int fd; char *addr; off64_t offset = 0x10000000; char *filename = "/dev/zero"; fd = open(filename, O_RDONLY); if (fd < 0) { perror("open"); return 1; } offset *= 0x10; printf("offset = " U64_STR "\n", offset); addr = (char*)mmap64(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, offset); if ((void*)addr == MAP_FAILED) { perror("mmap64"); return 1; } { FILE *fmaps; char *line = NULL; size_t len = 0; ssize_t read; size_t filename_len = strlen(filename); fmaps = fopen("/proc/self/maps", "r"); if (!fmaps) { perror("fopen"); return 1; } while ((read = getline(&line, &len, fmaps)) != -1) { if ((read > filename_len + 1) && (strncmp(&line[read - filename_len - 1], filename, filename_len) == 0)) printf("%s", line); } if (line) free(line); fclose(fmaps); } close(fd); return 0; } [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Clement Calmels Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/nommu.c | 4 ++-- fs/proc/task_mmu.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c index 79ecd28..3f87d26 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c @@ -52,14 +52,14 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) } seq_printf(m, - "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n", + "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", vma->vm_start, vma->vm_end, flags & VM_READ ? 'r' : '-', flags & VM_WRITE ? 'w' : '-', flags & VM_EXEC ? 'x' : '-', flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p', - vma->vm_pgoff << PAGE_SHIFT, + ((loff_t)vma->vm_pgoff) << PAGE_SHIFT, MAJOR(dev), MINOR(dev), ino, &len); if (file) { diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 7546a91..73d1891 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -219,14 +219,14 @@ static int show_map(struct seq_file *m, void *v) ino = inode->i_ino; } - seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n", + seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", vma->vm_start, vma->vm_end, flags & VM_READ ? 'r' : '-', flags & VM_WRITE ? 'w' : '-', flags & VM_EXEC ? 'x' : '-', flags & VM_MAYSHARE ? 's' : 'p', - vma->vm_pgoff << PAGE_SHIFT, + ((loff_t)vma->vm_pgoff) << PAGE_SHIFT, MAJOR(dev), MINOR(dev), ino, &len); /* -- cgit v1.1 From ff9bc512f198eb47204f55b24c6fe3d36ed89592 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 20 Aug 2008 14:09:10 -0700 Subject: binfmt_misc: fix false -ENOEXEC when coupled with other binary handlers In case the binfmt_misc binary handler is registered *before* the e.g. script one (when for example being compiled as a module) the following situation may occur: 1. user launches a script, whose interpreter is a misc binary; 2. the load_misc_binary sets the misc_bang and returns -ENOEVEC, since the binary is a script; 3. the load_script_binary loads one and calls for search_binary_hander to run the interpreter; 4. the load_misc_binary is called again, but refuses to load the binary due to misc_bang bit set. The fix is to move the misc_bang setting lower - prior to the actual call to the search_binary_handler. Caused by the commit 3a2e7f47 (binfmt_misc.c: avoid potential kernel stack overflow) Signed-off-by: Pavel Emelyanov Reported-by: Kirill A. Shutemov Tested-by: Kirill A. Shutemov Cc: [2.6.26.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/binfmt_misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 7562053..8d7e88e 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -120,8 +120,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (bprm->misc_bang) goto _ret; - bprm->misc_bang = 1; - /* to keep locking time low, we copy the interpreter string */ read_lock(&entries_lock); fmt = check_file(bprm); @@ -199,6 +197,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (retval < 0) goto _error; + bprm->misc_bang = 1; + retval = search_binary_handler (bprm, regs); if (retval < 0) goto _error; -- cgit v1.1 From 2d70b68d42b5196a48ccb639e3797f097ef5bea3 Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Wed, 20 Aug 2008 14:09:17 -0700 Subject: fix setpriority(PRIO_PGRP) thread iterator breakage When user calls sys_setpriority(PRIO_PGRP ...) on a NPTL style multi-LWP process, only the task leader of the process is affected, all other sibling LWP threads didn't receive the setting. The problem was that the iterator used in sys_setpriority() only iteartes over one task for each process, ignoring all other sibling thread. Introduce a new macro do_each_pid_thread / while_each_pid_thread to walk each thread of a process. Convert 4 call sites in {set/get}priority and ioprio_{set/get}. Signed-off-by: Ken Chen Cc: Oleg Nesterov Cc: Roland McGrath Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ioprio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/ioprio.c b/fs/ioprio.c index c4a1c3c..da3cc46 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c @@ -115,11 +115,11 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) pgrp = task_pgrp(current); else pgrp = find_vpid(who); - do_each_pid_task(pgrp, PIDTYPE_PGID, p) { + do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { ret = set_task_ioprio(p, ioprio); if (ret) break; - } while_each_pid_task(pgrp, PIDTYPE_PGID, p); + } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); break; case IOPRIO_WHO_USER: if (!who) @@ -204,7 +204,7 @@ asmlinkage long sys_ioprio_get(int which, int who) pgrp = task_pgrp(current); else pgrp = find_vpid(who); - do_each_pid_task(pgrp, PIDTYPE_PGID, p) { + do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { tmpio = get_task_ioprio(p); if (tmpio < 0) continue; @@ -212,7 +212,7 @@ asmlinkage long sys_ioprio_get(int which, int who) ret = tmpio; else ret = ioprio_best(ret, tmpio); - } while_each_pid_task(pgrp, PIDTYPE_PGID, p); + } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); break; case IOPRIO_WHO_USER: if (!who) -- cgit v1.1 From 82d63fc9e30687c055b97928942b8893ea65b0bb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 20 Aug 2008 14:09:24 -0700 Subject: cramfs: fix named-pipe handling After commit a97c9bf33f4612e2aed6f000f6b1d268b6814f3c (fix cramfs making duplicate entries in inode cache) in kernel 2.6.14, named-pipe on cramfs does not work properly. It seems the commit make all named-pipe on cramfs share their inode (and named-pipe buffer). Make ..._test() refuse to merge inodes with ->i_ino == 1, take inode setup back to get_cramfs_inode() and make ->drop_inode() evict ones with ->i_ino == 1 immediately. Reported-by: Atsushi Nemoto Cc: Al Viro Cc: [2.6.14 and later] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/cramfs/inode.c | 84 +++++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 46 deletions(-) (limited to 'fs') diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 0c3b618..f40423e 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -43,58 +43,13 @@ static DEFINE_MUTEX(read_mutex); static int cramfs_iget5_test(struct inode *inode, void *opaque) { struct cramfs_inode *cramfs_inode = opaque; - - if (inode->i_ino != CRAMINO(cramfs_inode)) - return 0; /* does not match */ - - if (inode->i_ino != 1) - return 1; - - /* all empty directories, char, block, pipe, and sock, share inode #1 */ - - if ((inode->i_mode != cramfs_inode->mode) || - (inode->i_gid != cramfs_inode->gid) || - (inode->i_uid != cramfs_inode->uid)) - return 0; /* does not match */ - - if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) && - (inode->i_rdev != old_decode_dev(cramfs_inode->size))) - return 0; /* does not match */ - - return 1; /* matches */ + return inode->i_ino == CRAMINO(cramfs_inode) && inode->i_ino != 1; } static int cramfs_iget5_set(struct inode *inode, void *opaque) { - static struct timespec zerotime; struct cramfs_inode *cramfs_inode = opaque; - inode->i_mode = cramfs_inode->mode; - inode->i_uid = cramfs_inode->uid; - inode->i_size = cramfs_inode->size; - inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; - inode->i_gid = cramfs_inode->gid; - /* Struct copy intentional */ - inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; inode->i_ino = CRAMINO(cramfs_inode); - /* inode->i_nlink is left 1 - arguably wrong for directories, - but it's the best we can do without reading the directory - contents. 1 yields the right result in GNU find, even - without -noleaf option. */ - if (S_ISREG(inode->i_mode)) { - inode->i_fop = &generic_ro_fops; - inode->i_data.a_ops = &cramfs_aops; - } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = &cramfs_dir_inode_operations; - inode->i_fop = &cramfs_directory_operations; - } else if (S_ISLNK(inode->i_mode)) { - inode->i_op = &page_symlink_inode_operations; - inode->i_data.a_ops = &cramfs_aops; - } else { - inode->i_size = 0; - inode->i_blocks = 0; - init_special_inode(inode, inode->i_mode, - old_decode_dev(cramfs_inode->size)); - } return 0; } @@ -104,12 +59,48 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), cramfs_iget5_test, cramfs_iget5_set, cramfs_inode); + static struct timespec zerotime; + if (inode && (inode->i_state & I_NEW)) { + inode->i_mode = cramfs_inode->mode; + inode->i_uid = cramfs_inode->uid; + inode->i_size = cramfs_inode->size; + inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; + inode->i_gid = cramfs_inode->gid; + /* Struct copy intentional */ + inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; + /* inode->i_nlink is left 1 - arguably wrong for directories, + but it's the best we can do without reading the directory + contents. 1 yields the right result in GNU find, even + without -noleaf option. */ + if (S_ISREG(inode->i_mode)) { + inode->i_fop = &generic_ro_fops; + inode->i_data.a_ops = &cramfs_aops; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &cramfs_dir_inode_operations; + inode->i_fop = &cramfs_directory_operations; + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_data.a_ops = &cramfs_aops; + } else { + inode->i_size = 0; + inode->i_blocks = 0; + init_special_inode(inode, inode->i_mode, + old_decode_dev(cramfs_inode->size)); + } unlock_new_inode(inode); } return inode; } +static void cramfs_drop_inode(struct inode *inode) +{ + if (inode->i_ino == 1) + generic_delete_inode(inode); + else + generic_drop_inode(inode); +} + /* * We have our own block cache: don't fill up the buffer cache * with the rom-image, because the way the filesystem is set @@ -534,6 +525,7 @@ static const struct super_operations cramfs_ops = { .put_super = cramfs_put_super, .remount_fs = cramfs_remount, .statfs = cramfs_statfs, + .drop_inode = cramfs_drop_inode, }; static int cramfs_get_sb(struct file_system_type *fs_type, -- cgit v1.1 From 18496e80f729be5f536d0315751b3bbb95ca913e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 7 Aug 2008 00:11:12 +0300 Subject: [PATCH] ocfs2/cluster/tcp.c: make some functions static Commit 0f475b2abed6cbccee1da20a0bef2895eb2a0edd (ocfs2/net: Silence build warnings) made sense as far as it fixed compile warnings, but it was not required that it made the functions global. Signed-off-by: Adrian Bunk Signed-off-by: Mark Fasheh --- fs/ocfs2/cluster/tcp.c | 44 ++++++++++++++++++++++++++++++++++------- fs/ocfs2/cluster/tcp_internal.h | 32 ------------------------------ 2 files changed, 37 insertions(+), 39 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index a27d615..2bcf706 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -143,8 +143,8 @@ static void o2net_sc_postpone_idle(struct o2net_sock_container *sc); static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc); #ifdef CONFIG_DEBUG_FS -void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, - u32 msgkey, struct task_struct *task, u8 node) +static void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, + u32 msgkey, struct task_struct *task, u8 node) { INIT_LIST_HEAD(&nst->st_net_debug_item); nst->st_task = task; @@ -153,31 +153,61 @@ void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, nst->st_node = node; } -void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) +static void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) { do_gettimeofday(&nst->st_sock_time); } -void o2net_set_nst_send_time(struct o2net_send_tracking *nst) +static void o2net_set_nst_send_time(struct o2net_send_tracking *nst) { do_gettimeofday(&nst->st_send_time); } -void o2net_set_nst_status_time(struct o2net_send_tracking *nst) +static void o2net_set_nst_status_time(struct o2net_send_tracking *nst) { do_gettimeofday(&nst->st_status_time); } -void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, +static void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, struct o2net_sock_container *sc) { nst->st_sc = sc; } -void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, u32 msg_id) +static void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, u32 msg_id) { nst->st_id = msg_id; } + +#else /* CONFIG_DEBUG_FS */ + +static inline void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, + u32 msgkey, struct task_struct *task, u8 node) +{ +} + +static inline void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) +{ +} + +static inline void o2net_set_nst_send_time(struct o2net_send_tracking *nst) +{ +} + +static inline void o2net_set_nst_status_time(struct o2net_send_tracking *nst) +{ +} + +static inline void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, + struct o2net_sock_container *sc) +{ +} + +static inline void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, + u32 msg_id) +{ +} + #endif /* CONFIG_DEBUG_FS */ static inline int o2net_reconnect_delay(void) diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h index 18307ff..8d58cfe 100644 --- a/fs/ocfs2/cluster/tcp_internal.h +++ b/fs/ocfs2/cluster/tcp_internal.h @@ -224,42 +224,10 @@ struct o2net_send_tracking { struct timeval st_send_time; struct timeval st_status_time; }; - -void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, - u32 msgkey, struct task_struct *task, u8 node); -void o2net_set_nst_sock_time(struct o2net_send_tracking *nst); -void o2net_set_nst_send_time(struct o2net_send_tracking *nst); -void o2net_set_nst_status_time(struct o2net_send_tracking *nst); -void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, - struct o2net_sock_container *sc); -void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, u32 msg_id); - #else struct o2net_send_tracking { u32 dummy; }; - -static inline void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype, - u32 msgkey, struct task_struct *task, u8 node) -{ -} -static inline void o2net_set_nst_sock_time(struct o2net_send_tracking *nst) -{ -} -static inline void o2net_set_nst_send_time(struct o2net_send_tracking *nst) -{ -} -static inline void o2net_set_nst_status_time(struct o2net_send_tracking *nst) -{ -} -static inline void o2net_set_nst_sock_container(struct o2net_send_tracking *nst, - struct o2net_sock_container *sc) -{ -} -static inline void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, - u32 msg_id) -{ -} #endif /* CONFIG_DEBUG_FS */ #endif /* O2CLUSTER_TCP_INTERNAL_H */ -- cgit v1.1 From a57a874b04e27cb530a0e18c244387452e73ccce Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 6 Aug 2008 00:50:41 +0400 Subject: [PATCH] ocfs2/cluster/netdebug.c: fix warning ocfs2/cluster/netdebug.c: fix warning fs/ocfs2/cluster/netdebug.c:154: warning: format '%lu' expects type 'long unsigned int', but argument 17 has type 'suseconds_t' Signed-off-by: Alexander Beregalov Signed-off-by: Mark Fasheh --- fs/ocfs2/cluster/netdebug.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/netdebug.c b/fs/ocfs2/cluster/netdebug.c index d8bfa0e..52276c0 100644 --- a/fs/ocfs2/cluster/netdebug.c +++ b/fs/ocfs2/cluster/netdebug.c @@ -138,20 +138,20 @@ static int nst_seq_show(struct seq_file *seq, void *v) " message id: %d\n" " message type: %u\n" " message key: 0x%08x\n" - " sock acquiry: %lu.%lu\n" - " send start: %lu.%lu\n" - " wait start: %lu.%lu\n", + " sock acquiry: %lu.%ld\n" + " send start: %lu.%ld\n" + " wait start: %lu.%ld\n", nst, (unsigned long)nst->st_task->pid, (unsigned long)nst->st_task->tgid, nst->st_task->comm, nst->st_node, nst->st_sc, nst->st_id, nst->st_msg_type, nst->st_msg_key, nst->st_sock_time.tv_sec, - (unsigned long)nst->st_sock_time.tv_usec, + (long)nst->st_sock_time.tv_usec, nst->st_send_time.tv_sec, - (unsigned long)nst->st_send_time.tv_usec, + (long)nst->st_send_time.tv_usec, nst->st_status_time.tv_sec, - nst->st_status_time.tv_usec); + (long)nst->st_status_time.tv_usec); } spin_unlock(&o2net_debug_lock); @@ -276,7 +276,7 @@ static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos) return sc; /* unused, just needs to be null when done */ } -#define TV_SEC_USEC(TV) TV.tv_sec, (unsigned long)TV.tv_usec +#define TV_SEC_USEC(TV) TV.tv_sec, (long)TV.tv_usec static int sc_seq_show(struct seq_file *seq, void *v) { @@ -309,12 +309,12 @@ static int sc_seq_show(struct seq_file *seq, void *v) " remote node: %s\n" " page off: %zu\n" " handshake ok: %u\n" - " timer: %lu.%lu\n" - " data ready: %lu.%lu\n" - " advance start: %lu.%lu\n" - " advance stop: %lu.%lu\n" - " func start: %lu.%lu\n" - " func stop: %lu.%lu\n" + " timer: %lu.%ld\n" + " data ready: %lu.%ld\n" + " advance start: %lu.%ld\n" + " advance stop: %lu.%ld\n" + " func start: %lu.%ld\n" + " func stop: %lu.%ld\n" " func key: %u\n" " func type: %u\n", sc, -- cgit v1.1 From a1af7d15a18d1e375b0a6fee93789a0bbfe088b4 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 19 Aug 2008 17:20:28 -0700 Subject: ocfs2: Fix sleep-with-spinlock recovery regression This fixes a bug introduced with 539d8264093560b917ee3afe4c7f74e5da09d6a5: [PATCH 2/2] ocfs2: Fix race between mount and recovery ocfs2_mark_dead_nodes() was reading journal inodes while holding the spinlock protecting our in-memory recovery state. The fix is very simple - the disk state is protected by a cluster lock that's already held, so we just move the spinlock down past the read. Reviewed-by: Joel Becker Signed-off-by: Mark Fasheh --- fs/ocfs2/journal.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 7a37240..c47bc2a 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -1418,13 +1418,13 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) { unsigned int node_num; int status, i; + u32 gen; struct buffer_head *bh = NULL; struct ocfs2_dinode *di; /* This is called with the super block cluster lock, so we * know that the slot map can't change underneath us. */ - spin_lock(&osb->osb_lock); for (i = 0; i < osb->max_slots; i++) { /* Read journal inode to get the recovery generation */ status = ocfs2_read_journal_inode(osb, i, &bh, NULL); @@ -1433,23 +1433,31 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) goto bail; } di = (struct ocfs2_dinode *)bh->b_data; - osb->slot_recovery_generations[i] = - ocfs2_get_recovery_generation(di); + gen = ocfs2_get_recovery_generation(di); brelse(bh); bh = NULL; + spin_lock(&osb->osb_lock); + osb->slot_recovery_generations[i] = gen; + mlog(0, "Slot %u recovery generation is %u\n", i, osb->slot_recovery_generations[i]); - if (i == osb->slot_num) + if (i == osb->slot_num) { + spin_unlock(&osb->osb_lock); continue; + } status = ocfs2_slot_to_node_num_locked(osb, i, &node_num); - if (status == -ENOENT) + if (status == -ENOENT) { + spin_unlock(&osb->osb_lock); continue; + } - if (__ocfs2_recovery_map_test(osb, node_num)) + if (__ocfs2_recovery_map_test(osb, node_num)) { + spin_unlock(&osb->osb_lock); continue; + } spin_unlock(&osb->osb_lock); /* Ok, we have a slot occupied by another node which @@ -1465,10 +1473,7 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) mlog_errno(status); goto bail; } - - spin_lock(&osb->osb_lock); } - spin_unlock(&osb->osb_lock); status = 0; bail: -- cgit v1.1 From 83cab5338fa8c74f979223698c8d4cc88f2ab68e Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 21 Aug 2008 14:14:27 +0800 Subject: ocfs2: Jump to correct label in ocfs2_expand_inline_dir() When we fail to insert extent in ocfs2_expand_inline_dir(), we should go to out_commit, not out. Signed-off-by: Tao Ma Signed-off-by: Mark Fasheh --- fs/ocfs2/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 8a18758..8e9c4a4 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -1310,7 +1310,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, NULL); if (ret) { mlog_errno(ret); - goto out; + goto out_commit; } ret = ocfs2_journal_dirty(handle, di_bh); @@ -1336,7 +1336,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, len, 0, NULL); if (ret) { mlog_errno(ret); - goto out; + goto out_commit; } } -- cgit v1.1 From 9780eb6cfaf7d2d5ccc061eaf94e7aec6a17791e Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 5 Aug 2008 11:32:46 -0700 Subject: ocfs2: correctly set i_blocks after inline dir gets expanded We were setting i_blocks based on allocation before the extent insert, which is wrong as the value is a calculation based on ip_clusters which gets updated as a result of the insert. This patch moves the line in question to just after the call to ocfs2_insert_extent(). Without this fix, inline directories were temporarily having an i_blocks value of zero immediately after expansion to extents. Reported-and-tested-by: Tristan Ye Signed-off-by: Mark Fasheh --- fs/ocfs2/dir.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 8e9c4a4..9cce563 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -1300,7 +1300,6 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, di->i_size = cpu_to_le64(sb->s_blocksize); di->i_ctime = di->i_mtime = cpu_to_le64(dir->i_ctime.tv_sec); di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(dir->i_ctime.tv_nsec); - dir->i_blocks = ocfs2_inode_sector_count(dir); /* * This should never fail as our extent list is empty and all @@ -1313,6 +1312,12 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, goto out_commit; } + /* + * Set i_blocks after the extent insert for the most up to + * date ip_clusters value. + */ + dir->i_blocks = ocfs2_inode_sector_count(dir); + ret = ocfs2_journal_dirty(handle, di_bh); if (ret) { mlog_errno(ret); -- cgit v1.1 From de6bf18e9ce0df807dab08cff08751cac383429d Mon Sep 17 00:00:00 2001 From: Louis Rilling Date: Fri, 15 Aug 2008 12:37:23 -0700 Subject: [PATCH] configfs: Consolidate locking around configfs_detach_prep() in configfs_rmdir() It appears that configfs_rmdir() can protect configfs_detach_prep() retries with less calls to {spin,mutex}_{lock,unlock}, and a cleaner code. This patch does not change any behavior, except that it removes two useless lock/unlock pairs having nothing inside to protect and providing a useless barrier. Signed-off-by: Louis Rilling Signed-off-by: Joel Becker Signed-off-by: Mark Fasheh --- fs/configfs/dir.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 7a8db78..8e93341 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -1311,16 +1311,18 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) * Ensure that no racing symlink() will make detach_prep() fail while * the new link is temporarily attached */ - mutex_lock(&configfs_symlink_mutex); - spin_lock(&configfs_dirent_lock); do { struct mutex *wait_mutex; + mutex_lock(&configfs_symlink_mutex); + spin_lock(&configfs_dirent_lock); ret = configfs_detach_prep(dentry, &wait_mutex); - if (ret) { + if (ret) configfs_detach_rollback(dentry); - spin_unlock(&configfs_dirent_lock); - mutex_unlock(&configfs_symlink_mutex); + spin_unlock(&configfs_dirent_lock); + mutex_unlock(&configfs_symlink_mutex); + + if (ret) { if (ret != -EAGAIN) { config_item_put(parent_item); return ret; @@ -1329,13 +1331,8 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) /* Wait until the racing operation terminates */ mutex_lock(wait_mutex); mutex_unlock(wait_mutex); - - mutex_lock(&configfs_symlink_mutex); - spin_lock(&configfs_dirent_lock); } } while (ret == -EAGAIN); - spin_unlock(&configfs_dirent_lock); - mutex_unlock(&configfs_symlink_mutex); /* Get a working ref for the duration of this function */ item = configfs_get_config_item(dentry); -- cgit v1.1 From 7a8fc9b248e77a4eab0613acf30a6811799786b3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 17 Aug 2008 17:36:59 +0300 Subject: removed unused #include 's This patch lets the files using linux/version.h match the files that #include it. Signed-off-by: Adrian Bunk Signed-off-by: Linus Torvalds --- fs/jffs2/jffs2_fs_i.h | 1 - fs/xfs/xfs_dmapi.h | 1 - 2 files changed, 2 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h index 31559f4..4c41db9 100644 --- a/fs/jffs2/jffs2_fs_i.h +++ b/fs/jffs2/jffs2_fs_i.h @@ -12,7 +12,6 @@ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I -#include #include #include #include diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index cdc2d34..2813cdd 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -18,7 +18,6 @@ #ifndef __XFS_DMAPI_H__ #define __XFS_DMAPI_H__ -#include /* Values used to define the on-disk version of dm_attrname_t. All * on-disk attribute names start with the 8-byte string "SGI_DMI_". * -- cgit v1.1 From cc996099174dc05b35b7a29301026987990e7f8c Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 2 Aug 2008 07:30:48 +0400 Subject: [PATCH] proc: inode number fixlet Ouch, if number taken from IDA is too big, the intent was to signal an error, not check for overflow and still do overflowing addition. One still needs 2^28 proc entries to notice this. Signed-off-by: Alexey Dobriyan Signed-off-by: Al Viro --- fs/proc/generic.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 4fb81e9..bca0f81 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -330,6 +330,7 @@ retry: spin_lock(&proc_inum_lock); ida_remove(&proc_inum_ida, i); spin_unlock(&proc_inum_lock); + return 0; } return PROC_DYNAMIC_FIRST + i; } -- cgit v1.1 From 2d8a10cd1760e7ecc07a21e409485947c68a3291 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 11 Aug 2008 11:33:57 -0400 Subject: [PATCH] fix efs_lookup() it needs to use d_splice_alias(), not d_add() Signed-off-by: Al Viro --- fs/efs/namei.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/efs/namei.c b/fs/efs/namei.c index 3a404e7..291abb1 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c @@ -74,8 +74,7 @@ struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct namei } unlock_kernel(); - d_add(dentry, inode); - return NULL; + return d_splice_alias(inode, dentry); } static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, -- cgit v1.1 From e45b590b976465c258f3e2a6cc84573fc19e16d3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 7 Aug 2008 23:49:07 +0200 Subject: [PATCH] change d_add_ci argument ordering As pointed out during review d_add_ci argument order should match d_add, so switch the dentry and inode arguments. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/dcache.c | 2 +- fs/xfs/linux-2.6/xfs_iops.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/dcache.c b/fs/dcache.c index 101663d..80e9395 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1236,7 +1236,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) * If no entry exists with the exact case name, allocate new dentry with * the exact case, and return the spliced entry. */ -struct dentry *d_add_ci(struct inode *inode, struct dentry *dentry, +struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, struct qstr *name) { int error; diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 91bcd979..095d271 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -355,7 +355,7 @@ xfs_vn_ci_lookup( /* else case-insensitive match... */ dname.name = ci_name.name; dname.len = ci_name.len; - dentry = d_add_ci(VFS_I(ip), dentry, &dname); + dentry = d_add_ci(dentry, VFS_I(ip), &dname); kmem_free(ci_name.name); return dentry; } -- cgit v1.1 From 2690421743b03c9be05d8e44c3b827986d1329a7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 7 Aug 2008 23:50:21 +0200 Subject: [PATCH] ntfs: use d_add_ci d_add_ci was lifted 1:1 from ntfs. Change ntfs to use the common version. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/ntfs/namei.c | 89 ++------------------------------------------------------- 1 file changed, 2 insertions(+), 87 deletions(-) (limited to 'fs') diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index e1781c8..9e8a95b 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c @@ -174,7 +174,6 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, // TODO: Consider moving this lot to a separate function! (AIA) handle_name: { - struct dentry *real_dent, *new_dent; MFT_RECORD *m; ntfs_attr_search_ctx *ctx; ntfs_inode *ni = NTFS_I(dent_inode); @@ -255,93 +254,9 @@ handle_name: } nls_name.hash = full_name_hash(nls_name.name, nls_name.len); - /* - * Note: No need for dent->d_lock lock as i_mutex is held on the - * parent inode. - */ - - /* Does a dentry matching the nls_name exist already? */ - real_dent = d_lookup(dent->d_parent, &nls_name); - /* If not, create it now. */ - if (!real_dent) { - real_dent = d_alloc(dent->d_parent, &nls_name); - kfree(nls_name.name); - if (!real_dent) { - err = -ENOMEM; - goto err_out; - } - new_dent = d_splice_alias(dent_inode, real_dent); - if (new_dent) - dput(real_dent); - else - new_dent = real_dent; - ntfs_debug("Done. (Created new dentry.)"); - return new_dent; - } + dent = d_add_ci(dent, dent_inode, &nls_name); kfree(nls_name.name); - /* Matching dentry exists, check if it is negative. */ - if (real_dent->d_inode) { - if (unlikely(real_dent->d_inode != dent_inode)) { - /* This can happen because bad inodes are unhashed. */ - BUG_ON(!is_bad_inode(dent_inode)); - BUG_ON(!is_bad_inode(real_dent->d_inode)); - } - /* - * Already have the inode and the dentry attached, decrement - * the reference count to balance the ntfs_iget() we did - * earlier on. We found the dentry using d_lookup() so it - * cannot be disconnected and thus we do not need to worry - * about any NFS/disconnectedness issues here. - */ - iput(dent_inode); - ntfs_debug("Done. (Already had inode and dentry.)"); - return real_dent; - } - /* - * Negative dentry: instantiate it unless the inode is a directory and - * has a 'disconnected' dentry (i.e. IS_ROOT and DCACHE_DISCONNECTED), - * in which case d_move() that in place of the found dentry. - */ - if (!S_ISDIR(dent_inode->i_mode)) { - /* Not a directory; everything is easy. */ - d_instantiate(real_dent, dent_inode); - ntfs_debug("Done. (Already had negative file dentry.)"); - return real_dent; - } - spin_lock(&dcache_lock); - if (list_empty(&dent_inode->i_dentry)) { - /* - * Directory without a 'disconnected' dentry; we need to do - * d_instantiate() by hand because it takes dcache_lock which - * we already hold. - */ - list_add(&real_dent->d_alias, &dent_inode->i_dentry); - real_dent->d_inode = dent_inode; - spin_unlock(&dcache_lock); - security_d_instantiate(real_dent, dent_inode); - ntfs_debug("Done. (Already had negative directory dentry.)"); - return real_dent; - } - /* - * Directory with a 'disconnected' dentry; get a reference to the - * 'disconnected' dentry. - */ - new_dent = list_entry(dent_inode->i_dentry.next, struct dentry, - d_alias); - dget_locked(new_dent); - spin_unlock(&dcache_lock); - /* Do security vodoo. */ - security_d_instantiate(real_dent, dent_inode); - /* Move new_dent in place of real_dent. */ - d_move(new_dent, real_dent); - /* Balance the ntfs_iget() we did above. */ - iput(dent_inode); - /* Throw away real_dent. */ - dput(real_dent); - /* Use new_dent as the actual dentry. */ - ntfs_debug("Done. (Already had negative, disconnected directory " - "dentry.)"); - return new_dent; + return dent; eio_err_out: ntfs_error(vol->sb, "Illegal file name attribute. Run chkdsk."); -- cgit v1.1 From 8f3f655da7288504c1013621090ecc940173ae1c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 12 Aug 2008 00:28:24 -0400 Subject: [PATCH] fix regular readdir() and friends Handling of -EOVERFLOW. Signed-off-by: Al Viro --- fs/compat.c | 8 ++++++-- fs/readdir.c | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/compat.c b/fs/compat.c index c9d1472..075d050 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -792,8 +792,10 @@ static int compat_fillonedir(void *__buf, const char *name, int namlen, if (buf->result) return -EINVAL; d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { + buf->result = -EOVERFLOW; return -EOVERFLOW; + } buf->result++; dirent = buf->dirent; if (!access_ok(VERIFY_WRITE, dirent, @@ -862,8 +864,10 @@ static int compat_filldir(void *__buf, const char *name, int namlen, if (reclen > buf->count) return -EINVAL; d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { + buf->error = -EOVERFLOW; return -EOVERFLOW; + } dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) diff --git a/fs/readdir.c b/fs/readdir.c index 4e026e5..93a7559 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -80,8 +80,10 @@ static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset if (buf->result) return -EINVAL; d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { + buf->result = -EOVERFLOW; return -EOVERFLOW; + } buf->result++; dirent = buf->dirent; if (!access_ok(VERIFY_WRITE, dirent, @@ -155,8 +157,10 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, if (reclen > buf->count) return -EINVAL; d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) + if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { + buf->error = -EOVERFLOW; return -EOVERFLOW; + } dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) -- cgit v1.1 From 59af1584bf33810639cb98d79856021253e2177c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Aug 2008 07:24:41 -0400 Subject: [PATCH] fix ->llseek() for a bunch of directories Signed-off-by: Al Viro --- fs/9p/vfs_dir.c | 1 + fs/adfs/dir.c | 1 + fs/affs/dir.c | 1 + fs/autofs4/root.c | 2 ++ fs/befs/linuxvfs.c | 1 + fs/xfs/linux-2.6/xfs_file.c | 1 + 6 files changed, 7 insertions(+) (limited to 'fs') diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 88e3787..e298fe1 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -119,6 +119,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) const struct file_operations v9fs_dir_operations = { .read = generic_read_dir, + .llseek = generic_file_llseek, .readdir = v9fs_dir_readdir, .open = v9fs_file_open, .release = v9fs_dir_release, diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index fc1a8dc..85a30e9 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -197,6 +197,7 @@ out: const struct file_operations adfs_dir_operations = { .read = generic_read_dir, + .llseek = generic_file_llseek, .readdir = adfs_readdir, .fsync = file_fsync, }; diff --git a/fs/affs/dir.c b/fs/affs/dir.c index 6e3f282..7b36904 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c @@ -19,6 +19,7 @@ static int affs_readdir(struct file *, void *, filldir_t); const struct file_operations affs_dir_operations = { .read = generic_read_dir, + .llseek = generic_file_llseek, .readdir = affs_readdir, .fsync = file_fsync, }; diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index bcfb2dc..2a41c2a 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -36,6 +36,7 @@ const struct file_operations autofs4_root_operations = { .release = dcache_dir_close, .read = generic_read_dir, .readdir = dcache_readdir, + .llseek = dcache_dir_lseek, .ioctl = autofs4_root_ioctl, }; @@ -44,6 +45,7 @@ const struct file_operations autofs4_dir_operations = { .release = dcache_dir_close, .read = generic_read_dir, .readdir = dcache_readdir, + .llseek = dcache_dir_lseek, }; const struct inode_operations autofs4_indirect_root_inode_operations = { diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 02c6e62b..740f536 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -66,6 +66,7 @@ static struct kmem_cache *befs_inode_cachep; static const struct file_operations befs_dir_operations = { .read = generic_read_dir, .readdir = befs_readdir, + .llseek = generic_file_llseek, }; static const struct inode_operations befs_dir_inode_operations = { diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 5f60363..5311c1a 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -475,6 +475,7 @@ const struct file_operations xfs_invis_file_operations = { const struct file_operations xfs_dir_file_operations = { .read = generic_read_dir, .readdir = xfs_file_readdir, + .llseek = generic_file_llseek, .unlocked_ioctl = xfs_file_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = xfs_file_compat_ioctl, -- cgit v1.1 From 4cdfe84b51420c9ac95c7133da2d4c8a191094af Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Aug 2008 07:45:33 -0400 Subject: [PATCH] deal with the first call of ->show() generating no output seq_read() has a subtle bug - we want the first loop there to go until at least one *non-empty* record had fit entirely into buffer. Signed-off-by: Al Viro --- fs/seq_file.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/seq_file.c b/fs/seq_file.c index 5d54205..bd20f7f 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -108,9 +108,9 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) goto Done; } /* we need at least one record in buffer */ + pos = m->index; + p = m->op->start(m, &pos); while (1) { - pos = m->index; - p = m->op->start(m, &pos); err = PTR_ERR(p); if (!p || IS_ERR(p)) break; @@ -119,6 +119,11 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) break; if (unlikely(err)) m->count = 0; + if (unlikely(!m->count)) { + p = m->op->next(m, p, &pos); + m->index = pos; + continue; + } if (m->count < m->size) goto Fill; m->op->stop(m, p); @@ -128,6 +133,8 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) goto Enomem; m->count = 0; m->version = 0; + pos = m->index; + p = m->op->start(m, &pos); } m->op->stop(m, p); m->count = 0; -- cgit v1.1 From d6817cdbd143f87f9d7c59a4c3194091190eeb84 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Fri, 22 Aug 2008 14:30:10 -0700 Subject: ocfs2: Increment the reference count of an already-active stack. The ocfs2_stack_driver_request() function failed to increment the refcount of an already-active stack. It only did the increment on the first reference. Whoops. Signed-off-by: Joel Becker Tested-by: Marcos Matsunaga Signed-off-by: Mark Fasheh --- fs/ocfs2/stackglue.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index 10e149a..07f348b 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c @@ -97,13 +97,14 @@ static int ocfs2_stack_driver_request(const char *stack_name, goto out; } - /* Ok, the stack is pinned */ - p->sp_count++; active_stack = p; - rc = 0; out: + /* If we found it, pin it */ + if (!rc) + active_stack->sp_count++; + spin_unlock(&ocfs2_stack_lock); return rc; } -- cgit v1.1 From 6ce5eecb9cd3ac97b952c50309b87c31488a45e9 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 26 Aug 2008 00:37:14 +0000 Subject: [CIFS] check version in spnego upcall response Currently, we don't check the version in the SPNEGO upcall response even though one is provided. Jeff and Q have made the corresponding change to the Samba client (cifs.upcall). Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/CHANGES | 6 +++++- fs/cifs/cifs_spnego.h | 2 +- fs/cifs/sess.c | 9 +++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index f5d0083..526041a5 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -4,7 +4,11 @@ Fix premature write failure on congested networks (we would give up on EAGAIN from the socket too quickly on large writes). Cifs_mkdir and cifs_create now respect the setgid bit on parent dir. Fix endian problems in acl (mode from/to cifs acl) on bigendian -architectures. +architectures. Fix problems with preserving timestamps on copying open +files (e.g. "cp -a") to Windows servers. For mkdir and create honor setgid bit +on parent directory when server supports Unix Extensions but not POSIX +create. Update cifs.upcall version to handle new Kerberos sec flags +(this requires update of cifs.upcall program from Samba). Version 1.53 ------------ diff --git a/fs/cifs/cifs_spnego.h b/fs/cifs/cifs_spnego.h index 05a34b1..e4041ec 100644 --- a/fs/cifs/cifs_spnego.h +++ b/fs/cifs/cifs_spnego.h @@ -23,7 +23,7 @@ #ifndef _CIFS_SPNEGO_H #define _CIFS_SPNEGO_H -#define CIFS_SPNEGO_UPCALL_VERSION 1 +#define CIFS_SPNEGO_UPCALL_VERSION 2 /* * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION. diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 3188e4d..b537fad 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -516,6 +516,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, } msg = spnego_key->payload.data; + /* check version field to make sure that cifs.upcall is + sending us a response in an expected form */ + if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) { + cERROR(1, ("incorrect version of cifs.upcall (expected" + " %d but got %d)", + CIFS_SPNEGO_UPCALL_VERSION, msg->version)); + rc = -EKEYREJECTED; + goto ssetup_exit; + } /* bail out if key is too long */ if (msg->sesskey_len > sizeof(ses->server->mac_signing_key.data.krb5)) { -- cgit v1.1 From e9775843ecb039318dbc9ded6da9c762bff28a0b Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 26 Aug 2008 18:22:50 +0000 Subject: [CIFS] Correct keys dependency for cifs kerberos support Must also depend on CIFS ... Signed-off-by: Steve French --- fs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/Kconfig b/fs/Kconfig index f042710..3fab390 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1984,7 +1984,7 @@ config CIFS_EXPERIMENTAL config CIFS_UPCALL bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" - depends on KEYS + depends on CIFS && KEYS help Enables an upcall mechanism for CIFS which accesses userspace helper utilities to provide SPNEGO packaged (RFC 4178) -- cgit v1.1 From 96c2a1137b9e00bcdbe3a95113ea8f42ca994f76 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 26 Aug 2008 18:32:28 +0000 Subject: [CIFS] Reorder cifs config item for better clarity Signed-off-by: Steve French --- fs/Kconfig | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/Kconfig b/fs/Kconfig index 3fab390..abccb5da 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1930,6 +1930,16 @@ config CIFS_WEAK_PW_HASH If unsure, say N. +config CIFS_UPCALL + bool "Kerberos/SPNEGO advanced session setup" + depends on CIFS && KEYS + help + Enables an upcall mechanism for CIFS which accesses + userspace helper utilities to provide SPNEGO packaged (RFC 4178) + Kerberos tickets which are needed to mount to certain secure servers + (for which more secure Kerberos authentication is required). If + unsure, say N. + config CIFS_XATTR bool "CIFS extended attributes" depends on CIFS @@ -1982,16 +1992,6 @@ config CIFS_EXPERIMENTAL (which is disabled by default). See the file fs/cifs/README for more details. If unsure, say N. -config CIFS_UPCALL - bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" - depends on CIFS && KEYS - help - Enables an upcall mechanism for CIFS which accesses - userspace helper utilities to provide SPNEGO packaged (RFC 4178) - Kerberos tickets which are needed to mount to certain secure servers - (for which more secure Kerberos authentication is required). If - unsure, say N. - config CIFS_DFS_UPCALL bool "DFS feature support (EXPERIMENTAL)" depends on CIFS_EXPERIMENTAL -- cgit v1.1 From 48fd4f93a00eac844678629f2f00518e146ed30d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 22 Aug 2008 10:00:36 +0200 Subject: block: submit_bh() inadvertently discards barrier flag on a sync write Reported by Milan Broz , commit 18ce3751 inadvertently made submit_bh() discard the barrier bit for a WRITE_SYNC request. Fix that up. Signed-off-by: Jens Axboe --- fs/buffer.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/buffer.c b/fs/buffer.c index 38653e3..ac78d4c 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2926,14 +2926,17 @@ int submit_bh(int rw, struct buffer_head * bh) BUG_ON(!buffer_mapped(bh)); BUG_ON(!bh->b_end_io); - if (buffer_ordered(bh) && (rw == WRITE)) - rw = WRITE_BARRIER; + /* + * Mask in barrier bit for a write (could be either a WRITE or a + * WRITE_SYNC + */ + if (buffer_ordered(bh) && (rw & WRITE)) + rw |= WRITE_BARRIER; /* - * Only clear out a write error when rewriting, should this - * include WRITE_SYNC as well? + * Only clear out a write error when rewriting */ - if (test_set_buffer_req(bh) && (rw == WRITE || rw == WRITE_BARRIER)) + if (test_set_buffer_req(bh) && (rw & WRITE)) clear_buffer_write_io_error(bh); /* -- cgit v1.1 From 76029ff37f31dad64641489c610d98955217bb68 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 25 Aug 2008 20:36:08 +0200 Subject: bio: fix bio_copy_kern() handling of bio->bv_len The commit 68154e90c9d1492d570671ae181d9a8f8530da55 introduced bio_copy_kern() to add bounce support to blk_rq_map_kern. bio_copy_kern() uses bio->bv_len to copy data for READ commands after the completion but it doesn't work with a request that partially completed. SCSI always completes a PC request as a whole but seems some don't. This patch fixes bio_copy_kern to handle the above case. As bio_copy_user does, bio_copy_kern uses struct bio_map_data to store struct bio_vec. Signed-off-by: FUJITA Tomonori Reported-by: Nix Tested-by: Nix Cc: stable@kernel.org Signed-off-by: Jens Axboe --- fs/bio.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/bio.c b/fs/bio.c index 8000e2f..8b1f5ee 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -469,20 +469,21 @@ static void bio_free_map_data(struct bio_map_data *bmd) kfree(bmd); } -static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count) +static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, + gfp_t gfp_mask) { - struct bio_map_data *bmd = kmalloc(sizeof(*bmd), GFP_KERNEL); + struct bio_map_data *bmd = kmalloc(sizeof(*bmd), gfp_mask); if (!bmd) return NULL; - bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, GFP_KERNEL); + bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, gfp_mask); if (!bmd->iovecs) { kfree(bmd); return NULL; } - bmd->sgvecs = kmalloc(sizeof(struct sg_iovec) * iov_count, GFP_KERNEL); + bmd->sgvecs = kmalloc(sizeof(struct sg_iovec) * iov_count, gfp_mask); if (bmd->sgvecs) return bmd; @@ -596,7 +597,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, len += iov[i].iov_len; } - bmd = bio_alloc_map_data(nr_pages, iov_count); + bmd = bio_alloc_map_data(nr_pages, iov_count, GFP_KERNEL); if (!bmd) return ERR_PTR(-ENOMEM); @@ -942,19 +943,22 @@ static void bio_copy_kern_endio(struct bio *bio, int err) { struct bio_vec *bvec; const int read = bio_data_dir(bio) == READ; - char *p = bio->bi_private; + struct bio_map_data *bmd = bio->bi_private; int i; + char *p = bmd->sgvecs[0].iov_base; __bio_for_each_segment(bvec, bio, i, 0) { char *addr = page_address(bvec->bv_page); + int len = bmd->iovecs[i].bv_len; if (read && !err) - memcpy(p, addr, bvec->bv_len); + memcpy(p, addr, len); __free_page(bvec->bv_page); - p += bvec->bv_len; + p += len; } + bio_free_map_data(bmd); bio_put(bio); } @@ -978,11 +982,21 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, const int nr_pages = end - start; struct bio *bio; struct bio_vec *bvec; + struct bio_map_data *bmd; int i, ret; + struct sg_iovec iov; + + iov.iov_base = data; + iov.iov_len = len; + + bmd = bio_alloc_map_data(nr_pages, 1, gfp_mask); + if (!bmd) + return ERR_PTR(-ENOMEM); + ret = -ENOMEM; bio = bio_alloc(gfp_mask, nr_pages); if (!bio) - return ERR_PTR(-ENOMEM); + goto out_bmd; while (len) { struct page *page; @@ -1016,14 +1030,18 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, } } - bio->bi_private = data; + bio->bi_private = bmd; bio->bi_end_io = bio_copy_kern_endio; + + bio_set_map_data(bmd, bio, &iov, 1); return bio; cleanup: bio_for_each_segment(bvec, bio, i) __free_page(bvec->bv_page); bio_put(bio); +out_bmd: + bio_free_map_data(bmd); return ERR_PTR(ret); } -- cgit v1.1 From aefcc28a3a63ac33a298777aa50ba43641c75241 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 25 Aug 2008 20:36:08 +0200 Subject: bio: fix __bio_copy_iov() handling of bio->bv_len The commit c5dec1c3034f1ae3503efbf641ff3b0273b64797 introduced __bio_copy_iov() to add bounce support to blk_rq_map_user_iov. __bio_copy_iov() uses bio->bv_len to copy data for READ commands after the completion but it doesn't work with a request that partially completed. SCSI always completes a PC request as a whole but seems some don't. Signed-off-by: FUJITA Tomonori Cc: stable@kernel.org Signed-off-by: Jens Axboe --- fs/bio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/bio.c b/fs/bio.c index 8b1f5ee..3cba7ae 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -492,8 +492,8 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, return NULL; } -static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count, - int uncopy) +static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, + struct sg_iovec *iov, int iov_count, int uncopy) { int ret = 0, i; struct bio_vec *bvec; @@ -503,7 +503,7 @@ static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count, __bio_for_each_segment(bvec, bio, i, 0) { char *bv_addr = page_address(bvec->bv_page); - unsigned int bv_len = bvec->bv_len; + unsigned int bv_len = iovecs[i].bv_len; while (bv_len && iov_idx < iov_count) { unsigned int bytes; @@ -555,7 +555,7 @@ int bio_uncopy_user(struct bio *bio) struct bio_map_data *bmd = bio->bi_private; int ret; - ret = __bio_copy_iov(bio, bmd->sgvecs, bmd->nr_sgvecs, 1); + ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, bmd->nr_sgvecs, 1); bio_free_map_data(bmd); bio_put(bio); @@ -634,7 +634,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, * success */ if (!write_to_vm) { - ret = __bio_copy_iov(bio, iov, iov_count, 0); + ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0); if (ret) goto cleanup; } -- cgit v1.1 From 87ed1d65fb536a0cd4e84874c0b038f953e448aa Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 27 Aug 2008 17:53:30 +0000 Subject: [CIFS] Add destroy routine for dns_resolver Otherwise, we're leaking the payload memory. CC: Stable Kernel Acked-by: David Howells Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/CHANGES | 3 ++- fs/cifs/dns_resolve.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 526041a5..f9e4ad9 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -8,7 +8,8 @@ architectures. Fix problems with preserving timestamps on copying open files (e.g. "cp -a") to Windows servers. For mkdir and create honor setgid bit on parent directory when server supports Unix Extensions but not POSIX create. Update cifs.upcall version to handle new Kerberos sec flags -(this requires update of cifs.upcall program from Samba). +(this requires update of cifs.upcall program from Samba). Fix memory leak +on dns_upcall (resolving DFS referralls). Version 1.53 ------------ diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index f730ef3..a2e0673 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c @@ -47,11 +47,18 @@ static int dns_resolver_instantiate(struct key *key, const void *data, return rc; } +static void +dns_resolver_destroy(struct key *key) +{ + kfree(key->payload.data); +} + struct key_type key_type_dns_resolver = { .name = "dns_resolver", .def_datalen = sizeof(struct in_addr), .describe = user_describe, .instantiate = dns_resolver_instantiate, + .destroy = dns_resolver_destroy, .match = user_match, }; -- cgit v1.1