From f112a049712a5c07de25d511c3c6587a2b1a015e Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 30 Sep 2013 09:37:03 +1000 Subject: xfs: lockdep needs to know about 3 dquot-deep nesting Michael Semon reported that xfs/299 generated this lockdep warning: ============================================= [ INFO: possible recursive locking detected ] 3.12.0-rc2+ #2 Not tainted --------------------------------------------- touch/21072 is trying to acquire lock: (&xfs_dquot_other_class){+.+...}, at: [] xfs_trans_dqlockedjoin+0x57/0x64 but task is already holding lock: (&xfs_dquot_other_class){+.+...}, at: [] xfs_trans_dqlockedjoin+0x57/0x64 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&xfs_dquot_other_class); lock(&xfs_dquot_other_class); *** DEADLOCK *** May be due to missing lock nesting notation 7 locks held by touch/21072: #0: (sb_writers#10){++++.+}, at: [] mnt_want_write+0x1e/0x3e #1: (&type->i_mutex_dir_key#4){+.+.+.}, at: [] do_last+0x245/0xe40 #2: (sb_internal#2){++++.+}, at: [] xfs_trans_alloc+0x1f/0x35 #3: (&(&ip->i_lock)->mr_lock/1){+.+...}, at: [] xfs_ilock+0x100/0x1f1 #4: (&(&ip->i_lock)->mr_lock){++++-.}, at: [] xfs_ilock_nowait+0x105/0x22f #5: (&dqp->q_qlock){+.+...}, at: [] xfs_trans_dqlockedjoin+0x57/0x64 #6: (&xfs_dquot_other_class){+.+...}, at: [] xfs_trans_dqlockedjoin+0x57/0x64 The lockdep annotation for dquot lock nesting only understands locking for user and "other" dquots, not user, group and quota dquots. Fix the annotations to match the locking heirarchy we now have. Reported-by: Michael L. Semon Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_dquot.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 71520e6e5d65..1ee776d477c3 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -64,7 +64,8 @@ int xfs_dqerror_mod = 33; struct kmem_zone *xfs_qm_dqtrxzone; static struct kmem_zone *xfs_qm_dqzone; -static struct lock_class_key xfs_dquot_other_class; +static struct lock_class_key xfs_dquot_group_class; +static struct lock_class_key xfs_dquot_project_class; /* * This is called to free all the memory associated with a dquot @@ -703,8 +704,20 @@ xfs_qm_dqread( * Make sure group quotas have a different lock class than user * quotas. */ - if (!(type & XFS_DQ_USER)) - lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class); + switch (type) { + case XFS_DQ_USER: + /* uses the default lock class */ + break; + case XFS_DQ_GROUP: + lockdep_set_class(&dqp->q_qlock, &xfs_dquot_group_class); + break; + case XFS_DQ_PROJ: + lockdep_set_class(&dqp->q_qlock, &xfs_dquot_project_class); + break; + default: + ASSERT(0); + break; + } XFS_STATS_INC(xs_qm_dquot); -- cgit v1.2.3 From 367993e7c6428cb7617ab7653d61dca54e2fdede Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 30 Sep 2013 09:37:04 +1000 Subject: xfs: dirent dtype presence is dependent on directory magic numbers The determination of whether a directory entry contains a dtype field originally was dependent on the filesystem having CRCs enabled. This meant that the format for dtype beign enabled could be determined by checking the directory block magic number rather than doing a feature bit check. This was useful in that it meant that we didn't need to pass a struct xfs_mount around to functions that were already supplied with a directory block header. Unfortunately, the introduction of dtype fields into the v4 structure via a feature bit meant this "use the directory block magic number" method of discriminating the dirent entry sizes is broken. Hence we need to convert the places that use magic number checks to use feature bit checks so that they work correctly and not by chance. The current code works on v4 filesystems only because the dirent size roundup covers the extra byte needed by the dtype field in the places where this problem occurs. Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_dir2_block.c | 6 +++--- fs/xfs/xfs_dir2_format.h | 51 +++++++++++++++++++---------------------------- fs/xfs/xfs_dir2_readdir.c | 4 ++-- fs/xfs/xfs_dir2_sf.c | 6 +++--- 4 files changed, 28 insertions(+), 39 deletions(-) diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 0957aa98b6c0..12dad188939d 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -1158,7 +1158,7 @@ xfs_dir2_sf_to_block( /* * Create entry for . */ - dep = xfs_dir3_data_dot_entry_p(hdr); + dep = xfs_dir3_data_dot_entry_p(mp, hdr); dep->inumber = cpu_to_be64(dp->i_ino); dep->namelen = 1; dep->name[0] = '.'; @@ -1172,7 +1172,7 @@ xfs_dir2_sf_to_block( /* * Create entry for .. */ - dep = xfs_dir3_data_dotdot_entry_p(hdr); + dep = xfs_dir3_data_dotdot_entry_p(mp, hdr); dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp)); dep->namelen = 2; dep->name[0] = dep->name[1] = '.'; @@ -1183,7 +1183,7 @@ xfs_dir2_sf_to_block( blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, (char *)dep - (char *)hdr)); - offset = xfs_dir3_data_first_offset(hdr); + offset = xfs_dir3_data_first_offset(mp); /* * Loop over existing entries, stuff them in. */ diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h index a0961a61ac1a..9cf67381adf6 100644 --- a/fs/xfs/xfs_dir2_format.h +++ b/fs/xfs/xfs_dir2_format.h @@ -497,69 +497,58 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) /* * Offsets of . and .. in data space (always block 0) * - * The macros are used for shortform directories as they have no headers to read - * the magic number out of. Shortform directories need to know the size of the - * data block header because the sfe embeds the block offset of the entry into - * it so that it doesn't change when format conversion occurs. Bad Things Happen - * if we don't follow this rule. - * * XXX: there is scope for significant optimisation of the logic here. Right * now we are checking for "dir3 format" over and over again. Ideally we should * only do it once for each operation. */ -#define XFS_DIR3_DATA_DOT_OFFSET(mp) \ - xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&(mp)->m_sb)) -#define XFS_DIR3_DATA_DOTDOT_OFFSET(mp) \ - (XFS_DIR3_DATA_DOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 1)) -#define XFS_DIR3_DATA_FIRST_OFFSET(mp) \ - (XFS_DIR3_DATA_DOTDOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 2)) - static inline xfs_dir2_data_aoff_t -xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr) +xfs_dir3_data_dot_offset(struct xfs_mount *mp) { - return xfs_dir3_data_entry_offset(hdr); + return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)); } static inline xfs_dir2_data_aoff_t -xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr) +xfs_dir3_data_dotdot_offset(struct xfs_mount *mp) { - bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || - hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); - return xfs_dir3_data_dot_offset(hdr) + - __xfs_dir3_data_entsize(dir3, 1); + return xfs_dir3_data_dot_offset(mp) + + xfs_dir3_data_entsize(mp, 1); } static inline xfs_dir2_data_aoff_t -xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr) +xfs_dir3_data_first_offset(struct xfs_mount *mp) { - bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || - hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); - return xfs_dir3_data_dotdot_offset(hdr) + - __xfs_dir3_data_entsize(dir3, 2); + return xfs_dir3_data_dotdot_offset(mp) + + xfs_dir3_data_entsize(mp, 2); } /* * location of . and .. in data space (always block 0) */ static inline struct xfs_dir2_data_entry * -xfs_dir3_data_dot_entry_p(struct xfs_dir2_data_hdr *hdr) +xfs_dir3_data_dot_entry_p( + struct xfs_mount *mp, + struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_dot_offset(hdr)); + ((char *)hdr + xfs_dir3_data_dot_offset(mp)); } static inline struct xfs_dir2_data_entry * -xfs_dir3_data_dotdot_entry_p(struct xfs_dir2_data_hdr *hdr) +xfs_dir3_data_dotdot_entry_p( + struct xfs_mount *mp, + struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_dotdot_offset(hdr)); + ((char *)hdr + xfs_dir3_data_dotdot_offset(mp)); } static inline struct xfs_dir2_data_entry * -xfs_dir3_data_first_entry_p(struct xfs_dir2_data_hdr *hdr) +xfs_dir3_data_first_entry_p( + struct xfs_mount *mp, + struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_first_offset(hdr)); + ((char *)hdr + xfs_dir3_data_first_offset(mp)); } /* diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 8993ec17452c..8f84153e98a8 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -119,9 +119,9 @@ xfs_dir2_sf_getdents( * mp->m_dirdatablk. */ dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, - XFS_DIR3_DATA_DOT_OFFSET(mp)); + xfs_dir3_data_dot_offset(mp)); dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, - XFS_DIR3_DATA_DOTDOT_OFFSET(mp)); + xfs_dir3_data_dotdot_offset(mp)); /* * Put . entry unless we're starting past it. diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index bb6e2848f473..3ef6d402084c 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -557,7 +557,7 @@ xfs_dir2_sf_addname_hard( * to insert the new entry. * If it's going to end up at the end then oldsfep will point there. */ - for (offset = XFS_DIR3_DATA_FIRST_OFFSET(mp), + for (offset = xfs_dir3_data_first_offset(mp), oldsfep = xfs_dir2_sf_firstentry(oldsfp), add_datasize = xfs_dir3_data_entsize(mp, args->namelen), eof = (char *)oldsfep == &buf[old_isize]; @@ -640,7 +640,7 @@ xfs_dir2_sf_addname_pick( sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; size = xfs_dir3_data_entsize(mp, args->namelen); - offset = XFS_DIR3_DATA_FIRST_OFFSET(mp); + offset = xfs_dir3_data_first_offset(mp); sfep = xfs_dir2_sf_firstentry(sfp); holefit = 0; /* @@ -713,7 +713,7 @@ xfs_dir2_sf_check( mp = dp->i_mount; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; - offset = XFS_DIR3_DATA_FIRST_OFFSET(mp); + offset = xfs_dir3_data_first_offset(mp); ino = xfs_dir2_sf_get_parent_ino(sfp); i8count = ino > XFS_DIR2_MAX_SHORT_INUM; -- cgit v1.2.3 From 519ccb81ac1c8e3e4eed294acf93be00b43dcad6 Mon Sep 17 00:00:00 2001 From: "tinguely@sgi.com" Date: Fri, 27 Sep 2013 09:00:55 -0500 Subject: xfs: fix memory leak in xlog_recover_add_to_trans Free the memory in error path of xlog_recover_add_to_trans(). Normally this memory is freed in recovery pass2, but is leaked in the error path. Signed-off-by: Mark Tinguely Reviewed-by: Eric Sandeen Signed-off-by: Ben Myers --- fs/xfs/xfs_log_recover.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index cc179878fe41..43240583fd5b 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -1585,6 +1585,7 @@ xlog_recover_add_to_trans( "bad number of regions (%d) in inode log format", in_f->ilf_size); ASSERT(0); + free(ptr); return XFS_ERROR(EIO); } -- cgit v1.2.3 From aaaae98022efa4f3c31042f1fdf9e7a0c5f04663 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 1 Oct 2013 16:47:53 +0200 Subject: xfs: Use kmem_free() instead of free() This fixes a build failure caused by calling the free() function which does not exist in the Linux kernel. Signed-off-by: Thierry Reding Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers --- fs/xfs/xfs_log_recover.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 43240583fd5b..39797490a1f1 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -1585,7 +1585,7 @@ xlog_recover_add_to_trans( "bad number of regions (%d) in inode log format", in_f->ilf_size); ASSERT(0); - free(ptr); + kmem_free(ptr); return XFS_ERROR(EIO); } -- cgit v1.2.3 From 0799a3e808e5543235bcdfe9d1fa1572e0e86ab5 Mon Sep 17 00:00:00 2001 From: Jie Liu Date: Sun, 29 Sep 2013 18:56:04 +0800 Subject: xfs: get rid of count from xfs_iomap_write_allocate() Get rid of function variable count from xfs_iomap_write_allocate() as it is unused. Additionally, checkpatch warn me of the following for this change: WARNING: extern prototypes should be avoided in .h files +extern int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, So this patch also remove all extern function prototypes at xfs_iomap.h to suppress it to make this code style in consistent manner in this file. Signed-off-by: Jie Liu Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_aops.c | 2 +- fs/xfs/xfs_iomap.c | 1 - fs/xfs/xfs_iomap.h | 8 ++++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index e51e581454e9..f3f95f094af8 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -333,7 +333,7 @@ xfs_map_blocks( if (type == XFS_IO_DELALLOC && (!nimaps || isnullstartblock(imap->br_startblock))) { - error = xfs_iomap_write_allocate(ip, offset, count, imap); + error = xfs_iomap_write_allocate(ip, offset, imap); if (!error) trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); return -XFS_ERROR(error); diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 8d4d49b6fbf3..521fdf2ac6da 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -655,7 +655,6 @@ int xfs_iomap_write_allocate( xfs_inode_t *ip, xfs_off_t offset, - size_t count, xfs_bmbt_irec_t *imap) { xfs_mount_t *mp = ip->i_mount; diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index 80615760959a..411fbb8919ef 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h @@ -21,12 +21,12 @@ struct xfs_inode; struct xfs_bmbt_irec; -extern int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t, +int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t, struct xfs_bmbt_irec *, int); -extern int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, +int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, struct xfs_bmbt_irec *); -extern int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, size_t, +int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, struct xfs_bmbt_irec *); -extern int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, size_t); +int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, size_t); #endif /* __XFS_IOMAP_H__*/ -- cgit v1.2.3 From 17ec81c15fd022842f9bc947841ba9fb9eb52591 Mon Sep 17 00:00:00 2001 From: Jie Liu Date: Sun, 22 Sep 2013 16:25:15 +0800 Subject: xfs: fix the wrong new_size/rnew_size at xfs_iext_realloc_direct() At xfs_iext_realloc_direct(), the new_size is changed by adding if_bytes if originally the extent records are stored at the inline extent buffer, and we have to switch from it to a direct extent list for those new allocated extents, this is wrong. e.g, Create a file with three extents which was showing as following, xfs_io -f -c "truncate 100m" /xfs/testme for i in $(seq 0 5 10); do offset=$(($i * $((1 << 20)))) xfs_io -c "pwrite $offset 1m" /xfs/testme done Inline ------ irec: if_bytes bytes_diff new_size 1st 0 16 16 2nd 16 16 32 Switching --------- rnew_size 3rd 32 16 48 + 32 = 80 roundup=128 In this case, the desired value of new_size should be 48, and then it will be roundup to 64 and be assigned to rnew_size. However, this issue has been covered by resetting the if_bytes to the new_size which is calculated at the begnning of xfs_iext_add() before leaving out this function, and in turn make the rnew_size correctly again. Hence, this can not be detected via xfstestes. This patch fix above problem and revise the new_size comments at xfs_iext_realloc_direct() to make it more readable. Also, fix the comments while switching from the inline extent buffer to a direct extent list to reflect this change. Signed-off-by: Jie Liu Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_inode_fork.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/fs/xfs/xfs_inode_fork.c b/fs/xfs/xfs_inode_fork.c index 02f1083955bb..4fa56fcb38d1 100644 --- a/fs/xfs/xfs_inode_fork.c +++ b/fs/xfs/xfs_inode_fork.c @@ -1359,7 +1359,7 @@ xfs_iext_remove_indirect( void xfs_iext_realloc_direct( xfs_ifork_t *ifp, /* inode fork pointer */ - int new_size) /* new size of extents */ + int new_size) /* new size of extents after adding */ { int rnew_size; /* real new size of extents */ @@ -1397,13 +1397,8 @@ xfs_iext_realloc_direct( rnew_size - ifp->if_real_bytes); } } - /* - * Switch from the inline extent buffer to a direct - * extent list. Be sure to include the inline extent - * bytes in new_size. - */ + /* Switch from the inline extent buffer to a direct extent list */ else { - new_size += ifp->if_bytes; if (!is_power_of_2(new_size)) { rnew_size = roundup_pow_of_two(new_size); } -- cgit v1.2.3 From d948709b8e468510d8c855d1e4c9f1cb7b524880 Mon Sep 17 00:00:00 2001 From: Ben Myers Date: Tue, 10 Sep 2013 18:11:22 -0500 Subject: xfs: remove usage of is_bad_inode XFS never calls mark_inode_bad or iget_failed, so it will never see a bad inode. Remove all checks for is_bad_inode because they are unnecessary. Signed-off-by: Ben Myers Reviewed-by: Dave Chinner --- fs/xfs/xfs_icache.c | 7 ------- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_super.c | 9 --------- 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 474807a401c8..76a4ecd638c3 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -500,11 +500,6 @@ xfs_inode_ag_walk_grab( if (!igrab(inode)) return ENOENT; - if (is_bad_inode(inode)) { - IRELE(ip); - return ENOENT; - } - /* inode is valid */ return 0; @@ -918,8 +913,6 @@ restart: xfs_iflock(ip); } - if (is_bad_inode(VFS_I(ip))) - goto reclaim; if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { xfs_iunpin_wait(ip); xfs_iflush_abort(ip, false); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index e3d75385aa76..5ac716b2df22 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1687,7 +1687,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 || is_bad_inode(VFS_I(ip))) { + if (ip->i_d.di_mode == 0) { ASSERT(ip->i_df.if_real_bytes == 0); ASSERT(ip->i_df.if_broot_bytes == 0); return VN_INACTIVE_CACHE; diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 15188cc99449..938e50fe6c61 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -946,10 +946,6 @@ xfs_fs_destroy_inode( XFS_STATS_INC(vn_reclaim); - /* bad inode, get out here ASAP */ - if (is_bad_inode(inode)) - goto out_reclaim; - ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); /* @@ -965,7 +961,6 @@ xfs_fs_destroy_inode( * this more efficiently than we can here, so simply let background * reclaim tear down all inodes. */ -out_reclaim: xfs_inode_set_reclaim_tag(ip); } @@ -1491,10 +1486,6 @@ xfs_fs_fill_super( error = ENOENT; goto out_unmount; } - if (is_bad_inode(root)) { - error = EINVAL; - goto out_unmount; - } sb->s_root = d_make_root(root); if (!sb->s_root) { error = ENOMEM; -- cgit v1.2.3 From 2900a579abcea13e4e77c40f89eb16eeecb5508e Mon Sep 17 00:00:00 2001 From: Mark Tinguely Date: Wed, 2 Oct 2013 16:00:06 -0500 Subject: xfs: add the inode directory type support to XFS_IOC_FSGEOM Add the inode type directory type support to XFS_IOC_FSGEOM so that xfs_repair/xfs_info knows if the superblock v4 filesystem enabled the feature. Signed-off-by: Mark Tinguely Reviewed-by: Carlos Maiolino Signed-off-by: Ben Myers --- fs/xfs/xfs_fs.h | 4 ++-- fs/xfs/xfs_fsops.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index 18272c766a50..c5fc116dfaa3 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h @@ -233,11 +233,11 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */ #define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */ #define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */ -#define XFS_FSOP_GEOM_FLAGS_PROJID32 0x0800 /* 32-bit project IDs */ +#define XFS_FSOP_GEOM_FLAGS_PROJID32 0x0800 /* 32-bit project IDs */ #define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */ #define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */ #define XFS_FSOP_GEOM_FLAGS_V5SB 0x8000 /* version 5 superblock */ - +#define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ /* * Minimum and maximum sizes need for growth checks. diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index e64ee5288b86..fdae4ec5f21b 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -101,7 +101,9 @@ xfs_fs_geometry( (xfs_sb_version_hasprojid32bit(&mp->m_sb) ? XFS_FSOP_GEOM_FLAGS_PROJID32 : 0) | (xfs_sb_version_hascrc(&mp->m_sb) ? - XFS_FSOP_GEOM_FLAGS_V5SB : 0); + XFS_FSOP_GEOM_FLAGS_V5SB : 0) | + (xfs_sb_version_hasftype(&mp->m_sb) ? + XFS_FSOP_GEOM_FLAGS_FTYPE : 0); geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? mp->m_sb.sb_logsectsize : BBSIZE; geo->rtsectsize = mp->m_sb.sb_blocksize; -- cgit v1.2.3 From 36b21dde6e899d2f25077b7c239d2d6bcff17d73 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Fri, 20 Sep 2013 11:06:09 -0400 Subject: xfs: push down inactive transaction mgmt for remote symlinks Push down the transaction management for remote symlinks from xfs_inactive() down to xfs_inactive_symlink_rmt(). The latter is cleaned up to avoid transaction management intended for the calling context (i.e., trans duplication, reservation, item attachment). Signed-off-by: Brian Foster Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_inode.c | 15 ++++----- fs/xfs/xfs_symlink.c | 86 ++++++++++++++++++++++++---------------------------- fs/xfs/xfs_symlink.h | 2 +- 3 files changed, 49 insertions(+), 54 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 5ac716b2df22..c26990b50941 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1724,9 +1724,14 @@ xfs_inactive( if (error) return VN_INACTIVE_CACHE; + if (S_ISLNK(ip->i_d.di_mode)) { + error = xfs_inactive_symlink(ip); + if (error) + goto out; + } + tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - resp = (truncate || S_ISLNK(ip->i_d.di_mode)) ? - &M_RES(mp)->tr_itruncate : &M_RES(mp)->tr_ifree; + resp = truncate ? &M_RES(mp)->tr_itruncate : &M_RES(mp)->tr_ifree; error = xfs_trans_reserve(tp, resp, 0, 0); if (error) { @@ -1738,11 +1743,7 @@ xfs_inactive( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - if (S_ISLNK(ip->i_d.di_mode)) { - error = xfs_inactive_symlink(ip, &tp); - if (error) - goto out_cancel; - } else if (truncate) { + if (truncate) { ip->i_d.di_size = 0; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index f622a97a7e33..ded282b10bc2 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -424,8 +424,7 @@ xfs_symlink( */ STATIC int xfs_inactive_symlink_rmt( - xfs_inode_t *ip, - xfs_trans_t **tpp) + struct xfs_inode *ip) { xfs_buf_t *bp; int committed; @@ -437,11 +436,9 @@ xfs_inactive_symlink_rmt( xfs_mount_t *mp; xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS]; int nmaps; - xfs_trans_t *ntp; int size; xfs_trans_t *tp; - tp = *tpp; mp = ip->i_mount; ASSERT(ip->i_df.if_flags & XFS_IFEXTENTS); /* @@ -453,6 +450,16 @@ xfs_inactive_symlink_rmt( */ ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2); + tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); + if (error) { + xfs_trans_cancel(tp, 0); + return error; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); + /* * Lock the inode, fix the size, and join it to the transaction. * Hold it so in the normal path, we still have it locked for @@ -471,7 +478,7 @@ xfs_inactive_symlink_rmt( error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size), mval, &nmaps, 0); if (error) - goto error0; + goto error_trans_cancel; /* * Invalidate the block(s). No validation is done. */ @@ -481,22 +488,24 @@ xfs_inactive_symlink_rmt( XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0); if (!bp) { error = ENOMEM; - goto error1; + goto error_bmap_cancel; } xfs_trans_binval(tp, bp); } /* * Unmap the dead block(s) to the free_list. */ - if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, - &first_block, &free_list, &done))) - goto error1; + error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, + &first_block, &free_list, &done); + if (error) + goto error_bmap_cancel; ASSERT(done); /* * Commit the first transaction. This logs the EFI and the inode. */ - if ((error = xfs_bmap_finish(&tp, &free_list, &committed))) - goto error1; + error = xfs_bmap_finish(&tp, &free_list, &committed); + if (error) + goto error_bmap_cancel; /* * The transaction must have been committed, since there were * actually extents freed by xfs_bunmapi. See xfs_bmap_finish. @@ -510,27 +519,14 @@ xfs_inactive_symlink_rmt( */ xfs_trans_ijoin(tp, ip, 0); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - /* - * Get a new, empty transaction to return to our caller. - */ - ntp = xfs_trans_dup(tp); /* * Commit the transaction containing extent freeing and EFDs. - * If we get an error on the commit here or on the reserve below, - * we need to unlock the inode since the new transaction doesn't - * have the inode attached. */ - error = xfs_trans_commit(tp, 0); - tp = ntp; + error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); if (error) { ASSERT(XFS_FORCED_SHUTDOWN(mp)); - goto error0; + goto error_unlock; } - /* - * transaction commit worked ok so we can drop the extra ticket - * reference that we gained in xfs_trans_dup() - */ - xfs_log_ticket_put(tp->t_ticket); /* * Remove the memory for extent descriptions (just bookkeeping). @@ -538,23 +534,16 @@ xfs_inactive_symlink_rmt( if (ip->i_df.if_bytes) xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK); ASSERT(ip->i_df.if_bytes == 0); - /* - * Put an itruncate log reservation in the new transaction - * for our caller. - */ - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); - if (error) { - ASSERT(XFS_FORCED_SHUTDOWN(mp)); - goto error0; - } - xfs_trans_ijoin(tp, ip, 0); - *tpp = tp; + xfs_iunlock(ip, XFS_ILOCK_EXCL); return 0; - error1: +error_bmap_cancel: xfs_bmap_cancel(&free_list); - error0: +error_trans_cancel: + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); +error_unlock: + xfs_iunlock(ip, XFS_ILOCK_EXCL); return error; } @@ -563,41 +552,46 @@ xfs_inactive_symlink_rmt( */ int xfs_inactive_symlink( - struct xfs_inode *ip, - struct xfs_trans **tp) + struct xfs_inode *ip) { struct xfs_mount *mp = ip->i_mount; int pathlen; trace_xfs_inactive_symlink(ip); - ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); - if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); + xfs_ilock(ip, XFS_ILOCK_EXCL); + /* * Zero length symlinks _can_ exist. */ pathlen = (int)ip->i_d.di_size; - if (!pathlen) + if (!pathlen) { + xfs_iunlock(ip, XFS_ILOCK_EXCL); return 0; + } if (pathlen < 0 || pathlen > MAXPATHLEN) { xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)", __func__, (unsigned long long)ip->i_ino, pathlen); + xfs_iunlock(ip, XFS_ILOCK_EXCL); ASSERT(0); return XFS_ERROR(EFSCORRUPTED); } if (ip->i_df.if_flags & XFS_IFINLINE) { - if (ip->i_df.if_bytes > 0) + if (ip->i_df.if_bytes > 0) xfs_idata_realloc(ip, -(ip->i_df.if_bytes), XFS_DATA_FORK); + xfs_iunlock(ip, XFS_ILOCK_EXCL); ASSERT(ip->i_df.if_bytes == 0); return 0; } + xfs_iunlock(ip, XFS_ILOCK_EXCL); + /* remove the remote symlink */ - return xfs_inactive_symlink_rmt(ip, tp); + return xfs_inactive_symlink_rmt(ip); } diff --git a/fs/xfs/xfs_symlink.h b/fs/xfs/xfs_symlink.h index 99338ba666ac..e75245d09116 100644 --- a/fs/xfs/xfs_symlink.h +++ b/fs/xfs/xfs_symlink.h @@ -22,6 +22,6 @@ int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, const char *target_path, umode_t mode, struct xfs_inode **ipp); int xfs_readlink(struct xfs_inode *ip, char *link); -int xfs_inactive_symlink(struct xfs_inode *ip, struct xfs_trans **tpp); +int xfs_inactive_symlink(struct xfs_inode *ip); #endif /* __XFS_SYMLINK_H */ -- cgit v1.2.3 From f7be2d7f594cbc7a00902b5427332a1ad519a528 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Fri, 20 Sep 2013 11:06:10 -0400 Subject: xfs: push down inactive transaction mgmt for truncate Create the new xfs_inactive_truncate() function to handle the truncate portion of xfs_inactive(). Push the locking and transaction management into the new function. Signed-off-by: Brian Foster Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_inode.c | 117 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 49 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c26990b50941..7b86f643046b 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1662,6 +1662,58 @@ xfs_release( return 0; } +/* + * xfs_inactive_truncate + * + * Called to perform a truncate when an inode becomes unlinked. + */ +STATIC int +xfs_inactive_truncate( + struct xfs_inode *ip) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + int error; + + tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); + if (error) { + ASSERT(XFS_FORCED_SHUTDOWN(mp)); + xfs_trans_cancel(tp, 0); + return error; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); + + /* + * Log the inode size first to prevent stale data exposure in the event + * of a system crash before the truncate completes. See the related + * comment in xfs_setattr_size() for details. + */ + ip->i_d.di_size = 0; + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + + error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0); + if (error) + goto error_trans_cancel; + + ASSERT(ip->i_d.di_nextents == 0); + + error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); + if (error) + goto error_unlock; + + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return 0; + +error_trans_cancel: + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); +error_unlock: + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return error; +} + /* * xfs_inactive * @@ -1679,7 +1731,6 @@ xfs_inactive( int committed; struct xfs_trans *tp; struct xfs_mount *mp; - struct xfs_trans_res *resp; int error; int truncate = 0; @@ -1724,35 +1775,12 @@ xfs_inactive( if (error) return VN_INACTIVE_CACHE; - if (S_ISLNK(ip->i_d.di_mode)) { + if (S_ISLNK(ip->i_d.di_mode)) error = xfs_inactive_symlink(ip); - if (error) - goto out; - } - - tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - resp = truncate ? &M_RES(mp)->tr_itruncate : &M_RES(mp)->tr_ifree; - - error = xfs_trans_reserve(tp, resp, 0, 0); - if (error) { - ASSERT(XFS_FORCED_SHUTDOWN(mp)); - xfs_trans_cancel(tp, 0); - return VN_INACTIVE_CACHE; - } - - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, 0); - - if (truncate) { - ip->i_d.di_size = 0; - xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - - error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0); - if (error) - goto out_cancel; - - ASSERT(ip->i_d.di_nextents == 0); - } + else if (truncate) + error = xfs_inactive_truncate(ip); + if (error) + goto out; /* * If there are attributes associated with the file then blow them away @@ -1763,25 +1791,9 @@ xfs_inactive( if (ip->i_d.di_anextents > 0) { ASSERT(ip->i_d.di_forkoff != 0); - error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); - if (error) - goto out_unlock; - - xfs_iunlock(ip, XFS_ILOCK_EXCL); - error = xfs_attr_inactive(ip); if (error) goto out; - - tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0); - if (error) { - xfs_trans_cancel(tp, 0); - goto out; - } - - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, 0); } if (ip->i_afp) @@ -1789,6 +1801,17 @@ xfs_inactive( ASSERT(ip->i_d.di_anextents == 0); + tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0); + if (error) { + ASSERT(XFS_FORCED_SHUTDOWN(mp)); + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); + goto out; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); + /* * Free the inode. */ @@ -1831,13 +1854,9 @@ xfs_inactive( * Release the dquots held by inode, if any. */ xfs_qm_dqdetach(ip); -out_unlock: xfs_iunlock(ip, XFS_ILOCK_EXCL); out: return VN_INACTIVE_CACHE; -out_cancel: - xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); - goto out_unlock; } /* -- cgit v1.2.3 From 88877d2b9727a14431bfe48216ff86331ab47ea5 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Fri, 20 Sep 2013 11:06:11 -0400 Subject: xfs: push down inactive transaction mgmt for ifree Push the inode free work performed during xfs_inactive() down into a new xfs_inactive_ifree() helper. This clears xfs_inactive() from all inode locking and transaction management more directly associated with freeing the inode xattrs, extents and the inode itself. Signed-off-by: Brian Foster Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_inode.c | 121 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 50 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 7b86f643046b..223d1a163b2d 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1714,6 +1714,74 @@ error_unlock: return error; } +/* + * xfs_inactive_ifree() + * + * Perform the inode free when an inode is unlinked. + */ +STATIC int +xfs_inactive_ifree( + struct xfs_inode *ip) +{ + xfs_bmap_free_t free_list; + xfs_fsblock_t first_block; + int committed; + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + int error; + + tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0); + if (error) { + ASSERT(XFS_FORCED_SHUTDOWN(mp)); + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); + return error; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); + + xfs_bmap_init(&free_list, &first_block); + error = xfs_ifree(tp, ip, &free_list); + if (error) { + /* + * If we fail to free the inode, shut down. The cancel + * might do that, we need to make sure. Otherwise the + * inode might be lost for a long time or forever. + */ + if (!XFS_FORCED_SHUTDOWN(mp)) { + xfs_notice(mp, "%s: xfs_ifree returned error %d", + __func__, error); + xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); + } + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return error; + } + + /* + * Credit the quota account(s). The inode is gone. + */ + xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1); + + /* + * Just ignore errors at this point. There is nothing we can + * do except to try to keep going. Make sure it's not a silent + * error. + */ + error = xfs_bmap_finish(&tp, &free_list, &committed); + if (error) + xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", + __func__, error); + error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); + if (error) + xfs_notice(mp, "%s: xfs_trans_commit returned error %d", + __func__, error); + + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return 0; +} + /* * xfs_inactive * @@ -1726,10 +1794,6 @@ int xfs_inactive( xfs_inode_t *ip) { - xfs_bmap_free_t free_list; - xfs_fsblock_t first_block; - int committed; - struct xfs_trans *tp; struct xfs_mount *mp; int error; int truncate = 0; @@ -1801,60 +1865,17 @@ xfs_inactive( ASSERT(ip->i_d.di_anextents == 0); - tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0); - if (error) { - ASSERT(XFS_FORCED_SHUTDOWN(mp)); - xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); - goto out; - } - - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, 0); - /* * Free the inode. */ - xfs_bmap_init(&free_list, &first_block); - error = xfs_ifree(tp, ip, &free_list); - if (error) { - /* - * If we fail to free the inode, shut down. The cancel - * might do that, we need to make sure. Otherwise the - * inode might be lost for a long time or forever. - */ - if (!XFS_FORCED_SHUTDOWN(mp)) { - xfs_notice(mp, "%s: xfs_ifree returned error %d", - __func__, error); - xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); - } - xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); - } else { - /* - * Credit the quota account(s). The inode is gone. - */ - xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1); - - /* - * Just ignore errors at this point. There is nothing we can - * do except to try to keep going. Make sure it's not a silent - * error. - */ - error = xfs_bmap_finish(&tp, &free_list, &committed); - if (error) - xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", - __func__, error); - error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); - if (error) - xfs_notice(mp, "%s: xfs_trans_commit returned error %d", - __func__, error); - } + error = xfs_inactive_ifree(ip); + if (error) + goto out; /* * Release the dquots held by inode, if any. */ xfs_qm_dqdetach(ip); - xfs_iunlock(ip, XFS_ILOCK_EXCL); out: return VN_INACTIVE_CACHE; } -- cgit v1.2.3 From 74564fb48cbfcb5b433c1baec1f3158ea638b203 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Fri, 20 Sep 2013 11:06:12 -0400 Subject: xfs: clean up xfs_inactive() error handling, kill VN_INACTIVE_[NO]CACHE The xfs_inactive() return value is meaningless. Turn xfs_inactive() into a void function and clean up the error handling appropriately. Kill the VN_INACTIVE_[NO]CACHE directives as they are not relevant to Linux. Signed-off-by: Brian Foster Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_inode.c | 28 +++++++++++----------------- fs/xfs/xfs_inode.h | 2 +- fs/xfs/xfs_vnode.h | 8 -------- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 223d1a163b2d..5fce7261a64b 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1790,7 +1790,7 @@ xfs_inactive_ifree( * now be truncated. Also, we clear all of the read-ahead state * kept for the inode here since the file is now closed. */ -int +void xfs_inactive( xfs_inode_t *ip) { @@ -1805,16 +1805,14 @@ xfs_inactive( if (ip->i_d.di_mode == 0) { ASSERT(ip->i_df.if_real_bytes == 0); ASSERT(ip->i_df.if_broot_bytes == 0); - return VN_INACTIVE_CACHE; + return; } mp = ip->i_mount; - error = 0; - /* If this is a read-only mount, don't do this (would generate I/O) */ if (mp->m_flags & XFS_MOUNT_RDONLY) - goto out; + return; if (ip->i_d.di_nlink != 0) { /* @@ -1822,12 +1820,10 @@ xfs_inactive( * cache. Post-eof blocks must be freed, lest we end up with * broken free space accounting. */ - if (xfs_can_free_eofblocks(ip, true)) { - error = xfs_free_eofblocks(mp, ip, false); - if (error) - return VN_INACTIVE_CACHE; - } - goto out; + if (xfs_can_free_eofblocks(ip, true)) + xfs_free_eofblocks(mp, ip, false); + + return; } if (S_ISREG(ip->i_d.di_mode) && @@ -1837,14 +1833,14 @@ xfs_inactive( error = xfs_qm_dqattach(ip, 0); if (error) - return VN_INACTIVE_CACHE; + return; if (S_ISLNK(ip->i_d.di_mode)) error = xfs_inactive_symlink(ip); else if (truncate) error = xfs_inactive_truncate(ip); if (error) - goto out; + return; /* * If there are attributes associated with the file then blow them away @@ -1857,7 +1853,7 @@ xfs_inactive( error = xfs_attr_inactive(ip); if (error) - goto out; + return; } if (ip->i_afp) @@ -1870,14 +1866,12 @@ xfs_inactive( */ error = xfs_inactive_ifree(ip); if (error) - goto out; + return; /* * Release the dquots held by inode, if any. */ xfs_qm_dqdetach(ip); -out: - return VN_INACTIVE_CACHE; } /* diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 4a91358c1470..cce62ce1a73a 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -316,7 +316,7 @@ static inline int xfs_isiflocked(struct xfs_inode *ip) int xfs_release(struct xfs_inode *ip); -int xfs_inactive(struct xfs_inode *ip); +void xfs_inactive(struct xfs_inode *ip); int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode **ipp, struct xfs_name *ci_name); int xfs_create(struct xfs_inode *dp, struct xfs_name *name, diff --git a/fs/xfs/xfs_vnode.h b/fs/xfs/xfs_vnode.h index db14d0c08682..3e8e797c6d11 100644 --- a/fs/xfs/xfs_vnode.h +++ b/fs/xfs/xfs_vnode.h @@ -24,14 +24,6 @@ struct file; struct xfs_inode; struct attrlist_cursor_kern; -/* - * 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. - */ -#define VN_INACTIVE_CACHE 0 -#define VN_INACTIVE_NOCACHE 1 - /* * Flags for read/write calls - same values as IRIX */ -- cgit v1.2.3 From 2c6e24ce1aa6b3b147c75d488c2797ee258eb22b Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 15 Oct 2013 09:17:49 +1100 Subject: xfs: prevent deadlock trying to cover an active log Recent analysis of a deadlocked XFS filesystem from a kernel crash dump indicated that the filesystem was stuck waiting for log space. The short story of the hang on the RHEL6 kernel is this: - the tail of the log is pinned by an inode - the inode has been pushed by the xfsaild - the inode has been flushed to it's backing buffer and is currently flush locked and hence waiting for backing buffer IO to complete and remove it from the AIL - the backing buffer is marked for write - it is on the delayed write queue - the inode buffer has been modified directly and logged recently due to unlinked inode list modification - the backing buffer is pinned in memory as it is in the active CIL context. - the xfsbufd won't start buffer writeback because it is pinned - xfssyncd won't force the log because it sees the log as needing to be covered and hence wants to issue a dummy transaction to move the log covering state machine along. Hence there is no trigger to force the CIL to the log and hence unpin the inode buffer and therefore complete the inode IO, remove it from the AIL and hence move the tail of the log along, allowing transactions to start again. Mainline kernels also have the same deadlock, though the signature is slightly different - the inode buffer never reaches the delayed write lists because xfs_buf_item_push() sees that it is pinned and hence never adds it to the delayed write list that the xfsaild flushes. There are two possible solutions here. The first is to simply force the log before trying to cover the log and so ensure that the CIL is emptied before we try to reserve space for the dummy transaction in the xfs_log_worker(). While this might work most of the time, it is still racy and is no guarantee that we don't get stuck in xfs_trans_reserve waiting for log space to come free. Hence it's not the best way to solve the problem. The second solution is to modify xfs_log_need_covered() to be aware of the CIL. We only should be attempting to cover the log if there is no current activity in the log - covering the log is the process of ensuring that the head and tail in the log on disk are identical (i.e. the log is clean and at idle). Hence, by definition, if there are items in the CIL then the log is not at idle and so we don't need to attempt to cover it. When we don't need to cover the log because it is active or idle, we issue a log force from xfs_log_worker() - if the log is idle, then this does nothing. However, if the log is active due to there being items in the CIL, it will force the items in the CIL to the log and unpin them. In the case of the above deadlock scenario, instead of xfs_log_worker() getting stuck in xfs_trans_reserve() attempting to cover the log, it will instead force the log, thereby unpinning the inode buffer, allowing IO to be issued and complete and hence removing the inode that was pinning the tail of the log from the AIL. At that point, everything will start moving along again. i.e. the xfs_log_worker turns back into a watchdog that can alleviate deadlocks based around pinned items that prevent the tail of the log from being moved... Signed-off-by: Dave Chinner Reviewed-by: Eric Sandeen Signed-off-by: Ben Myers --- fs/xfs/xfs_log.c | 48 +++++++++++++++++++++++++++++------------------- fs/xfs/xfs_log_cil.c | 14 ++++++++++++++ fs/xfs/xfs_log_priv.h | 10 ++++------ 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index a2dea108071a..613ed9414e70 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1000,27 +1000,34 @@ xfs_log_space_wake( } /* - * Determine if we have a transaction that has gone to disk - * that needs to be covered. To begin the transition to the idle state - * firstly the log needs to be idle (no AIL and nothing in the iclogs). - * If we are then in a state where covering is needed, the caller is informed - * that dummy transactions are required to move the log into the idle state. + * Determine if we have a transaction that has gone to disk that needs to be + * covered. To begin the transition to the idle state firstly the log needs to + * be idle. That means the CIL, the AIL and the iclogs needs to be empty before + * we start attempting to cover the log. * - * Because this is called as part of the sync process, we should also indicate - * that dummy transactions should be issued in anything but the covered or - * idle states. This ensures that the log tail is accurately reflected in - * the log at the end of the sync, hence if a crash occurrs avoids replay - * of transactions where the metadata is already on disk. + * Only if we are then in a state where covering is needed, the caller is + * informed that dummy transactions are required to move the log into the idle + * state. + * + * If there are any items in the AIl or CIL, then we do not want to attempt to + * cover the log as we may be in a situation where there isn't log space + * available to run a dummy transaction and this can lead to deadlocks when the + * tail of the log is pinned by an item that is modified in the CIL. Hence + * there's no point in running a dummy transaction at this point because we + * can't start trying to idle the log until both the CIL and AIL are empty. */ int xfs_log_need_covered(xfs_mount_t *mp) { - int needed = 0; struct xlog *log = mp->m_log; + int needed = 0; if (!xfs_fs_writable(mp)) return 0; + if (!xlog_cil_empty(log)) + return 0; + spin_lock(&log->l_icloglock); switch (log->l_covered_state) { case XLOG_STATE_COVER_DONE: @@ -1029,14 +1036,17 @@ xfs_log_need_covered(xfs_mount_t *mp) break; case XLOG_STATE_COVER_NEED: case XLOG_STATE_COVER_NEED2: - if (!xfs_ail_min_lsn(log->l_ailp) && - xlog_iclogs_empty(log)) { - if (log->l_covered_state == XLOG_STATE_COVER_NEED) - log->l_covered_state = XLOG_STATE_COVER_DONE; - else - log->l_covered_state = XLOG_STATE_COVER_DONE2; - } - /* FALLTHRU */ + if (xfs_ail_min_lsn(log->l_ailp)) + break; + if (!xlog_iclogs_empty(log)) + break; + + needed = 1; + if (log->l_covered_state == XLOG_STATE_COVER_NEED) + log->l_covered_state = XLOG_STATE_COVER_DONE; + else + log->l_covered_state = XLOG_STATE_COVER_DONE2; + break; default: needed = 1; break; diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index cfe97973ba36..da8524e779b6 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -711,6 +711,20 @@ xlog_cil_push_foreground( xlog_cil_push(log); } +bool +xlog_cil_empty( + struct xlog *log) +{ + struct xfs_cil *cil = log->l_cilp; + bool empty = false; + + spin_lock(&cil->xc_push_lock); + if (list_empty(&cil->xc_cil)) + empty = true; + spin_unlock(&cil->xc_push_lock); + return empty; +} + /* * Commit a transaction with the given vector to the Committed Item List. * diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 136654b9400d..f80cff26fda9 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -514,12 +514,10 @@ xlog_assign_grant_head(atomic64_t *head, int cycle, int space) /* * Committed Item List interfaces */ -int -xlog_cil_init(struct xlog *log); -void -xlog_cil_init_post_recovery(struct xlog *log); -void -xlog_cil_destroy(struct xlog *log); +int xlog_cil_init(struct xlog *log); +void xlog_cil_init_post_recovery(struct xlog *log); +void xlog_cil_destroy(struct xlog *log); +bool xlog_cil_empty(struct xlog *log); /* * CIL force routines -- cgit v1.2.3 From 08e96e1a3c5fd823f846df813b0b8be8e734c6c2 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 11 Oct 2013 20:59:05 -0500 Subject: xfs: remove newlines from strings passed to __xfs_printk __xfs_printk adds its own "\n". Having it in the original string leads to unintentional blank lines from these messages. Most format strings have no newline, but a few do, leading to i.e.: [ 7347.119911] XFS (sdb2): Access to block zero in inode 132 start_block: 0 start_off: 0 blkcnt: 0 extent-state: 0 lastx: 1a05 [ 7347.119911] [ 7347.119919] XFS (sdb2): Access to block zero in inode 132 start_block: 0 start_off: 0 blkcnt: 0 extent-state: 0 lastx: 1a05 [ 7347.119919] Fix them all. Signed-off-by: Eric Sandeen Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers --- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_buf.c | 6 +++--- fs/xfs/xfs_dir2_node.c | 2 +- fs/xfs/xfs_error.c | 2 +- fs/xfs/xfs_iomap.c | 2 +- fs/xfs/xfs_log.c | 2 +- fs/xfs/xfs_log_recover.c | 6 +++--- fs/xfs/xfs_qm_syscalls.c | 12 ++++++------ fs/xfs/xfs_sb.c | 4 ++-- fs/xfs/xfs_super.c | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index f47e65c30be6..e6b42026f9d4 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -1482,7 +1482,7 @@ xfs_bmap_search_extents( xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO, "Access to block zero in inode %llu " "start_block: %llx start_off: %llx " - "blkcnt: %llx extent-state: %x lastx: %x\n", + "blkcnt: %llx extent-state: %x lastx: %x", (unsigned long long)ip->i_ino, (unsigned long long)gotp->br_startblock, (unsigned long long)gotp->br_startoff, diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 263470075ea2..75e4ea7b109a 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -590,7 +590,7 @@ found: error = _xfs_buf_map_pages(bp, flags); if (unlikely(error)) { xfs_warn(target->bt_mount, - "%s: failed to map pages\n", __func__); + "%s: failed to map pagesn", __func__); xfs_buf_relse(bp); return NULL; } @@ -809,7 +809,7 @@ xfs_buf_get_uncached( error = _xfs_buf_map_pages(bp, 0); if (unlikely(error)) { xfs_warn(target->bt_mount, - "%s: failed to map pages\n", __func__); + "%s: failed to map pages", __func__); goto fail_free_mem; } @@ -1618,7 +1618,7 @@ xfs_setsize_buftarg_flags( bdevname(btp->bt_bdev, name); xfs_warn(btp->bt_mount, - "Cannot set_blocksize to %u on device %s\n", + "Cannot set_blocksize to %u on device %s", sectorsize, name); return EINVAL; } diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 4c3dba7ffb74..34df052683eb 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -1101,7 +1101,7 @@ xfs_dir2_leafn_rebalance( state->inleaf = 1; blk2->index = 0; xfs_alert(args->dp->i_mount, - "%s: picked the wrong leaf? reverting original leaf: blk1->index %d\n", + "%s: picked the wrong leaf? reverting original leaf: blk1->index %d", __func__, blk1->index); } } diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 1123d93ff795..40f2985a27bc 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -159,7 +159,7 @@ xfs_error_report( { if (level <= xfs_error_level) { xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT, - "Internal error %s at line %d of file %s. Caller 0x%p\n", + "Internal error %s at line %d of file %s. Caller 0x%p", tag, linenum, filename, ra); xfs_stack_trace(); diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 521fdf2ac6da..338b33263c56 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -110,7 +110,7 @@ xfs_alert_fsblock_zero( xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO, "Access to block zero in inode %llu " "start_block: %llx start_off: %llx " - "blkcnt: %llx extent-state: %x\n", + "blkcnt: %llx extent-state: %x", (unsigned long long)ip->i_ino, (unsigned long long)imap->br_startblock, (unsigned long long)imap->br_startoff, diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 613ed9414e70..0461f0872244 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1989,7 +1989,7 @@ xlog_print_tic_res( for (i = 0; i < ticket->t_res_num; i++) { uint r_type = ticket->t_res_arr[i].r_type; - xfs_warn(mp, "region[%u]: %s - %u bytes\n", i, + xfs_warn(mp, "region[%u]: %s - %u bytes", i, ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ? "bad-rtype" : res_type_str[r_type-1]), ticket->t_res_arr[i].r_len); diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 39797490a1f1..e7ca48e8f515 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -305,9 +305,9 @@ xlog_header_check_dump( xfs_mount_t *mp, xlog_rec_header_t *head) { - xfs_debug(mp, "%s: SB : uuid = %pU, fmt = %d\n", + xfs_debug(mp, "%s: SB : uuid = %pU, fmt = %d", __func__, &mp->m_sb.sb_uuid, XLOG_FMT); - xfs_debug(mp, " log : uuid = %pU, fmt = %d\n", + xfs_debug(mp, " log : uuid = %pU, fmt = %d", &head->h_fs_uuid, be32_to_cpu(head->h_fmt)); } #else @@ -4077,7 +4077,7 @@ xlog_unpack_data_crc( if (crc != rhead->h_crc) { if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) { xfs_alert(log->l_mp, - "log record CRC mismatch: found 0x%x, expected 0x%x.\n", + "log record CRC mismatch: found 0x%x, expected 0x%x.", le32_to_cpu(rhead->h_crc), le32_to_cpu(crc)); xfs_hex_dump(dp, 32); diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index 8174aad0b388..fb6709191811 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c @@ -287,7 +287,7 @@ xfs_qm_scall_trunc_qfiles( int error = 0, error2 = 0; if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { - xfs_debug(mp, "%s: flags=%x m_qflags=%x\n", + xfs_debug(mp, "%s: flags=%x m_qflags=%x", __func__, flags, mp->m_qflags); return XFS_ERROR(EINVAL); } @@ -325,7 +325,7 @@ xfs_qm_scall_quotaon( sbflags = 0; if (flags == 0) { - xfs_debug(mp, "%s: zero flags, m_qflags=%x\n", + xfs_debug(mp, "%s: zero flags, m_qflags=%x", __func__, mp->m_qflags); return XFS_ERROR(EINVAL); } @@ -348,7 +348,7 @@ xfs_qm_scall_quotaon( (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 && (flags & XFS_PQUOTA_ENFD))) { xfs_debug(mp, - "%s: Can't enforce without acct, flags=%x sbflags=%x\n", + "%s: Can't enforce without acct, flags=%x sbflags=%x", __func__, flags, mp->m_sb.sb_qflags); return XFS_ERROR(EINVAL); } @@ -648,7 +648,7 @@ xfs_qm_scall_setqlim( q->qi_bsoftlimit = soft; } } else { - xfs_debug(mp, "blkhard %Ld < blksoft %Ld\n", hard, soft); + xfs_debug(mp, "blkhard %Ld < blksoft %Ld", hard, soft); } hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ? (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) : @@ -664,7 +664,7 @@ xfs_qm_scall_setqlim( q->qi_rtbsoftlimit = soft; } } else { - xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld\n", hard, soft); + xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld", hard, soft); } hard = (newlim->d_fieldmask & FS_DQ_IHARD) ? @@ -681,7 +681,7 @@ xfs_qm_scall_setqlim( q->qi_isoftlimit = soft; } } else { - xfs_debug(mp, "ihard %Ld < isoft %Ld\n", hard, soft); + xfs_debug(mp, "ihard %Ld < isoft %Ld", hard, soft); } /* diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index a5b59d92eb70..a89d0bcc7959 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -249,13 +249,13 @@ xfs_mount_validate_sb( if (xfs_sb_version_has_pquotino(sbp)) { if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) { xfs_notice(mp, - "Version 5 of Super block has XFS_OQUOTA bits.\n"); + "Version 5 of Super block has XFS_OQUOTA bits."); return XFS_ERROR(EFSCORRUPTED); } } else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD | XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) { xfs_notice(mp, -"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits.\n"); +"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits."); return XFS_ERROR(EFSCORRUPTED); } diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 938e50fe6c61..c2e3e9535b26 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1241,7 +1241,7 @@ xfs_fs_remount( */ #if 0 xfs_info(mp, - "mount option \"%s\" not supported for remount\n", p); + "mount option \"%s\" not supported for remount", p); return -EINVAL; #else break; -- cgit v1.2.3 From 31625f28ad7be67701dc4cefcf52087addd88af4 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 11 Oct 2013 14:12:31 -0500 Subject: xfs: don't emit corruption noise on fs probes If we get EWRONGFS due to probing of non-xfs filesystems, there's no need to issue the scary corruption error and backtrace. Signed-off-by: Eric Sandeen Reviewed-by: Mark Tinguely Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_sb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index a89d0bcc7959..b4762279bb78 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -624,8 +624,9 @@ xfs_sb_read_verify( out_error: if (error) { - XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, - mp, bp->b_addr); + if (error != EWRONGFS) + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, + mp, bp->b_addr); xfs_buf_ioerror(bp, error); } } -- cgit v1.2.3 From 59e5a0e821d838854b3afd030d31f82cee3ecd58 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 11 Oct 2013 14:14:05 -0500 Subject: xfs: don't break from growfs ag update loop on error When xfs_growfs_data_private() is updating backup superblocks, it bails out on the first error encountered, whether reading or writing: * If we get an error writing out the alternate superblocks, * just issue a warning and continue. The real work is * already done and committed. This can cause a problem later during repair, because repair looks at all superblocks, and picks the most prevalent one as correct. If we bail out early in the backup superblock loop, we can end up with more "bad" matching superblocks than good, and a post-growfs repair may revert the filesystem to the old geometry. With the combination of superblock verifiers and old bugs, we're more likely to encounter read errors due to verification. And perhaps even worse, we don't even properly write any of the newly-added superblocks in the new AGs. Even with this change, growfs will still say: xfs_growfs: XFS_IOC_FSGROWFSDATA xfsctl failed: Structure needs cleaning data blocks changed from 319815680 to 335216640 which might be confusing to the user, but it at least communicates that something has gone wrong, and dmesg will probably highlight the need for an xfs_repair. And this is still best-effort; if verifiers fail on more than half the backup supers, they may still "win" - but that's probably best left to repair to more gracefully handle by doing its own strict verification as part of the backup super "voting." Signed-off-by: Eric Sandeen Acked-by: Dave Chinner Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers --- fs/xfs/xfs_fsops.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index fdae4ec5f21b..76c7b2b4fa8d 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -155,7 +155,7 @@ xfs_growfs_data_private( xfs_buf_t *bp; int bucket; int dpct; - int error; + int error, saved_error = 0; xfs_agnumber_t nagcount; xfs_agnumber_t nagimax = 0; xfs_rfsblock_t nb, nb_mod; @@ -498,29 +498,33 @@ xfs_growfs_data_private( error = ENOMEM; } + /* + * If we get an error reading or writing alternate superblocks, + * continue. xfs_repair chooses the "best" superblock based + * on most matches; if we break early, we'll leave more + * superblocks un-updated than updated, and xfs_repair may + * pick them over the properly-updated primary. + */ if (error) { xfs_warn(mp, "error %d reading secondary superblock for ag %d", error, agno); - break; + saved_error = error; + continue; } xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS); - /* - * If we get an error writing out the alternate superblocks, - * just issue a warning and continue. The real work is - * already done and committed. - */ error = xfs_bwrite(bp); xfs_buf_relse(bp); if (error) { xfs_warn(mp, "write error %d updating secondary superblock for ag %d", error, agno); - break; /* no point in continuing */ + saved_error = error; + continue; } } - return error; + return saved_error ? saved_error : error; error0: xfs_trans_cancel(tp, XFS_TRANS_ABORT); -- cgit v1.2.3 From 76ca4c238cf5858f8ba5bcd24c94c23717f1e14e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 14 Oct 2013 07:09:35 -0700 Subject: xfs: always take the iolock around xfs_setattr_size There is no reason to conditionally take the iolock inside xfs_setattr_size when we can let the caller handle it unconditionally, which just incrases the lock hold time for the case where it was previously taken internally by a few instructions. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_bmap_util.c | 3 +-- fs/xfs/xfs_file.c | 2 +- fs/xfs/xfs_iops.c | 39 +++++++++++++++++++++------------------ fs/xfs/xfs_iops.h | 2 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 97f952caea74..291e30cedfd3 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1622,8 +1622,7 @@ xfs_change_file_space( iattr.ia_valid = ATTR_SIZE; iattr.ia_size = startoffset; - error = xfs_setattr_size(ip, &iattr, - attr_flags | XFS_ATTR_NOLOCK); + error = xfs_setattr_size(ip, &iattr); xfs_iunlock(ip, XFS_IOLOCK_EXCL); if (error) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 4c749ab543d0..c9179820c01b 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -852,7 +852,7 @@ xfs_file_fallocate( iattr.ia_valid = ATTR_SIZE; iattr.ia_size = new_size; - error = -xfs_setattr_size(ip, &iattr, XFS_ATTR_NOLOCK); + error = -xfs_setattr_size(ip, &iattr); } out_unlock: diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 2b8952d9199b..52ecd1ccec9f 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -709,8 +709,7 @@ out_dqrele: int xfs_setattr_size( struct xfs_inode *ip, - struct iattr *iattr, - int flags) + struct iattr *iattr) { struct xfs_mount *mp = ip->i_mount; struct inode *inode = VFS_I(ip); @@ -733,15 +732,11 @@ xfs_setattr_size( if (error) return XFS_ERROR(error); + ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); ASSERT(S_ISREG(ip->i_d.di_mode)); ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); - if (!(flags & XFS_ATTR_NOLOCK)) { - lock_flags |= XFS_IOLOCK_EXCL; - xfs_ilock(ip, lock_flags); - } - oldsize = inode->i_size; newsize = iattr->ia_size; @@ -750,12 +745,11 @@ xfs_setattr_size( */ if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) { if (!(mask & (ATTR_CTIME|ATTR_MTIME))) - goto out_unlock; + return 0; /* * Use the regular setattr path to update the timestamps. */ - xfs_iunlock(ip, lock_flags); iattr->ia_valid &= ~ATTR_SIZE; return xfs_setattr_nonsize(ip, iattr, 0); } @@ -765,7 +759,7 @@ xfs_setattr_size( */ error = xfs_qm_dqattach(ip, 0); if (error) - goto out_unlock; + return error; /* * Now we can make the changes. Before we join the inode to the @@ -783,7 +777,7 @@ xfs_setattr_size( */ error = xfs_zero_eof(ip, newsize, oldsize); if (error) - goto out_unlock; + return error; } /* @@ -802,7 +796,7 @@ xfs_setattr_size( error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping, ip->i_d.di_size, newsize); if (error) - goto out_unlock; + return error; } /* @@ -812,7 +806,7 @@ xfs_setattr_size( error = -block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks); if (error) - goto out_unlock; + return error; tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); @@ -916,12 +910,21 @@ out_trans_cancel: STATIC int xfs_vn_setattr( - struct dentry *dentry, - struct iattr *iattr) + struct dentry *dentry, + struct iattr *iattr) { - if (iattr->ia_valid & ATTR_SIZE) - return -xfs_setattr_size(XFS_I(dentry->d_inode), iattr, 0); - return -xfs_setattr_nonsize(XFS_I(dentry->d_inode), iattr, 0); + struct xfs_inode *ip = XFS_I(dentry->d_inode); + int error; + + if (iattr->ia_valid & ATTR_SIZE) { + xfs_ilock(ip, XFS_IOLOCK_EXCL); + error = xfs_setattr_size(ip, iattr); + xfs_iunlock(ip, XFS_IOLOCK_EXCL); + } else { + error = xfs_setattr_nonsize(ip, iattr, 0); + } + + return -error; } STATIC int diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h index d81fb41205ec..3e76dcba7a79 100644 --- a/fs/xfs/xfs_iops.h +++ b/fs/xfs/xfs_iops.h @@ -38,6 +38,6 @@ extern void xfs_setup_inode(struct xfs_inode *); extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, int flags); -extern int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap, int flags); +extern int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap); #endif /* __XFS_IOPS_H__ */ -- cgit v1.2.3 From 001a3e73706fcb8c52dcca1d4742679384d04184 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 12 Oct 2013 00:55:05 -0700 Subject: xfs: remove the unused XFS_ATTR_NONBLOCK flag Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_ioctl.c | 3 --- fs/xfs/xfs_iops.h | 1 - 2 files changed, 4 deletions(-) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 668e8f4ccf5e..5a57e0c80b6b 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -661,9 +661,6 @@ xfs_ioc_space( if (!S_ISREG(inode->i_mode)) return -XFS_ERROR(EINVAL); - if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) - attr_flags |= XFS_ATTR_NONBLOCK; - if (filp->f_flags & O_DSYNC) attr_flags |= XFS_ATTR_SYNC; diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h index 3e76dcba7a79..fe4013af2586 100644 --- a/fs/xfs/xfs_iops.h +++ b/fs/xfs/xfs_iops.h @@ -31,7 +31,6 @@ extern void xfs_setup_inode(struct xfs_inode *); * Internal setattr interfaces. */ #define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */ -#define XFS_ATTR_NONBLOCK 0x02 /* return EAGAIN if op would block */ #define XFS_ATTR_NOLOCK 0x04 /* Don't grab any conflicting locks */ #define XFS_ATTR_NOACL 0x08 /* Don't call xfs_acl_chmod */ #define XFS_ATTR_SYNC 0x10 /* synchronous operation required */ -- cgit v1.2.3 From 5f8aca8b43f41c4b2d4dc5389124a40cab92b644 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 12 Oct 2013 00:55:06 -0700 Subject: xfs: always hold the iolock when calling xfs_change_file_space Currently fallocate always holds the iolock when calling into xfs_change_file_space, while the ioctl path lets some of the lower level functions take it, but leave it out in others. This patch makes sure the ioctl path also always holds the iolock and thus introduces consistent locking for the preallocation operations while simplifying the code and allowing to kill the now unused XFS_ATTR_NOLOCK flag. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_bmap_util.c | 71 +++++++++++++++++--------------------------------- fs/xfs/xfs_file.c | 2 +- fs/xfs/xfs_ioctl.c | 2 ++ fs/xfs/xfs_iops.h | 1 - 4 files changed, 27 insertions(+), 49 deletions(-) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 291e30cedfd3..bdd552d83107 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -989,8 +989,7 @@ xfs_alloc_file_space( xfs_inode_t *ip, xfs_off_t offset, xfs_off_t len, - int alloc_type, - int attr_flags) + int alloc_type) { xfs_mount_t *mp = ip->i_mount; xfs_off_t count; @@ -1248,8 +1247,7 @@ STATIC int xfs_free_file_space( xfs_inode_t *ip, xfs_off_t offset, - xfs_off_t len, - int attr_flags) + xfs_off_t len) { int committed; int done; @@ -1267,7 +1265,6 @@ xfs_free_file_space( int rt; xfs_fileoff_t startoffset_fsb; xfs_trans_t *tp; - int need_iolock = 1; mp = ip->i_mount; @@ -1284,20 +1281,15 @@ xfs_free_file_space( startoffset_fsb = XFS_B_TO_FSB(mp, offset); endoffset_fsb = XFS_B_TO_FSBT(mp, offset + len); - if (attr_flags & XFS_ATTR_NOLOCK) - need_iolock = 0; - if (need_iolock) { - xfs_ilock(ip, XFS_IOLOCK_EXCL); - /* wait for the completion of any pending DIOs */ - inode_dio_wait(VFS_I(ip)); - } + /* wait for the completion of any pending DIOs */ + inode_dio_wait(VFS_I(ip)); rounding = max_t(xfs_off_t, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE); ioffset = offset & ~(rounding - 1); error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping, ioffset, -1); if (error) - goto out_unlock_iolock; + goto out; truncate_pagecache_range(VFS_I(ip), ioffset, -1); /* @@ -1311,7 +1303,7 @@ xfs_free_file_space( error = xfs_bmapi_read(ip, startoffset_fsb, 1, &imap, &nimap, 0); if (error) - goto out_unlock_iolock; + goto out; ASSERT(nimap == 0 || nimap == 1); if (nimap && imap.br_startblock != HOLESTARTBLOCK) { xfs_daddr_t block; @@ -1326,7 +1318,7 @@ xfs_free_file_space( error = xfs_bmapi_read(ip, endoffset_fsb - 1, 1, &imap, &nimap, 0); if (error) - goto out_unlock_iolock; + goto out; ASSERT(nimap == 0 || nimap == 1); if (nimap && imap.br_startblock != HOLESTARTBLOCK) { ASSERT(imap.br_startblock != DELAYSTARTBLOCK); @@ -1412,18 +1404,15 @@ xfs_free_file_space( xfs_iunlock(ip, XFS_ILOCK_EXCL); } - out_unlock_iolock: - if (need_iolock) - xfs_iunlock(ip, XFS_IOLOCK_EXCL); + out: return error; error0: xfs_bmap_cancel(&free_list); error1: xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); - xfs_iunlock(ip, need_iolock ? (XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL) : - XFS_ILOCK_EXCL); - return error; + xfs_iunlock(ip, XFS_ILOCK_EXCL); + goto out; } @@ -1431,8 +1420,7 @@ STATIC int xfs_zero_file_space( struct xfs_inode *ip, xfs_off_t offset, - xfs_off_t len, - int attr_flags) + xfs_off_t len) { struct xfs_mount *mp = ip->i_mount; uint granularity; @@ -1453,9 +1441,6 @@ xfs_zero_file_space( ASSERT(start_boundary >= offset); ASSERT(end_boundary <= offset + len); - if (!(attr_flags & XFS_ATTR_NOLOCK)) - xfs_ilock(ip, XFS_IOLOCK_EXCL); - if (start_boundary < end_boundary - 1) { /* punch out the page cache over the conversion range */ truncate_pagecache_range(VFS_I(ip), start_boundary, @@ -1463,16 +1448,16 @@ xfs_zero_file_space( /* convert the blocks */ error = xfs_alloc_file_space(ip, start_boundary, end_boundary - start_boundary - 1, - XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT, - attr_flags); + XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT); if (error) - goto out_unlock; + goto out; /* We've handled the interior of the range, now for the edges */ - if (start_boundary != offset) + if (start_boundary != offset) { error = xfs_iozero(ip, offset, start_boundary - offset); - if (error) - goto out_unlock; + if (error) + goto out; + } if (end_boundary != offset + len) error = xfs_iozero(ip, end_boundary, @@ -1486,9 +1471,7 @@ xfs_zero_file_space( error = xfs_iozero(ip, offset, len); } -out_unlock: - if (!(attr_flags & XFS_ATTR_NOLOCK)) - xfs_iunlock(ip, XFS_IOLOCK_EXCL); +out: return error; } @@ -1571,8 +1554,7 @@ xfs_change_file_space( setprealloc = clrprealloc = 0; switch (cmd) { case XFS_IOC_ZERO_RANGE: - error = xfs_zero_file_space(ip, startoffset, bf->l_len, - attr_flags); + error = xfs_zero_file_space(ip, startoffset, bf->l_len); if (error) return error; setprealloc = 1; @@ -1581,7 +1563,7 @@ xfs_change_file_space( case XFS_IOC_RESVSP: case XFS_IOC_RESVSP64: error = xfs_alloc_file_space(ip, startoffset, bf->l_len, - XFS_BMAPI_PREALLOC, attr_flags); + XFS_BMAPI_PREALLOC); if (error) return error; setprealloc = 1; @@ -1589,8 +1571,8 @@ xfs_change_file_space( case XFS_IOC_UNRESVSP: case XFS_IOC_UNRESVSP64: - if ((error = xfs_free_file_space(ip, startoffset, bf->l_len, - attr_flags))) + error = xfs_free_file_space(ip, startoffset, bf->l_len); + if (error) return error; break; @@ -1608,22 +1590,17 @@ xfs_change_file_space( * truncate, direct IO) from racing against the transient * allocated but not written state we can have here. */ - xfs_ilock(ip, XFS_IOLOCK_EXCL); if (startoffset > fsize) { error = xfs_alloc_file_space(ip, fsize, - startoffset - fsize, 0, - attr_flags | XFS_ATTR_NOLOCK); - if (error) { - xfs_iunlock(ip, XFS_IOLOCK_EXCL); + startoffset - fsize, 0); + if (error) break; - } } iattr.ia_valid = ATTR_SIZE; iattr.ia_size = startoffset; error = xfs_setattr_size(ip, &iattr); - xfs_iunlock(ip, XFS_IOLOCK_EXCL); if (error) return error; diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index c9179820c01b..116300f3b1d4 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -816,7 +816,7 @@ xfs_file_fallocate( xfs_flock64_t bf; xfs_inode_t *ip = XFS_I(inode); int cmd = XFS_IOC_RESVSP; - int attr_flags = XFS_ATTR_NOLOCK; + int attr_flags = 0; if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) return -EOPNOTSUPP; diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 5a57e0c80b6b..45287419dc37 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -670,7 +670,9 @@ xfs_ioc_space( error = mnt_want_write_file(filp); if (error) return error; + xfs_ilock(ip, XFS_IOLOCK_EXCL); error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); + xfs_iunlock(ip, XFS_IOLOCK_EXCL); mnt_drop_write_file(filp); return -error; } diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h index fe4013af2586..f3738253c69a 100644 --- a/fs/xfs/xfs_iops.h +++ b/fs/xfs/xfs_iops.h @@ -31,7 +31,6 @@ extern void xfs_setup_inode(struct xfs_inode *); * Internal setattr interfaces. */ #define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */ -#define XFS_ATTR_NOLOCK 0x04 /* Don't grab any conflicting locks */ #define XFS_ATTR_NOACL 0x08 /* Don't call xfs_acl_chmod */ #define XFS_ATTR_SYNC 0x10 /* synchronous operation required */ -- cgit v1.2.3 From 83aee9e4c2976143f35b3a42ad1faadf58c53ae7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 12 Oct 2013 00:55:07 -0700 Subject: xfs: simplify the fallocate path Call xfs_alloc_file_space or xfs_free_file_space directly from xfs_file_fallocate instead of going through xfs_change_file_space. This simplified the code by removing the unessecary marshalling of the arguments into an xfs_flock64_t structure and allows removing checks that are already done in the VFS code. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_bmap_util.c | 39 +++----------------------- fs/xfs/xfs_bmap_util.h | 4 +++ fs/xfs/xfs_file.c | 76 +++++++++++++++++++++++++++++++------------------- 3 files changed, 56 insertions(+), 63 deletions(-) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index bdd552d83107..7e1c2ae81c35 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -965,28 +965,9 @@ xfs_free_eofblocks( return error; } -/* - * xfs_alloc_file_space() - * This routine allocates disk space for the given file. - * - * If alloc_type == 0, this request is for an ALLOCSP type - * request which will change the file size. In this case, no - * DMAPI event will be generated by the call. A TRUNCATE event - * will be generated later by xfs_setattr. - * - * If alloc_type != 0, this request is for a RESVSP type - * request, and a DMAPI DM_EVENT_WRITE will be generated if the - * lower block boundary byte address is less than the file's - * length. - * - * RETURNS: - * 0 on success - * errno on error - * - */ -STATIC int +int xfs_alloc_file_space( - xfs_inode_t *ip, + struct xfs_inode *ip, xfs_off_t offset, xfs_off_t len, int alloc_type) @@ -1231,21 +1212,9 @@ xfs_zero_remaining_bytes( return error; } -/* - * xfs_free_file_space() - * This routine frees disk space for the given file. - * - * This routine is only called by xfs_change_file_space - * for an UNRESVSP type call. - * - * RETURNS: - * 0 on success - * errno on error - * - */ -STATIC int +int xfs_free_file_space( - xfs_inode_t *ip, + struct xfs_inode *ip, xfs_off_t offset, xfs_off_t len) { diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h index 061260946f7a..77cf5001719b 100644 --- a/fs/xfs/xfs_bmap_util.h +++ b/fs/xfs/xfs_bmap_util.h @@ -96,6 +96,10 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip, int xfs_change_file_space(struct xfs_inode *ip, int cmd, xfs_flock64_t *bf, xfs_off_t offset, int attr_flags); +int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset, + xfs_off_t len, int alloc_type); +int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset, + xfs_off_t len); /* EOF block manipulation functions */ bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 116300f3b1d4..c8a75a75e25a 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -805,44 +805,64 @@ out: STATIC long xfs_file_fallocate( - struct file *file, - int mode, - loff_t offset, - loff_t len) + struct file *file, + int mode, + loff_t offset, + loff_t len) { - struct inode *inode = file_inode(file); - long error; - loff_t new_size = 0; - xfs_flock64_t bf; - xfs_inode_t *ip = XFS_I(inode); - int cmd = XFS_IOC_RESVSP; - int attr_flags = 0; + struct inode *inode = file_inode(file); + struct xfs_inode *ip = XFS_I(inode); + struct xfs_trans *tp; + long error; + loff_t new_size = 0; + if (!S_ISREG(inode->i_mode)) + return -EINVAL; if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) return -EOPNOTSUPP; - bf.l_whence = 0; - bf.l_start = offset; - bf.l_len = len; - xfs_ilock(ip, XFS_IOLOCK_EXCL); + if (mode & FALLOC_FL_PUNCH_HOLE) { + error = xfs_free_file_space(ip, offset, len); + if (error) + goto out_unlock; + } else { + if (!(mode & FALLOC_FL_KEEP_SIZE) && + offset + len > i_size_read(inode)) { + new_size = offset + len; + error = -inode_newsize_ok(inode, new_size); + if (error) + goto out_unlock; + } - if (mode & FALLOC_FL_PUNCH_HOLE) - cmd = XFS_IOC_UNRESVSP; - - /* check the new inode size is valid before allocating */ - if (!(mode & FALLOC_FL_KEEP_SIZE) && - offset + len > i_size_read(inode)) { - new_size = offset + len; - error = inode_newsize_ok(inode, new_size); + error = xfs_alloc_file_space(ip, offset, len, + XFS_BMAPI_PREALLOC); if (error) goto out_unlock; } - if (file->f_flags & O_DSYNC) - attr_flags |= XFS_ATTR_SYNC; + tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID); + error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0); + if (error) { + xfs_trans_cancel(tp, 0); + goto out_unlock; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + ip->i_d.di_mode &= ~S_ISUID; + if (ip->i_d.di_mode & S_IXGRP) + ip->i_d.di_mode &= ~S_ISGID; + + if (!(mode & FALLOC_FL_PUNCH_HOLE)) + ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; + + xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags); + if (file->f_flags & O_DSYNC) + xfs_trans_set_sync(tp); + error = xfs_trans_commit(tp, 0); if (error) goto out_unlock; @@ -852,12 +872,12 @@ xfs_file_fallocate( iattr.ia_valid = ATTR_SIZE; iattr.ia_size = new_size; - error = -xfs_setattr_size(ip, &iattr); + error = xfs_setattr_size(ip, &iattr); } out_unlock: xfs_iunlock(ip, XFS_IOLOCK_EXCL); - return error; + return -error; } -- cgit v1.2.3 From 865e9446b4c17f78be0b1387426394b6bfc278f3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 12 Oct 2013 00:55:08 -0700 Subject: xfs: fold xfs_change_file_space into xfs_ioc_space Now that only one caller of xfs_change_file_space is left it can be merged into said caller. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_bmap_util.c | 178 +------------------------------------------------ fs/xfs/xfs_bmap_util.h | 5 +- fs/xfs/xfs_ioctl.c | 130 +++++++++++++++++++++++++++++++++--- fs/xfs/xfs_iops.h | 4 +- 4 files changed, 126 insertions(+), 191 deletions(-) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 7e1c2ae81c35..45cf5a2fd1bf 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1385,7 +1385,7 @@ xfs_free_file_space( } -STATIC int +int xfs_zero_file_space( struct xfs_inode *ip, xfs_off_t offset, @@ -1445,182 +1445,6 @@ out: } -/* - * xfs_change_file_space() - * This routine allocates or frees disk space for the given file. - * The user specified parameters are checked for alignment and size - * limitations. - * - * RETURNS: - * 0 on success - * errno on error - * - */ -int -xfs_change_file_space( - xfs_inode_t *ip, - int cmd, - xfs_flock64_t *bf, - xfs_off_t offset, - int attr_flags) -{ - xfs_mount_t *mp = ip->i_mount; - int clrprealloc; - int error; - xfs_fsize_t fsize; - int setprealloc; - xfs_off_t startoffset; - xfs_trans_t *tp; - struct iattr iattr; - - if (!S_ISREG(ip->i_d.di_mode)) - return XFS_ERROR(EINVAL); - - switch (bf->l_whence) { - case 0: /*SEEK_SET*/ - break; - case 1: /*SEEK_CUR*/ - bf->l_start += offset; - break; - case 2: /*SEEK_END*/ - bf->l_start += XFS_ISIZE(ip); - break; - default: - return XFS_ERROR(EINVAL); - } - - /* - * length of <= 0 for resv/unresv/zero is invalid. length for - * alloc/free is ignored completely and we have no idea what userspace - * might have set it to, so set it to zero to allow range - * checks to pass. - */ - switch (cmd) { - case XFS_IOC_ZERO_RANGE: - case XFS_IOC_RESVSP: - case XFS_IOC_RESVSP64: - case XFS_IOC_UNRESVSP: - case XFS_IOC_UNRESVSP64: - if (bf->l_len <= 0) - return XFS_ERROR(EINVAL); - break; - default: - bf->l_len = 0; - break; - } - - if (bf->l_start < 0 || - bf->l_start > mp->m_super->s_maxbytes || - bf->l_start + bf->l_len < 0 || - bf->l_start + bf->l_len >= mp->m_super->s_maxbytes) - return XFS_ERROR(EINVAL); - - bf->l_whence = 0; - - startoffset = bf->l_start; - fsize = XFS_ISIZE(ip); - - setprealloc = clrprealloc = 0; - switch (cmd) { - case XFS_IOC_ZERO_RANGE: - error = xfs_zero_file_space(ip, startoffset, bf->l_len); - if (error) - return error; - setprealloc = 1; - break; - - case XFS_IOC_RESVSP: - case XFS_IOC_RESVSP64: - error = xfs_alloc_file_space(ip, startoffset, bf->l_len, - XFS_BMAPI_PREALLOC); - if (error) - return error; - setprealloc = 1; - break; - - case XFS_IOC_UNRESVSP: - case XFS_IOC_UNRESVSP64: - error = xfs_free_file_space(ip, startoffset, bf->l_len); - if (error) - return error; - break; - - case XFS_IOC_ALLOCSP: - case XFS_IOC_ALLOCSP64: - case XFS_IOC_FREESP: - case XFS_IOC_FREESP64: - /* - * These operations actually do IO when extending the file, but - * the allocation is done seperately to the zeroing that is - * done. This set of operations need to be serialised against - * other IO operations, such as truncate and buffered IO. We - * need to take the IOLOCK here to serialise the allocation and - * zeroing IO to prevent other IOLOCK holders (e.g. getbmap, - * truncate, direct IO) from racing against the transient - * allocated but not written state we can have here. - */ - if (startoffset > fsize) { - error = xfs_alloc_file_space(ip, fsize, - startoffset - fsize, 0); - if (error) - break; - } - - iattr.ia_valid = ATTR_SIZE; - iattr.ia_size = startoffset; - - error = xfs_setattr_size(ip, &iattr); - - if (error) - return error; - - clrprealloc = 1; - break; - - default: - ASSERT(0); - return XFS_ERROR(EINVAL); - } - - /* - * update the inode timestamp, mode, and prealloc flag bits - */ - tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_writeid, 0, 0); - if (error) { - xfs_trans_cancel(tp, 0); - return error; - } - - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - - if ((attr_flags & XFS_ATTR_DMI) == 0) { - ip->i_d.di_mode &= ~S_ISUID; - - /* - * Note that we don't have to worry about mandatory - * file locking being disabled here because we only - * clear the S_ISGID bit if the Group execute bit is - * on, but if it was on then mandatory locking wouldn't - * have been enabled. - */ - if (ip->i_d.di_mode & S_IXGRP) - ip->i_d.di_mode &= ~S_ISGID; - - xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - } - if (setprealloc) - ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; - else if (clrprealloc) - ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC; - - xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - if (attr_flags & XFS_ATTR_SYNC) - xfs_trans_set_sync(tp); - return xfs_trans_commit(tp, 0); -} - /* * We need to check that the format of the data fork in the temporary inode is * valid for the target inode before doing the swap. This is not a problem with diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h index 77cf5001719b..900747b25772 100644 --- a/fs/xfs/xfs_bmap_util.h +++ b/fs/xfs/xfs_bmap_util.h @@ -93,13 +93,12 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip, int *is_empty); /* preallocation and hole punch interface */ -int xfs_change_file_space(struct xfs_inode *ip, int cmd, - xfs_flock64_t *bf, xfs_off_t offset, - int attr_flags); int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset, xfs_off_t len, int alloc_type); int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset, xfs_off_t len); +int xfs_zero_file_space(struct xfs_inode *ip, xfs_off_t offset, + xfs_off_t len); /* EOF block manipulation functions */ bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 45287419dc37..e448d735346b 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -641,7 +641,11 @@ xfs_ioc_space( unsigned int cmd, xfs_flock64_t *bf) { - int attr_flags = 0; + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + struct iattr iattr; + bool setprealloc = false; + bool clrprealloc = false; int error; /* @@ -661,17 +665,127 @@ xfs_ioc_space( if (!S_ISREG(inode->i_mode)) return -XFS_ERROR(EINVAL); - if (filp->f_flags & O_DSYNC) - attr_flags |= XFS_ATTR_SYNC; - - if (ioflags & IO_INVIS) - attr_flags |= XFS_ATTR_DMI; - error = mnt_want_write_file(filp); if (error) return error; + xfs_ilock(ip, XFS_IOLOCK_EXCL); - error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); + + switch (bf->l_whence) { + case 0: /*SEEK_SET*/ + break; + case 1: /*SEEK_CUR*/ + bf->l_start += filp->f_pos; + break; + case 2: /*SEEK_END*/ + bf->l_start += XFS_ISIZE(ip); + break; + default: + error = XFS_ERROR(EINVAL); + goto out_unlock; + } + + /* + * length of <= 0 for resv/unresv/zero is invalid. length for + * alloc/free is ignored completely and we have no idea what userspace + * might have set it to, so set it to zero to allow range + * checks to pass. + */ + switch (cmd) { + case XFS_IOC_ZERO_RANGE: + case XFS_IOC_RESVSP: + case XFS_IOC_RESVSP64: + case XFS_IOC_UNRESVSP: + case XFS_IOC_UNRESVSP64: + if (bf->l_len <= 0) { + error = XFS_ERROR(EINVAL); + goto out_unlock; + } + break; + default: + bf->l_len = 0; + break; + } + + if (bf->l_start < 0 || + bf->l_start > mp->m_super->s_maxbytes || + bf->l_start + bf->l_len < 0 || + bf->l_start + bf->l_len >= mp->m_super->s_maxbytes) { + error = XFS_ERROR(EINVAL); + goto out_unlock; + } + + switch (cmd) { + case XFS_IOC_ZERO_RANGE: + error = xfs_zero_file_space(ip, bf->l_start, bf->l_len); + if (!error) + setprealloc = true; + break; + case XFS_IOC_RESVSP: + case XFS_IOC_RESVSP64: + error = xfs_alloc_file_space(ip, bf->l_start, bf->l_len, + XFS_BMAPI_PREALLOC); + if (!error) + setprealloc = true; + break; + case XFS_IOC_UNRESVSP: + case XFS_IOC_UNRESVSP64: + error = xfs_free_file_space(ip, bf->l_start, bf->l_len); + break; + case XFS_IOC_ALLOCSP: + case XFS_IOC_ALLOCSP64: + case XFS_IOC_FREESP: + case XFS_IOC_FREESP64: + if (bf->l_start > XFS_ISIZE(ip)) { + error = xfs_alloc_file_space(ip, XFS_ISIZE(ip), + bf->l_start - XFS_ISIZE(ip), 0); + if (error) + goto out_unlock; + } + + iattr.ia_valid = ATTR_SIZE; + iattr.ia_size = bf->l_start; + + error = xfs_setattr_size(ip, &iattr); + if (!error) + clrprealloc = true; + break; + default: + ASSERT(0); + error = XFS_ERROR(EINVAL); + } + + if (error) + goto out_unlock; + + tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID); + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_writeid, 0, 0); + if (error) { + xfs_trans_cancel(tp, 0); + goto out_unlock; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + + if (!(ioflags & IO_INVIS)) { + ip->i_d.di_mode &= ~S_ISUID; + if (ip->i_d.di_mode & S_IXGRP) + ip->i_d.di_mode &= ~S_ISGID; + xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + } + + if (setprealloc) + ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; + else if (clrprealloc) + ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC; + + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + if (filp->f_flags & O_DSYNC) + xfs_trans_set_sync(tp); + error = xfs_trans_commit(tp, 0); + +out_unlock: xfs_iunlock(ip, XFS_IOLOCK_EXCL); mnt_drop_write_file(filp); return -error; diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h index f3738253c69a..d2c5057b5cc4 100644 --- a/fs/xfs/xfs_iops.h +++ b/fs/xfs/xfs_iops.h @@ -30,9 +30,7 @@ extern void xfs_setup_inode(struct xfs_inode *); /* * Internal setattr interfaces. */ -#define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */ -#define XFS_ATTR_NOACL 0x08 /* Don't call xfs_acl_chmod */ -#define XFS_ATTR_SYNC 0x10 /* synchronous operation required */ +#define XFS_ATTR_NOACL 0x01 /* Don't call xfs_acl_chmod */ extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, int flags); -- cgit v1.2.3 From 70a9883c5f34b215b8a77665cefd0398edc5a9ef Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 23 Oct 2013 10:36:05 +1100 Subject: xfs: create a shared header file for format-related information All of the buffer operations structures are needed to be exported for xfs_db, so move them all to a common location rather than spreading them all over the place. They are verifying the on-disk format, so while xfs_format.h might be a good place, it is not part of the on disk format. Hence we need to create a new header file that we centralise these related definitions. Start by moving the bffer operations structures, and then also move all the other definitions that have crept into xfs_log_format.h and xfs_format.h as there was no other shared header file to put them in. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_ag.h | 4 - fs/xfs/xfs_alloc.c | 3 +- fs/xfs/xfs_alloc.h | 3 - fs/xfs/xfs_alloc_btree.h | 2 - fs/xfs/xfs_aops.c | 4 +- fs/xfs/xfs_attr.c | 1 + fs/xfs/xfs_attr_inactive.c | 1 + fs/xfs/xfs_attr_leaf.h | 2 - fs/xfs/xfs_attr_remote.h | 2 - fs/xfs/xfs_bmap.c | 1 + fs/xfs/xfs_bmap_btree.h | 2 - fs/xfs/xfs_bmap_util.c | 1 + fs/xfs/xfs_btree.c | 2 +- fs/xfs/xfs_da_btree.c | 3 +- fs/xfs/xfs_da_btree.h | 2 - fs/xfs/xfs_dquot.c | 1 + fs/xfs/xfs_dquot.h | 2 - fs/xfs/xfs_extent_busy.c | 3 +- fs/xfs/xfs_file.c | 1 + fs/xfs/xfs_format.h | 10 -- fs/xfs/xfs_fsops.c | 2 + fs/xfs/xfs_ialloc.c | 3 +- fs/xfs/xfs_ialloc.h | 2 - fs/xfs/xfs_ialloc_btree.h | 2 - fs/xfs/xfs_icreate_item.c | 2 +- fs/xfs/xfs_inode.c | 1 + fs/xfs/xfs_inode_buf.c | 1 + fs/xfs/xfs_inode_buf.h | 3 - fs/xfs/xfs_ioctl.c | 1 + fs/xfs/xfs_iomap.c | 1 + fs/xfs/xfs_iops.c | 1 + fs/xfs/xfs_itable.c | 2 +- fs/xfs/xfs_log.c | 2 +- fs/xfs/xfs_log_cil.c | 2 +- fs/xfs/xfs_log_format.h | 177 -------------------------------- fs/xfs/xfs_log_recover.c | 1 + fs/xfs/xfs_log_rlimit.c | 1 + fs/xfs/xfs_mount.c | 1 + fs/xfs/xfs_qm.c | 1 + fs/xfs/xfs_qm_syscalls.c | 1 + fs/xfs/xfs_quota.h | 2 - fs/xfs/xfs_rtalloc.c | 1 + fs/xfs/xfs_sb.h | 3 - fs/xfs/xfs_shared.h | 244 ++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_super.c | 1 + fs/xfs/xfs_symlink.c | 1 + fs/xfs/xfs_symlink_remote.c | 1 + fs/xfs/xfs_trace.c | 2 +- fs/xfs/xfs_trans.c | 1 + fs/xfs/xfs_trans_buf.c | 2 +- fs/xfs/xfs_trans_dquot.c | 1 + fs/xfs/xfs_trans_extfree.c | 2 +- fs/xfs/xfs_trans_inode.c | 2 +- fs/xfs/xfs_trans_resv.c | 1 + 54 files changed, 289 insertions(+), 232 deletions(-) create mode 100644 fs/xfs/xfs_shared.h diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h index 1cb740afd674..3fc109819c34 100644 --- a/fs/xfs/xfs_ag.h +++ b/fs/xfs/xfs_ag.h @@ -128,8 +128,6 @@ typedef struct xfs_agf { extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, int flags, struct xfs_buf **bpp); -extern const struct xfs_buf_ops xfs_agf_buf_ops; - /* * Size of the unlinked inode hash table in the agi. */ @@ -191,8 +189,6 @@ typedef struct xfs_agi { extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_buf **bpp); -extern const struct xfs_buf_ops xfs_agi_buf_ops; - /* * The third a.g. block contains the a.g. freelist, an array * of block pointers to blocks owned by the allocation btree code. diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 5a1393f5e020..2bfca06e0ee7 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -17,7 +17,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 99d0a6101558..feacb061bab7 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h @@ -231,7 +231,4 @@ xfs_alloc_get_rec( xfs_extlen_t *len, /* output: length of extent */ int *stat); /* output: success/failure */ -extern const struct xfs_buf_ops xfs_agf_buf_ops; -extern const struct xfs_buf_ops xfs_agfl_buf_ops; - #endif /* __XFS_ALLOC_H__ */ diff --git a/fs/xfs/xfs_alloc_btree.h b/fs/xfs/xfs_alloc_btree.h index e3a3f7424192..72676c36b1bb 100644 --- a/fs/xfs/xfs_alloc_btree.h +++ b/fs/xfs/xfs_alloc_btree.h @@ -95,6 +95,4 @@ extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *, xfs_agnumber_t, xfs_btnum_t); extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int); -extern const struct xfs_buf_ops xfs_allocbt_buf_ops; - #endif /* __XFS_ALLOC_BTREE_H__ */ diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index f3f95f094af8..2c61e9622f57 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -16,9 +16,11 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" -#include "xfs_log.h" +#include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_sb.h" #include "xfs_ag.h" +#include "xfs_log.h" #include "xfs_trans.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index ddcf2267ffa6..21af043bbee8 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index bb24b07cbedb..e90a8760bc3d 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c @@ -19,6 +19,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h index c1022138c7e6..da34e64b5323 100644 --- a/fs/xfs/xfs_attr_leaf.h +++ b/fs/xfs/xfs_attr_leaf.h @@ -336,6 +336,4 @@ void xfs_attr3_leaf_hdr_from_disk(struct xfs_attr3_icleaf_hdr *to, void xfs_attr3_leaf_hdr_to_disk(struct xfs_attr_leafblock *to, struct xfs_attr3_icleaf_hdr *from); -extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops; - #endif /* __XFS_ATTR_LEAF_H__ */ diff --git a/fs/xfs/xfs_attr_remote.h b/fs/xfs/xfs_attr_remote.h index 92a8fd7977cc..b3e1e1bdfb3b 100644 --- a/fs/xfs/xfs_attr_remote.h +++ b/fs/xfs/xfs_attr_remote.h @@ -45,8 +45,6 @@ struct xfs_attr3_rmt_hdr { ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ sizeof(struct xfs_attr3_rmt_hdr) : 0)) -extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; - int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen); int xfs_attr_rmtval_get(struct xfs_da_args *args); diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index e6b42026f9d4..6870aad5d815 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_inum.h" diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h index e367461a638e..e2b0768a89ba 100644 --- a/fs/xfs/xfs_bmap_btree.h +++ b/fs/xfs/xfs_bmap_btree.h @@ -243,6 +243,4 @@ extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip, extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *, struct xfs_trans *, struct xfs_inode *, int); -extern const struct xfs_buf_ops xfs_bmbt_buf_ops; - #endif /* __XFS_BMAP_BTREE_H__ */ diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 45cf5a2fd1bf..4f246628a900 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -19,6 +19,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_inum.h" diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 5690e102243d..1a297e26e26c 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c @@ -17,7 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 20bf8e8002d6..ac51abeb4782 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -18,7 +18,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index b1f267995dea..a762cfa4097d 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h @@ -309,8 +309,6 @@ int xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, struct xfs_buf **bpp, int which_fork); -extern const struct xfs_buf_ops xfs_da3_node_buf_ops; - /* * Utility routines. */ diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 1ee776d477c3..8b1d2c0a9054 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h index 55abbca2883d..d22ed0053c32 100644 --- a/fs/xfs/xfs_dquot.h +++ b/fs/xfs/xfs_dquot.h @@ -172,6 +172,4 @@ static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp) return dqp; } -extern const struct xfs_buf_ops xfs_dquot_buf_ops; - #endif /* __XFS_DQUOT_H__ */ diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c index e43708e2f080..74828a7895eb 100644 --- a/fs/xfs/xfs_extent_busy.c +++ b/fs/xfs/xfs_extent_busy.c @@ -19,7 +19,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index c8a75a75e25a..57d95b2f8692 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -17,6 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_sb.h" #include "xfs_ag.h" diff --git a/fs/xfs/xfs_format.h b/fs/xfs/xfs_format.h index 35c08ff54ca0..a790428f3bf4 100644 --- a/fs/xfs/xfs_format.h +++ b/fs/xfs/xfs_format.h @@ -156,14 +156,4 @@ struct xfs_dsymlink_hdr { ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ sizeof(struct xfs_dsymlink_hdr) : 0)) -int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen); -int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, - uint32_t size, struct xfs_buf *bp); -bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, - uint32_t size, struct xfs_buf *bp); -void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp, - struct xfs_inode *ip, struct xfs_ifork *ifp); - -extern const struct xfs_buf_ops xfs_symlink_buf_ops; - #endif /* __XFS_FORMAT_H__ */ diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 76c7b2b4fa8d..e5d2c43c65c4 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -18,6 +18,8 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_types.h" +#include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index ccf2fb143962..8530cabf128d 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -17,7 +17,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_inum.h" diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h index 68c07320f096..155779803d67 100644 --- a/fs/xfs/xfs_ialloc.h +++ b/fs/xfs/xfs_ialloc.h @@ -158,6 +158,4 @@ int xfs_ialloc_inode_init(struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_agblock_t length, unsigned int gen); -extern const struct xfs_buf_ops xfs_agi_buf_ops; - #endif /* __XFS_IALLOC_H__ */ diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h index 3ac36b7642e9..cfbfe461abbc 100644 --- a/fs/xfs/xfs_ialloc_btree.h +++ b/fs/xfs/xfs_ialloc_btree.h @@ -110,6 +110,4 @@ extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *, struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t); extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int); -extern const struct xfs_buf_ops xfs_inobt_buf_ops; - #endif /* __XFS_IALLOC_BTREE_H__ */ diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c index 5a5a593994d4..df8baf38eb85 100644 --- a/fs/xfs/xfs_icreate_item.c +++ b/fs/xfs/xfs_icreate_item.c @@ -17,7 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 5fce7261a64b..1aaef689794d 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -20,6 +20,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_inum.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_inode_buf.c b/fs/xfs/xfs_inode_buf.c index 63382d37f565..65fa56edecf3 100644 --- a/fs/xfs/xfs_inode_buf.c +++ b/fs/xfs/xfs_inode_buf.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_inode_buf.h b/fs/xfs/xfs_inode_buf.h index abba0ae8cf2d..9308c47f2a52 100644 --- a/fs/xfs/xfs_inode_buf.h +++ b/fs/xfs/xfs_inode_buf.h @@ -47,7 +47,4 @@ void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); #define xfs_inobp_check(mp, bp) #endif /* DEBUG */ -extern const struct xfs_buf_ops xfs_inode_buf_ops; -extern const struct xfs_buf_ops xfs_inode_buf_ra_ops; - #endif /* __XFS_INODE_BUF_H__ */ diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index e448d735346b..c6c62d12a934 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 338b33263c56..d8fb6dfe75ed 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 52ecd1ccec9f..24fe333b8c41 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_acl.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 084b3e1741fd..4f50e637f33b 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -17,7 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_inum.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 0461f0872244..fbaf70af3d61 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -17,7 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index da8524e779b6..a844f77d2cc3 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -17,7 +17,7 @@ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_trans_priv.h" diff --git a/fs/xfs/xfs_log_format.h b/fs/xfs/xfs_log_format.h index ca7e28a8ed31..f0969c77bdbe 100644 --- a/fs/xfs/xfs_log_format.h +++ b/fs/xfs/xfs_log_format.h @@ -233,178 +233,6 @@ typedef struct xfs_trans_header { { XFS_LI_QUOTAOFF, "XFS_LI_QUOTAOFF" }, \ { XFS_LI_ICREATE, "XFS_LI_ICREATE" } -/* - * Transaction types. Used to distinguish types of buffers. - */ -#define XFS_TRANS_SETATTR_NOT_SIZE 1 -#define XFS_TRANS_SETATTR_SIZE 2 -#define XFS_TRANS_INACTIVE 3 -#define XFS_TRANS_CREATE 4 -#define XFS_TRANS_CREATE_TRUNC 5 -#define XFS_TRANS_TRUNCATE_FILE 6 -#define XFS_TRANS_REMOVE 7 -#define XFS_TRANS_LINK 8 -#define XFS_TRANS_RENAME 9 -#define XFS_TRANS_MKDIR 10 -#define XFS_TRANS_RMDIR 11 -#define XFS_TRANS_SYMLINK 12 -#define XFS_TRANS_SET_DMATTRS 13 -#define XFS_TRANS_GROWFS 14 -#define XFS_TRANS_STRAT_WRITE 15 -#define XFS_TRANS_DIOSTRAT 16 -/* 17 was XFS_TRANS_WRITE_SYNC */ -#define XFS_TRANS_WRITEID 18 -#define XFS_TRANS_ADDAFORK 19 -#define XFS_TRANS_ATTRINVAL 20 -#define XFS_TRANS_ATRUNCATE 21 -#define XFS_TRANS_ATTR_SET 22 -#define XFS_TRANS_ATTR_RM 23 -#define XFS_TRANS_ATTR_FLAG 24 -#define XFS_TRANS_CLEAR_AGI_BUCKET 25 -#define XFS_TRANS_QM_SBCHANGE 26 -/* - * Dummy entries since we use the transaction type to index into the - * trans_type[] in xlog_recover_print_trans_head() - */ -#define XFS_TRANS_DUMMY1 27 -#define XFS_TRANS_DUMMY2 28 -#define XFS_TRANS_QM_QUOTAOFF 29 -#define XFS_TRANS_QM_DQALLOC 30 -#define XFS_TRANS_QM_SETQLIM 31 -#define XFS_TRANS_QM_DQCLUSTER 32 -#define XFS_TRANS_QM_QINOCREATE 33 -#define XFS_TRANS_QM_QUOTAOFF_END 34 -#define XFS_TRANS_SB_UNIT 35 -#define XFS_TRANS_FSYNC_TS 36 -#define XFS_TRANS_GROWFSRT_ALLOC 37 -#define XFS_TRANS_GROWFSRT_ZERO 38 -#define XFS_TRANS_GROWFSRT_FREE 39 -#define XFS_TRANS_SWAPEXT 40 -#define XFS_TRANS_SB_COUNT 41 -#define XFS_TRANS_CHECKPOINT 42 -#define XFS_TRANS_ICREATE 43 -#define XFS_TRANS_TYPE_MAX 43 -/* new transaction types need to be reflected in xfs_logprint(8) */ - -#define XFS_TRANS_TYPES \ - { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \ - { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \ - { XFS_TRANS_INACTIVE, "INACTIVE" }, \ - { XFS_TRANS_CREATE, "CREATE" }, \ - { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \ - { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \ - { XFS_TRANS_REMOVE, "REMOVE" }, \ - { XFS_TRANS_LINK, "LINK" }, \ - { XFS_TRANS_RENAME, "RENAME" }, \ - { XFS_TRANS_MKDIR, "MKDIR" }, \ - { XFS_TRANS_RMDIR, "RMDIR" }, \ - { XFS_TRANS_SYMLINK, "SYMLINK" }, \ - { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \ - { XFS_TRANS_GROWFS, "GROWFS" }, \ - { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \ - { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \ - { XFS_TRANS_WRITEID, "WRITEID" }, \ - { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \ - { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \ - { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \ - { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \ - { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \ - { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \ - { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \ - { XFS_TRANS_QM_SBCHANGE, "QM_SBCHANGE" }, \ - { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \ - { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \ - { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \ - { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \ - { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \ - { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \ - { XFS_TRANS_SB_UNIT, "SB_UNIT" }, \ - { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \ - { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \ - { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \ - { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \ - { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \ - { XFS_TRANS_SB_COUNT, "SB_COUNT" }, \ - { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \ - { XFS_TRANS_DUMMY1, "DUMMY1" }, \ - { XFS_TRANS_DUMMY2, "DUMMY2" }, \ - { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" } - -/* - * This structure is used to track log items associated with - * a transaction. It points to the log item and keeps some - * flags to track the state of the log item. It also tracks - * the amount of space needed to log the item it describes - * once we get to commit processing (see xfs_trans_commit()). - */ -struct xfs_log_item_desc { - struct xfs_log_item *lid_item; - struct list_head lid_trans; - unsigned char lid_flags; -}; - -#define XFS_LID_DIRTY 0x1 - -/* - * Values for t_flags. - */ -#define XFS_TRANS_DIRTY 0x01 /* something needs to be logged */ -#define XFS_TRANS_SB_DIRTY 0x02 /* superblock is modified */ -#define XFS_TRANS_PERM_LOG_RES 0x04 /* xact took a permanent log res */ -#define XFS_TRANS_SYNC 0x08 /* make commit synchronous */ -#define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ -#define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ -#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer - count in superblock */ - -/* - * Values for call flags parameter. - */ -#define XFS_TRANS_RELEASE_LOG_RES 0x4 -#define XFS_TRANS_ABORT 0x8 - -/* - * Field values for xfs_trans_mod_sb. - */ -#define XFS_TRANS_SB_ICOUNT 0x00000001 -#define XFS_TRANS_SB_IFREE 0x00000002 -#define XFS_TRANS_SB_FDBLOCKS 0x00000004 -#define XFS_TRANS_SB_RES_FDBLOCKS 0x00000008 -#define XFS_TRANS_SB_FREXTENTS 0x00000010 -#define XFS_TRANS_SB_RES_FREXTENTS 0x00000020 -#define XFS_TRANS_SB_DBLOCKS 0x00000040 -#define XFS_TRANS_SB_AGCOUNT 0x00000080 -#define XFS_TRANS_SB_IMAXPCT 0x00000100 -#define XFS_TRANS_SB_REXTSIZE 0x00000200 -#define XFS_TRANS_SB_RBMBLOCKS 0x00000400 -#define XFS_TRANS_SB_RBLOCKS 0x00000800 -#define XFS_TRANS_SB_REXTENTS 0x00001000 -#define XFS_TRANS_SB_REXTSLOG 0x00002000 - -/* - * Here we centralize the specification of XFS meta-data buffer - * reference count values. This determine how hard the buffer - * cache tries to hold onto the buffer. - */ -#define XFS_AGF_REF 4 -#define XFS_AGI_REF 4 -#define XFS_AGFL_REF 3 -#define XFS_INO_BTREE_REF 3 -#define XFS_ALLOC_BTREE_REF 2 -#define XFS_BMAP_BTREE_REF 2 -#define XFS_DIR_BTREE_REF 2 -#define XFS_INO_REF 2 -#define XFS_ATTR_BTREE_REF 1 -#define XFS_DQUOT_REF 1 - -/* - * Flags for xfs_trans_ichgtime(). - */ -#define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */ -#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */ -#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */ - - /* * Inode Log Item Format definitions. * @@ -797,7 +625,6 @@ typedef struct xfs_qoff_logformat { char qf_pad[12]; /* padding for future */ } xfs_qoff_logformat_t; - /* * Disk quotas status in m_qflags, and also sb_qflags. 16 bits. */ @@ -849,8 +676,4 @@ struct xfs_icreate_log { __be32 icl_gen; /* inode generation number to use */ }; -int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes); -int xfs_log_calc_minimum_size(struct xfs_mount *); - - #endif /* __XFS_LOG_FORMAT_H__ */ diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index e7ca48e8f515..cbefc1235083 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_inum.h" diff --git a/fs/xfs/xfs_log_rlimit.c b/fs/xfs/xfs_log_rlimit.c index bbcec0bbc12d..0961310abe46 100644 --- a/fs/xfs/xfs_log_rlimit.c +++ b/fs/xfs/xfs_log_rlimit.c @@ -17,6 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_ag.h" diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 5dcc68019d1b..9515f96b4ab7 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_inum.h" diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 3e6c2e6c9cd2..dc2d4f7ad7c9 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index fb6709191811..174390703eb6 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c @@ -21,6 +21,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index e7d84d2d8683..84661d4431fa 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -154,6 +154,4 @@ extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *); extern int xfs_mount_reset_sbqflags(struct xfs_mount *); -extern const struct xfs_buf_ops xfs_dquot_buf_ops; - #endif /* __XFS_QUOTA_H__ */ diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 6f9e63c9fc26..6f63de303e8e 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h index 6835b44f850e..35061d4b614c 100644 --- a/fs/xfs/xfs_sb.h +++ b/fs/xfs/xfs_sb.h @@ -699,7 +699,4 @@ extern void xfs_sb_from_disk(struct xfs_sb *, struct xfs_dsb *); extern void xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t); extern void xfs_sb_quota_from_disk(struct xfs_sb *sbp); -extern const struct xfs_buf_ops xfs_sb_buf_ops; -extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops; - #endif /* __XFS_SB_H__ */ diff --git a/fs/xfs/xfs_shared.h b/fs/xfs/xfs_shared.h new file mode 100644 index 000000000000..8c5035a13df1 --- /dev/null +++ b/fs/xfs/xfs_shared.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2000-2005 Silicon Graphics, Inc. + * Copyright (c) 2013 Red Hat, 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_SHARED_H__ +#define __XFS_SHARED_H__ + +/* + * Definitions shared between kernel and userspace that don't fit into any other + * header file that is shared with userspace. + */ +struct xfs_ifork; +struct xfs_buf; +struct xfs_buf_ops; +struct xfs_mount; +struct xfs_trans; +struct xfs_inode; + +/* + * Buffer verifier operations are widely used, including userspace tools + */ +extern const struct xfs_buf_ops xfs_agf_buf_ops; +extern const struct xfs_buf_ops xfs_agi_buf_ops; +extern const struct xfs_buf_ops xfs_agf_buf_ops; +extern const struct xfs_buf_ops xfs_agfl_buf_ops; +extern const struct xfs_buf_ops xfs_allocbt_buf_ops; +extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops; +extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; +extern const struct xfs_buf_ops xfs_bmbt_buf_ops; +extern const struct xfs_buf_ops xfs_da3_node_buf_ops; +extern const struct xfs_buf_ops xfs_dquot_buf_ops; +extern const struct xfs_buf_ops xfs_symlink_buf_ops; +extern const struct xfs_buf_ops xfs_agi_buf_ops; +extern const struct xfs_buf_ops xfs_inobt_buf_ops; +extern const struct xfs_buf_ops xfs_inode_buf_ops; +extern const struct xfs_buf_ops xfs_inode_buf_ra_ops; +extern const struct xfs_buf_ops xfs_dquot_buf_ops; +extern const struct xfs_buf_ops xfs_sb_buf_ops; +extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops; +extern const struct xfs_buf_ops xfs_symlink_buf_ops; + +/* + * Transaction types. Used to distinguish types of buffers. These never reach + * the log. + */ +#define XFS_TRANS_SETATTR_NOT_SIZE 1 +#define XFS_TRANS_SETATTR_SIZE 2 +#define XFS_TRANS_INACTIVE 3 +#define XFS_TRANS_CREATE 4 +#define XFS_TRANS_CREATE_TRUNC 5 +#define XFS_TRANS_TRUNCATE_FILE 6 +#define XFS_TRANS_REMOVE 7 +#define XFS_TRANS_LINK 8 +#define XFS_TRANS_RENAME 9 +#define XFS_TRANS_MKDIR 10 +#define XFS_TRANS_RMDIR 11 +#define XFS_TRANS_SYMLINK 12 +#define XFS_TRANS_SET_DMATTRS 13 +#define XFS_TRANS_GROWFS 14 +#define XFS_TRANS_STRAT_WRITE 15 +#define XFS_TRANS_DIOSTRAT 16 +/* 17 was XFS_TRANS_WRITE_SYNC */ +#define XFS_TRANS_WRITEID 18 +#define XFS_TRANS_ADDAFORK 19 +#define XFS_TRANS_ATTRINVAL 20 +#define XFS_TRANS_ATRUNCATE 21 +#define XFS_TRANS_ATTR_SET 22 +#define XFS_TRANS_ATTR_RM 23 +#define XFS_TRANS_ATTR_FLAG 24 +#define XFS_TRANS_CLEAR_AGI_BUCKET 25 +#define XFS_TRANS_QM_SBCHANGE 26 +/* + * Dummy entries since we use the transaction type to index into the + * trans_type[] in xlog_recover_print_trans_head() + */ +#define XFS_TRANS_DUMMY1 27 +#define XFS_TRANS_DUMMY2 28 +#define XFS_TRANS_QM_QUOTAOFF 29 +#define XFS_TRANS_QM_DQALLOC 30 +#define XFS_TRANS_QM_SETQLIM 31 +#define XFS_TRANS_QM_DQCLUSTER 32 +#define XFS_TRANS_QM_QINOCREATE 33 +#define XFS_TRANS_QM_QUOTAOFF_END 34 +#define XFS_TRANS_SB_UNIT 35 +#define XFS_TRANS_FSYNC_TS 36 +#define XFS_TRANS_GROWFSRT_ALLOC 37 +#define XFS_TRANS_GROWFSRT_ZERO 38 +#define XFS_TRANS_GROWFSRT_FREE 39 +#define XFS_TRANS_SWAPEXT 40 +#define XFS_TRANS_SB_COUNT 41 +#define XFS_TRANS_CHECKPOINT 42 +#define XFS_TRANS_ICREATE 43 +#define XFS_TRANS_TYPE_MAX 43 +/* new transaction types need to be reflected in xfs_logprint(8) */ + +#define XFS_TRANS_TYPES \ + { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \ + { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \ + { XFS_TRANS_INACTIVE, "INACTIVE" }, \ + { XFS_TRANS_CREATE, "CREATE" }, \ + { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \ + { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \ + { XFS_TRANS_REMOVE, "REMOVE" }, \ + { XFS_TRANS_LINK, "LINK" }, \ + { XFS_TRANS_RENAME, "RENAME" }, \ + { XFS_TRANS_MKDIR, "MKDIR" }, \ + { XFS_TRANS_RMDIR, "RMDIR" }, \ + { XFS_TRANS_SYMLINK, "SYMLINK" }, \ + { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \ + { XFS_TRANS_GROWFS, "GROWFS" }, \ + { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \ + { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \ + { XFS_TRANS_WRITEID, "WRITEID" }, \ + { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \ + { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \ + { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \ + { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \ + { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \ + { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \ + { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \ + { XFS_TRANS_QM_SBCHANGE, "QM_SBCHANGE" }, \ + { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \ + { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \ + { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \ + { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \ + { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \ + { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \ + { XFS_TRANS_SB_UNIT, "SB_UNIT" }, \ + { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \ + { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \ + { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \ + { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \ + { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \ + { XFS_TRANS_SB_COUNT, "SB_COUNT" }, \ + { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \ + { XFS_TRANS_DUMMY1, "DUMMY1" }, \ + { XFS_TRANS_DUMMY2, "DUMMY2" }, \ + { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" } + +/* + * This structure is used to track log items associated with + * a transaction. It points to the log item and keeps some + * flags to track the state of the log item. It also tracks + * the amount of space needed to log the item it describes + * once we get to commit processing (see xfs_trans_commit()). + */ +struct xfs_log_item_desc { + struct xfs_log_item *lid_item; + struct list_head lid_trans; + unsigned char lid_flags; +}; + +#define XFS_LID_DIRTY 0x1 + +/* log size calculation functions */ +int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes); +int xfs_log_calc_minimum_size(struct xfs_mount *); + + +/* + * Values for t_flags. + */ +#define XFS_TRANS_DIRTY 0x01 /* something needs to be logged */ +#define XFS_TRANS_SB_DIRTY 0x02 /* superblock is modified */ +#define XFS_TRANS_PERM_LOG_RES 0x04 /* xact took a permanent log res */ +#define XFS_TRANS_SYNC 0x08 /* make commit synchronous */ +#define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ +#define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ +#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer + count in superblock */ +/* + * Values for call flags parameter. + */ +#define XFS_TRANS_RELEASE_LOG_RES 0x4 +#define XFS_TRANS_ABORT 0x8 + +/* + * Field values for xfs_trans_mod_sb. + */ +#define XFS_TRANS_SB_ICOUNT 0x00000001 +#define XFS_TRANS_SB_IFREE 0x00000002 +#define XFS_TRANS_SB_FDBLOCKS 0x00000004 +#define XFS_TRANS_SB_RES_FDBLOCKS 0x00000008 +#define XFS_TRANS_SB_FREXTENTS 0x00000010 +#define XFS_TRANS_SB_RES_FREXTENTS 0x00000020 +#define XFS_TRANS_SB_DBLOCKS 0x00000040 +#define XFS_TRANS_SB_AGCOUNT 0x00000080 +#define XFS_TRANS_SB_IMAXPCT 0x00000100 +#define XFS_TRANS_SB_REXTSIZE 0x00000200 +#define XFS_TRANS_SB_RBMBLOCKS 0x00000400 +#define XFS_TRANS_SB_RBLOCKS 0x00000800 +#define XFS_TRANS_SB_REXTENTS 0x00001000 +#define XFS_TRANS_SB_REXTSLOG 0x00002000 + +/* + * Here we centralize the specification of XFS meta-data buffer reference count + * values. This determines how hard the buffer cache tries to hold onto the + * buffer. + */ +#define XFS_AGF_REF 4 +#define XFS_AGI_REF 4 +#define XFS_AGFL_REF 3 +#define XFS_INO_BTREE_REF 3 +#define XFS_ALLOC_BTREE_REF 2 +#define XFS_BMAP_BTREE_REF 2 +#define XFS_DIR_BTREE_REF 2 +#define XFS_INO_REF 2 +#define XFS_ATTR_BTREE_REF 1 +#define XFS_DQUOT_REF 1 + +/* + * Flags for xfs_trans_ichgtime(). + */ +#define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */ +#define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */ +#define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */ + + +/* + * Symlink decoding/encoding functions + */ +int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen); +int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, + uint32_t size, struct xfs_buf *bp); +bool xfs_symlink_hdr_ok(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, + uint32_t size, struct xfs_buf *bp); +void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp, + struct xfs_inode *ip, struct xfs_ifork *ifp); + +#endif /* __XFS_SHARED_H__ */ diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index c2e3e9535b26..4886b35b1ef1 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_inum.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index ded282b10bc2..cba781edb192 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -19,6 +19,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_bit.h" #include "xfs_log.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_symlink_remote.c b/fs/xfs/xfs_symlink_remote.c index 01c85e3f6470..4251cd8e8fec 100644 --- a/fs/xfs/xfs_symlink_remote.c +++ b/fs/xfs/xfs_symlink_remote.c @@ -19,6 +19,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_ag.h" diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c index 5d7b3e40705f..29705391c896 100644 --- a/fs/xfs/xfs_trace.c +++ b/fs/xfs/xfs_trace.c @@ -17,8 +17,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 5411e01ab452..3693ce279143 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -19,6 +19,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 8c75b8f67270..0167a65ec851 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -17,7 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index 54ee3c5dee76..4d630d2c2804 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index 8d71b16eccae..3bfb98bec050 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c @@ -17,7 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index 53dfe46f3680..dcab52ec9cb6 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c @@ -17,7 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans.h" #include "xfs_sb.h" diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c index a65a3cc40610..b5d952dbe6a4 100644 --- a/fs/xfs/xfs_trans_resv.c +++ b/fs/xfs/xfs_trans_resv.c @@ -19,6 +19,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_shared.h" #include "xfs_log.h" #include "xfs_trans_resv.h" #include "xfs_trans.h" -- cgit v1.2.3 From 5706278758e334bf6a15f57c18dc16df19c83957 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 15 Oct 2013 09:17:51 +1100 Subject: xfs: unify directory/attribute format definitions The on-disk format definitions for the directory and attribute structures are spread across 3 header files right now, only one of which is dedicated to defining on-disk structures and their manipulation (xfs_dir2_format.h). Pull all the format definitions into a single header file - xfs_da_format.h - and switch all the code over to point at that. Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_attr.c | 1 + fs/xfs/xfs_attr_inactive.c | 1 + fs/xfs/xfs_attr_leaf.c | 1 + fs/xfs/xfs_attr_leaf.h | 230 -------- fs/xfs/xfs_attr_list.c | 1 + fs/xfs/xfs_attr_remote.c | 1 + fs/xfs/xfs_attr_remote.h | 27 - fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_bmap_util.c | 2 +- fs/xfs/xfs_da_btree.c | 2 +- fs/xfs/xfs_da_btree.h | 140 ----- fs/xfs/xfs_da_format.h | 1362 ++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_dir2.c | 2 +- fs/xfs/xfs_dir2_block.c | 2 +- fs/xfs/xfs_dir2_data.c | 2 +- fs/xfs/xfs_dir2_format.h | 964 ------------------------------- fs/xfs/xfs_dir2_leaf.c | 2 +- fs/xfs/xfs_dir2_node.c | 2 +- fs/xfs/xfs_dir2_readdir.c | 2 +- fs/xfs/xfs_dir2_sf.c | 2 +- fs/xfs/xfs_export.c | 3 +- fs/xfs/xfs_file.c | 4 +- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_iops.c | 2 +- fs/xfs/xfs_log_recover.c | 2 +- fs/xfs/xfs_log_rlimit.c | 1 + fs/xfs/xfs_mount.c | 3 +- fs/xfs/xfs_sb.c | 2 +- fs/xfs/xfs_super.c | 2 +- fs/xfs/xfs_symlink.c | 3 +- fs/xfs/xfs_trace.c | 3 +- fs/xfs/xfs_trans.c | 2 +- fs/xfs/xfs_trans_resv.c | 1 + fs/xfs/xfs_xattr.c | 7 +- 34 files changed, 1398 insertions(+), 1387 deletions(-) create mode 100644 fs/xfs/xfs_da_format.h delete mode 100644 fs/xfs/xfs_dir2_format.h diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 21af043bbee8..dd0f48ff8832 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -26,6 +26,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_attr_sf.h" diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index e90a8760bc3d..60b60c008fb7 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c @@ -26,6 +26,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 86db20a9cc02..94838fe67386 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -26,6 +26,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h index da34e64b5323..3ec5ec0b8678 100644 --- a/fs/xfs/xfs_attr_leaf.h +++ b/fs/xfs/xfs_attr_leaf.h @@ -19,16 +19,6 @@ #ifndef __XFS_ATTR_LEAF_H__ #define __XFS_ATTR_LEAF_H__ -/* - * Attribute storage layout, internal structure, access macros, etc. - * - * Attribute lists are structured around Btrees where all the data - * elements are in the leaf nodes. Attribute names are hashed into an int, - * then that int is used as the index into the Btree. Since the hashval - * of an attribute name may not be unique, we may have duplicate keys. The - * internal links in the Btree are logical block offsets into the file. - */ - struct attrlist; struct attrlist_cursor_kern; struct xfs_attr_list_context; @@ -38,226 +28,6 @@ struct xfs_da_state_blk; struct xfs_inode; struct xfs_trans; -/*======================================================================== - * Attribute structure when equal to XFS_LBSIZE(mp) bytes. - *========================================================================*/ - -/* - * This is the structure of the leaf nodes in the Btree. - * - * Struct leaf_entry's are packed from the top. Name/values grow from the - * bottom but are not packed. The freemap contains run-length-encoded entries - * for the free bytes after the leaf_entry's, but only the N largest such, - * smaller runs are dropped. When the freemap doesn't show enough space - * for an allocation, we compact the name/value area and try again. If we - * still don't have enough space, then we have to split the block. The - * name/value structs (both local and remote versions) must be 32bit aligned. - * - * Since we have duplicate hash keys, for each key that matches, compare - * the actual name string. The root and intermediate node search always - * takes the first-in-the-block key match found, so we should only have - * to work "forw"ard. If none matches, continue with the "forw"ard leaf - * nodes until the hash key changes or the attribute name is found. - * - * We store the fact that an attribute is a ROOT/USER/SECURE attribute in - * the leaf_entry. The namespaces are independent only because we also look - * at the namespace bit when we are looking for a matching attribute name. - * - * We also store an "incomplete" bit in the leaf_entry. It shows that an - * attribute is in the middle of being created and should not be shown to - * the user if we crash during the time that the bit is set. We clear the - * bit when we have finished setting up the attribute. We do this because - * we cannot create some large attributes inside a single transaction, and we - * need some indication that we weren't finished if we crash in the middle. - */ -#define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */ - -typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */ - __be16 base; /* base of free region */ - __be16 size; /* length of free region */ -} xfs_attr_leaf_map_t; - -typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */ - xfs_da_blkinfo_t info; /* block type, links, etc. */ - __be16 count; /* count of active leaf_entry's */ - __be16 usedbytes; /* num bytes of names/values stored */ - __be16 firstused; /* first used byte in name area */ - __u8 holes; /* != 0 if blk needs compaction */ - __u8 pad1; - xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE]; - /* N largest free regions */ -} xfs_attr_leaf_hdr_t; - -typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */ - __be32 hashval; /* hash value of name */ - __be16 nameidx; /* index into buffer of name/value */ - __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */ - __u8 pad2; /* unused pad byte */ -} xfs_attr_leaf_entry_t; - -typedef struct xfs_attr_leaf_name_local { - __be16 valuelen; /* number of bytes in value */ - __u8 namelen; /* length of name bytes */ - __u8 nameval[1]; /* name/value bytes */ -} xfs_attr_leaf_name_local_t; - -typedef struct xfs_attr_leaf_name_remote { - __be32 valueblk; /* block number of value bytes */ - __be32 valuelen; /* number of bytes in value */ - __u8 namelen; /* length of name bytes */ - __u8 name[1]; /* name bytes */ -} xfs_attr_leaf_name_remote_t; - -typedef struct xfs_attr_leafblock { - xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */ - xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */ - xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */ - xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */ -} xfs_attr_leafblock_t; - -/* - * CRC enabled leaf structures. Called "version 3" structures to match the - * version number of the directory and dablk structures for this feature, and - * attr2 is already taken by the variable inode attribute fork size feature. - */ -struct xfs_attr3_leaf_hdr { - struct xfs_da3_blkinfo info; - __be16 count; - __be16 usedbytes; - __be16 firstused; - __u8 holes; - __u8 pad1; - struct xfs_attr_leaf_map freemap[XFS_ATTR_LEAF_MAPSIZE]; - __be32 pad2; /* 64 bit alignment */ -}; - -#define XFS_ATTR3_LEAF_CRC_OFF (offsetof(struct xfs_attr3_leaf_hdr, info.crc)) - -struct xfs_attr3_leafblock { - struct xfs_attr3_leaf_hdr hdr; - struct xfs_attr_leaf_entry entries[1]; - - /* - * The rest of the block contains the following structures after the - * leaf entries, growing from the bottom up. The variables are never - * referenced, the locations accessed purely from helper functions. - * - * struct xfs_attr_leaf_name_local - * struct xfs_attr_leaf_name_remote - */ -}; - -/* - * incore, neutral version of the attribute leaf header - */ -struct xfs_attr3_icleaf_hdr { - __uint32_t forw; - __uint32_t back; - __uint16_t magic; - __uint16_t count; - __uint16_t usedbytes; - __uint16_t firstused; - __u8 holes; - struct { - __uint16_t base; - __uint16_t size; - } freemap[XFS_ATTR_LEAF_MAPSIZE]; -}; - -/* - * Flags used in the leaf_entry[i].flags field. - * NOTE: the INCOMPLETE bit must not collide with the flags bits specified - * on the system call, they are "or"ed together for various operations. - */ -#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ -#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ -#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ -#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ -#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) -#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) -#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT) -#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) - -/* - * Conversion macros for converting namespace bits from argument flags - * to ondisk flags. - */ -#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE) -#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE) -#define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK) -#define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK) -#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\ - ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0)) -#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\ - ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0)) - -/* - * Alignment for namelist and valuelist entries (since they are mixed - * there can be only one alignment value) - */ -#define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t)) - -static inline int -xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp) -{ - if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) - return sizeof(struct xfs_attr3_leaf_hdr); - return sizeof(struct xfs_attr_leaf_hdr); -} - -static inline struct xfs_attr_leaf_entry * -xfs_attr3_leaf_entryp(xfs_attr_leafblock_t *leafp) -{ - if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) - return &((struct xfs_attr3_leafblock *)leafp)->entries[0]; - return &leafp->entries[0]; -} - -/* - * Cast typed pointers for "local" and "remote" name/value structs. - */ -static inline char * -xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx) -{ - struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp); - - return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)]; -} - -static inline xfs_attr_leaf_name_remote_t * -xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx) -{ - return (xfs_attr_leaf_name_remote_t *)xfs_attr3_leaf_name(leafp, idx); -} - -static inline xfs_attr_leaf_name_local_t * -xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx) -{ - return (xfs_attr_leaf_name_local_t *)xfs_attr3_leaf_name(leafp, idx); -} - -/* - * Calculate total bytes used (including trailing pad for alignment) for - * a "local" name/value structure, a "remote" name/value structure, and - * a pointer which might be either. - */ -static inline int xfs_attr_leaf_entsize_remote(int nlen) -{ - return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \ - XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1); -} - -static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen) -{ - return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) + - XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1); -} - -static inline int xfs_attr_leaf_entsize_local_max(int bsize) -{ - return (((bsize) >> 1) + ((bsize) >> 2)); -} - /* * Used to keep a list of "remote value" extents when unlinking an inode. */ diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index cbc80d485177..8ba8e4b5e310 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -25,6 +25,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c index 712a502de619..578f21b70875 100644 --- a/fs/xfs/xfs_attr_remote.c +++ b/fs/xfs/xfs_attr_remote.c @@ -26,6 +26,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_error.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" diff --git a/fs/xfs/xfs_attr_remote.h b/fs/xfs/xfs_attr_remote.h index b3e1e1bdfb3b..5a9acfa156d7 100644 --- a/fs/xfs/xfs_attr_remote.h +++ b/fs/xfs/xfs_attr_remote.h @@ -18,33 +18,6 @@ #ifndef __XFS_ATTR_REMOTE_H__ #define __XFS_ATTR_REMOTE_H__ -#define XFS_ATTR3_RMT_MAGIC 0x5841524d /* XARM */ - -/* - * There is one of these headers per filesystem block in a remote attribute. - * This is done to ensure there is a 1:1 mapping between the attribute value - * length and the number of blocks needed to store the attribute. This makes the - * verification of a buffer a little more complex, but greatly simplifies the - * allocation, reading and writing of these attributes as we don't have to guess - * the number of blocks needed to store the attribute data. - */ -struct xfs_attr3_rmt_hdr { - __be32 rm_magic; - __be32 rm_offset; - __be32 rm_bytes; - __be32 rm_crc; - uuid_t rm_uuid; - __be64 rm_owner; - __be64 rm_blkno; - __be64 rm_lsn; -}; - -#define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc) - -#define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \ - ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ - sizeof(struct xfs_attr3_rmt_hdr) : 0)) - int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen); int xfs_attr_rmtval_get(struct xfs_da_args *args); diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 6870aad5d815..b5cb377bd2bb 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -26,8 +26,8 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 4f246628a900..74ff478b9b75 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -27,7 +27,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_da_btree.h" +#include "xfs_da_format.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index ac51abeb4782..4ec68c361c4c 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -26,9 +26,9 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_dinode.h" diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index a762cfa4097d..e492dcadd032 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h @@ -24,146 +24,6 @@ struct xfs_inode; struct xfs_trans; struct zone; -/*======================================================================== - * Directory Structure when greater than XFS_LBSIZE(mp) bytes. - *========================================================================*/ - -/* - * This structure is common to both leaf nodes and non-leaf nodes in the Btree. - * - * It is used to manage a doubly linked list of all blocks at the same - * level in the Btree, and to identify which type of block this is. - */ -#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */ -#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */ -#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ -#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ - -typedef struct xfs_da_blkinfo { - __be32 forw; /* previous block in list */ - __be32 back; /* following block in list */ - __be16 magic; /* validity check on block */ - __be16 pad; /* unused */ -} xfs_da_blkinfo_t; - -/* - * CRC enabled directory structure types - * - * The headers change size for the additional verification information, but - * otherwise the tree layouts and contents are unchanged. Hence the da btree - * code can use the struct xfs_da_blkinfo for manipulating the tree links and - * magic numbers without modification for both v2 and v3 nodes. - */ -#define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */ -#define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */ -#define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */ -#define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */ - -struct xfs_da3_blkinfo { - /* - * the node link manipulation code relies on the fact that the first - * element of this structure is the struct xfs_da_blkinfo so it can - * ignore the differences in the rest of the structures. - */ - struct xfs_da_blkinfo hdr; - __be32 crc; /* CRC of block */ - __be64 blkno; /* first block of the buffer */ - __be64 lsn; /* sequence number of last write */ - uuid_t uuid; /* filesystem we belong to */ - __be64 owner; /* inode that owns the block */ -}; - -/* - * This is the structure of the root and intermediate nodes in the Btree. - * The leaf nodes are defined above. - * - * Entries are not packed. - * - * Since we have duplicate keys, use a binary search but always follow - * all match in the block, not just the first match found. - */ -#define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */ - -typedef struct xfs_da_node_hdr { - struct xfs_da_blkinfo info; /* block type, links, etc. */ - __be16 __count; /* count of active entries */ - __be16 __level; /* level above leaves (leaf == 0) */ -} xfs_da_node_hdr_t; - -struct xfs_da3_node_hdr { - struct xfs_da3_blkinfo info; /* block type, links, etc. */ - __be16 __count; /* count of active entries */ - __be16 __level; /* level above leaves (leaf == 0) */ - __be32 __pad32; -}; - -#define XFS_DA3_NODE_CRC_OFF (offsetof(struct xfs_da3_node_hdr, info.crc)) - -typedef struct xfs_da_node_entry { - __be32 hashval; /* hash value for this descendant */ - __be32 before; /* Btree block before this key */ -} xfs_da_node_entry_t; - -typedef struct xfs_da_intnode { - struct xfs_da_node_hdr hdr; - struct xfs_da_node_entry __btree[]; -} xfs_da_intnode_t; - -struct xfs_da3_intnode { - struct xfs_da3_node_hdr hdr; - struct xfs_da_node_entry __btree[]; -}; - -/* - * In-core version of the node header to abstract the differences in the v2 and - * v3 disk format of the headers. Callers need to convert to/from disk format as - * appropriate. - */ -struct xfs_da3_icnode_hdr { - __uint32_t forw; - __uint32_t back; - __uint16_t magic; - __uint16_t count; - __uint16_t level; -}; - -extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to, - struct xfs_da_intnode *from); -extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to, - struct xfs_da3_icnode_hdr *from); - -static inline int -__xfs_da3_node_hdr_size(bool v3) -{ - if (v3) - return sizeof(struct xfs_da3_node_hdr); - return sizeof(struct xfs_da_node_hdr); -} -static inline int -xfs_da3_node_hdr_size(struct xfs_da_intnode *dap) -{ - bool v3 = dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC); - - return __xfs_da3_node_hdr_size(v3); -} - -static inline struct xfs_da_node_entry * -xfs_da3_node_tree_p(struct xfs_da_intnode *dap) -{ - if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) { - struct xfs_da3_intnode *dap3 = (struct xfs_da3_intnode *)dap; - return dap3->__btree; - } - return dap->__btree; -} - -extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to, - struct xfs_da_intnode *from); -extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to, - struct xfs_da3_icnode_hdr *from); - -#define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize - /*======================================================================== * Btree searching and modification structure definitions. *========================================================================*/ diff --git a/fs/xfs/xfs_da_format.h b/fs/xfs/xfs_da_format.h new file mode 100644 index 000000000000..89a1a219c8ff --- /dev/null +++ b/fs/xfs/xfs_da_format.h @@ -0,0 +1,1362 @@ +/* + * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. + * Copyright (c) 2013 Red Hat, 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_DA_FORMAT_H__ +#define __XFS_DA_FORMAT_H__ + +/*======================================================================== + * Directory Structure when greater than XFS_LBSIZE(mp) bytes. + *========================================================================*/ + +/* + * This structure is common to both leaf nodes and non-leaf nodes in the Btree. + * + * It is used to manage a doubly linked list of all blocks at the same + * level in the Btree, and to identify which type of block this is. + */ +#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */ +#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */ +#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ +#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ + +typedef struct xfs_da_blkinfo { + __be32 forw; /* previous block in list */ + __be32 back; /* following block in list */ + __be16 magic; /* validity check on block */ + __be16 pad; /* unused */ +} xfs_da_blkinfo_t; + +/* + * CRC enabled directory structure types + * + * The headers change size for the additional verification information, but + * otherwise the tree layouts and contents are unchanged. Hence the da btree + * code can use the struct xfs_da_blkinfo for manipulating the tree links and + * magic numbers without modification for both v2 and v3 nodes. + */ +#define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */ +#define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */ +#define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */ +#define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */ + +struct xfs_da3_blkinfo { + /* + * the node link manipulation code relies on the fact that the first + * element of this structure is the struct xfs_da_blkinfo so it can + * ignore the differences in the rest of the structures. + */ + struct xfs_da_blkinfo hdr; + __be32 crc; /* CRC of block */ + __be64 blkno; /* first block of the buffer */ + __be64 lsn; /* sequence number of last write */ + uuid_t uuid; /* filesystem we belong to */ + __be64 owner; /* inode that owns the block */ +}; + +/* + * This is the structure of the root and intermediate nodes in the Btree. + * The leaf nodes are defined above. + * + * Entries are not packed. + * + * Since we have duplicate keys, use a binary search but always follow + * all match in the block, not just the first match found. + */ +#define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */ + +typedef struct xfs_da_node_hdr { + struct xfs_da_blkinfo info; /* block type, links, etc. */ + __be16 __count; /* count of active entries */ + __be16 __level; /* level above leaves (leaf == 0) */ +} xfs_da_node_hdr_t; + +struct xfs_da3_node_hdr { + struct xfs_da3_blkinfo info; /* block type, links, etc. */ + __be16 __count; /* count of active entries */ + __be16 __level; /* level above leaves (leaf == 0) */ + __be32 __pad32; +}; + +#define XFS_DA3_NODE_CRC_OFF (offsetof(struct xfs_da3_node_hdr, info.crc)) + +typedef struct xfs_da_node_entry { + __be32 hashval; /* hash value for this descendant */ + __be32 before; /* Btree block before this key */ +} xfs_da_node_entry_t; + +typedef struct xfs_da_intnode { + struct xfs_da_node_hdr hdr; + struct xfs_da_node_entry __btree[]; +} xfs_da_intnode_t; + +struct xfs_da3_intnode { + struct xfs_da3_node_hdr hdr; + struct xfs_da_node_entry __btree[]; +}; + +/* + * In-core version of the node header to abstract the differences in the v2 and + * v3 disk format of the headers. Callers need to convert to/from disk format as + * appropriate. + */ +struct xfs_da3_icnode_hdr { + __uint32_t forw; + __uint32_t back; + __uint16_t magic; + __uint16_t count; + __uint16_t level; +}; + +extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to, + struct xfs_da_intnode *from); +extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to, + struct xfs_da3_icnode_hdr *from); + +static inline int +__xfs_da3_node_hdr_size(bool v3) +{ + if (v3) + return sizeof(struct xfs_da3_node_hdr); + return sizeof(struct xfs_da_node_hdr); +} +static inline int +xfs_da3_node_hdr_size(struct xfs_da_intnode *dap) +{ + bool v3 = dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC); + + return __xfs_da3_node_hdr_size(v3); +} + +static inline struct xfs_da_node_entry * +xfs_da3_node_tree_p(struct xfs_da_intnode *dap) +{ + if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) { + struct xfs_da3_intnode *dap3 = (struct xfs_da3_intnode *)dap; + return dap3->__btree; + } + return dap->__btree; +} + +extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to, + struct xfs_da_intnode *from); +extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to, + struct xfs_da3_icnode_hdr *from); + +#define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize + +/* + * Directory version 2. + * + * There are 4 possible formats: + * - shortform - embedded into the inode + * - single block - data with embedded leaf at the end + * - multiple data blocks, single leaf+freeindex block + * - data blocks, node and leaf blocks (btree), freeindex blocks + * + * Note: many node blocks structures and constants are shared with the attr + * code and defined in xfs_da_btree.h. + */ + +#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: single block dirs */ +#define XFS_DIR2_DATA_MAGIC 0x58443244 /* XD2D: multiblock dirs */ +#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */ + +/* + * Directory Version 3 With CRCs. + * + * The tree formats are the same as for version 2 directories. The difference + * is in the block header and dirent formats. In many cases the v3 structures + * use v2 definitions as they are no different and this makes code sharing much + * easier. + * + * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the + * format is v2 then they switch to the existing v2 code, or the format is v3 + * they implement the v3 functionality. This means the existing dir2 is a mix of + * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called + * where there is a difference in the formats, otherwise the code is unchanged. + * + * Where it is possible, the code decides what to do based on the magic numbers + * in the blocks rather than feature bits in the superblock. This means the code + * is as independent of the external XFS code as possible as doesn't require + * passing struct xfs_mount pointers into places where it isn't really + * necessary. + * + * Version 3 includes: + * + * - a larger block header for CRC and identification purposes and so the + * offsets of all the structures inside the blocks are different. + * + * - new magic numbers to be able to detect the v2/v3 types on the fly. + */ + +#define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */ +#define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */ +#define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */ + +/* + * Dirents in version 3 directories have a file type field. Additions to this + * list are an on-disk format change, requiring feature bits. Valid values + * are as follows: + */ +#define XFS_DIR3_FT_UNKNOWN 0 +#define XFS_DIR3_FT_REG_FILE 1 +#define XFS_DIR3_FT_DIR 2 +#define XFS_DIR3_FT_CHRDEV 3 +#define XFS_DIR3_FT_BLKDEV 4 +#define XFS_DIR3_FT_FIFO 5 +#define XFS_DIR3_FT_SOCK 6 +#define XFS_DIR3_FT_SYMLINK 7 +#define XFS_DIR3_FT_WHT 8 + +#define XFS_DIR3_FT_MAX 9 + +/* + * Byte offset in data block and shortform entry. + */ +typedef __uint16_t xfs_dir2_data_off_t; +#define NULLDATAOFF 0xffffU +typedef uint xfs_dir2_data_aoff_t; /* argument form */ + +/* + * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. + * Only need 16 bits, this is the byte offset into the single block form. + */ +typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t; + +/* + * Offset in data space of a data entry. + */ +typedef __uint32_t xfs_dir2_dataptr_t; +#define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff) +#define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0) + +/* + * Byte offset in a directory. + */ +typedef xfs_off_t xfs_dir2_off_t; + +/* + * Directory block number (logical dirblk in file) + */ +typedef __uint32_t xfs_dir2_db_t; + +/* + * Inode number stored as 8 8-bit values. + */ +typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t; + +/* + * Inode number stored as 4 8-bit values. + * Works a lot of the time, when all the inode numbers in a directory + * fit in 32 bits. + */ +typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t; + +typedef union { + xfs_dir2_ino8_t i8; + xfs_dir2_ino4_t i4; +} xfs_dir2_inou_t; +#define XFS_DIR2_MAX_SHORT_INUM ((xfs_ino_t)0xffffffffULL) + +/* + * Directory layout when stored internal to an inode. + * + * Small directories are packed as tightly as possible so as to fit into the + * literal area of the inode. These "shortform" directories consist of a + * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry + * structures. Due the different inode number storage size and the variable + * length name field in the xfs_dir2_sf_entry all these structure are + * variable length, and the accessors in this file should be used to iterate + * over them. + */ +typedef struct xfs_dir2_sf_hdr { + __uint8_t count; /* count of entries */ + __uint8_t i8count; /* count of 8-byte inode #s */ + xfs_dir2_inou_t parent; /* parent dir inode number */ +} __arch_pack xfs_dir2_sf_hdr_t; + +typedef struct xfs_dir2_sf_entry { + __u8 namelen; /* actual name length */ + xfs_dir2_sf_off_t offset; /* saved offset */ + __u8 name[]; /* name, variable size */ + /* + * A single byte containing the file type field follows the inode + * number for version 3 directory entries. + * + * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a + * variable offset after the name. + */ +} __arch_pack xfs_dir2_sf_entry_t; + +static inline int xfs_dir2_sf_hdr_size(int i8count) +{ + return sizeof(struct xfs_dir2_sf_hdr) - + (i8count == 0) * + (sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t)); +} + +static inline xfs_dir2_data_aoff_t +xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep) +{ + return get_unaligned_be16(&sfep->offset.i); +} + +static inline void +xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off) +{ + put_unaligned_be16(off, &sfep->offset.i); +} + +static inline struct xfs_dir2_sf_entry * +xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) +{ + return (struct xfs_dir2_sf_entry *) + ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count)); +} + +static inline int +xfs_dir3_sf_entsize( + struct xfs_mount *mp, + struct xfs_dir2_sf_hdr *hdr, + int len) +{ + int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */ + + count += len; /* name */ + count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) : + sizeof(xfs_dir2_ino4_t); /* ino # */ + if (xfs_sb_version_hasftype(&mp->m_sb)) + count += sizeof(__uint8_t); /* file type */ + return count; +} + +static inline struct xfs_dir2_sf_entry * +xfs_dir3_sf_nextentry( + struct xfs_mount *mp, + struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep) +{ + return (struct xfs_dir2_sf_entry *) + ((char *)sfep + xfs_dir3_sf_entsize(mp, hdr, sfep->namelen)); +} + +/* + * in dir3 shortform directories, the file type field is stored at a variable + * offset after the inode number. Because it's only a single byte, endian + * conversion is not necessary. + */ +static inline __uint8_t * +xfs_dir3_sfe_ftypep( + struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep) +{ + return (__uint8_t *)&sfep->name[sfep->namelen]; +} + +static inline __uint8_t +xfs_dir3_sfe_get_ftype( + struct xfs_mount *mp, + struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep) +{ + __uint8_t *ftp; + + if (!xfs_sb_version_hasftype(&mp->m_sb)) + return XFS_DIR3_FT_UNKNOWN; + + ftp = xfs_dir3_sfe_ftypep(hdr, sfep); + if (*ftp >= XFS_DIR3_FT_MAX) + return XFS_DIR3_FT_UNKNOWN; + return *ftp; +} + +static inline void +xfs_dir3_sfe_put_ftype( + struct xfs_mount *mp, + struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep, + __uint8_t ftype) +{ + __uint8_t *ftp; + + ASSERT(ftype < XFS_DIR3_FT_MAX); + + if (!xfs_sb_version_hasftype(&mp->m_sb)) + return; + ftp = xfs_dir3_sfe_ftypep(hdr, sfep); + *ftp = ftype; +} + +/* + * Data block structures. + * + * A pure data block looks like the following drawing on disk: + * + * +-------------------------------------------------+ + * | xfs_dir2_data_hdr_t | + * +-------------------------------------------------+ + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | + * | ... | + * +-------------------------------------------------+ + * | unused space | + * +-------------------------------------------------+ + * + * As all the entries are variable size structures the accessors below should + * be used to iterate over them. + * + * In addition to the pure data blocks for the data and node formats, + * most structures are also used for the combined data/freespace "block" + * format below. + */ + +#define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */ +#define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG) +#define XFS_DIR2_DATA_FREE_TAG 0xffff +#define XFS_DIR2_DATA_FD_COUNT 3 + +/* + * Directory address space divided into sections, + * spaces separated by 32GB. + */ +#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) +#define XFS_DIR2_DATA_SPACE 0 +#define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE) +#define XFS_DIR2_DATA_FIRSTDB(mp) \ + xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET) + +/* + * Describe a free area in the data block. + * + * The freespace will be formatted as a xfs_dir2_data_unused_t. + */ +typedef struct xfs_dir2_data_free { + __be16 offset; /* start of freespace */ + __be16 length; /* length of freespace */ +} xfs_dir2_data_free_t; + +/* + * Header for the data blocks. + * + * The code knows that XFS_DIR2_DATA_FD_COUNT is 3. + */ +typedef struct xfs_dir2_data_hdr { + __be32 magic; /* XFS_DIR2_DATA_MAGIC or */ + /* XFS_DIR2_BLOCK_MAGIC */ + xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT]; +} xfs_dir2_data_hdr_t; + +/* + * define a structure for all the verification fields we are adding to the + * directory block structures. This will be used in several structures. + * The magic number must be the first entry to align with all the dir2 + * structures so we determine how to decode them just by the magic number. + */ +struct xfs_dir3_blk_hdr { + __be32 magic; /* magic number */ + __be32 crc; /* CRC of block */ + __be64 blkno; /* first block of the buffer */ + __be64 lsn; /* sequence number of last write */ + uuid_t uuid; /* filesystem we belong to */ + __be64 owner; /* inode that owns the block */ +}; + +struct xfs_dir3_data_hdr { + struct xfs_dir3_blk_hdr hdr; + xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT]; + __be32 pad; /* 64 bit alignment */ +}; + +#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc) + +static inline struct xfs_dir2_data_free * +xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) +{ + if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || + hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { + struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr; + return hdr3->best_free; + } + return hdr->bestfree; +} + +/* + * Active entry in a data block. + * + * Aligned to 8 bytes. After the variable length name field there is a + * 2 byte tag field, which can be accessed using xfs_dir3_data_entry_tag_p. + * + * For dir3 structures, there is file type field between the name and the tag. + * This can only be manipulated by helper functions. It is packed hard against + * the end of the name so any padding for rounding is between the file type and + * the tag. + */ +typedef struct xfs_dir2_data_entry { + __be64 inumber; /* inode number */ + __u8 namelen; /* name length */ + __u8 name[]; /* name bytes, no null */ + /* __u8 filetype; */ /* type of inode we point to */ + /* __be16 tag; */ /* starting offset of us */ +} xfs_dir2_data_entry_t; + +/* + * Unused entry in a data block. + * + * Aligned to 8 bytes. Tag appears as the last 2 bytes and must be accessed + * using xfs_dir2_data_unused_tag_p. + */ +typedef struct xfs_dir2_data_unused { + __be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */ + __be16 length; /* total free length */ + /* variable offset */ + __be16 tag; /* starting offset of us */ +} xfs_dir2_data_unused_t; + +/* + * Size of a data entry. + */ +static inline int +__xfs_dir3_data_entsize( + bool ftype, + int n) +{ + int size = offsetof(struct xfs_dir2_data_entry, name[0]); + + size += n; + size += sizeof(xfs_dir2_data_off_t); + if (ftype) + size += sizeof(__uint8_t); + return roundup(size, XFS_DIR2_DATA_ALIGN); +} +static inline int +xfs_dir3_data_entsize( + struct xfs_mount *mp, + int n) +{ + bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false; + return __xfs_dir3_data_entsize(ftype, n); +} + +static inline __uint8_t +xfs_dir3_dirent_get_ftype( + struct xfs_mount *mp, + struct xfs_dir2_data_entry *dep) +{ + if (xfs_sb_version_hasftype(&mp->m_sb)) { + __uint8_t type = dep->name[dep->namelen]; + + ASSERT(type < XFS_DIR3_FT_MAX); + if (type < XFS_DIR3_FT_MAX) + return type; + + } + return XFS_DIR3_FT_UNKNOWN; +} + +static inline void +xfs_dir3_dirent_put_ftype( + struct xfs_mount *mp, + struct xfs_dir2_data_entry *dep, + __uint8_t type) +{ + ASSERT(type < XFS_DIR3_FT_MAX); + ASSERT(dep->namelen != 0); + + if (xfs_sb_version_hasftype(&mp->m_sb)) + dep->name[dep->namelen] = type; +} + +/* + * Pointer to an entry's tag word. + */ +static inline __be16 * +xfs_dir3_data_entry_tag_p( + struct xfs_mount *mp, + struct xfs_dir2_data_entry *dep) +{ + return (__be16 *)((char *)dep + + xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16)); +} + +/* + * Pointer to a freespace's tag word. + */ +static inline __be16 * +xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) +{ + return (__be16 *)((char *)dup + + be16_to_cpu(dup->length) - sizeof(__be16)); +} + +static inline size_t +xfs_dir3_data_hdr_size(bool dir3) +{ + if (dir3) + return sizeof(struct xfs_dir3_data_hdr); + return sizeof(struct xfs_dir2_data_hdr); +} + +static inline size_t +xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr) +{ + bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || + hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); + return xfs_dir3_data_hdr_size(dir3); +} + +static inline struct xfs_dir2_data_entry * +xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir3_data_entry_offset(hdr)); +} + +static inline struct xfs_dir2_data_unused * +xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_unused *) + ((char *)hdr + xfs_dir3_data_entry_offset(hdr)); +} + +/* + * Offsets of . and .. in data space (always block 0) + * + * XXX: there is scope for significant optimisation of the logic here. Right + * now we are checking for "dir3 format" over and over again. Ideally we should + * only do it once for each operation. + */ +static inline xfs_dir2_data_aoff_t +xfs_dir3_data_dot_offset(struct xfs_mount *mp) +{ + return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)); +} + +static inline xfs_dir2_data_aoff_t +xfs_dir3_data_dotdot_offset(struct xfs_mount *mp) +{ + return xfs_dir3_data_dot_offset(mp) + + xfs_dir3_data_entsize(mp, 1); +} + +static inline xfs_dir2_data_aoff_t +xfs_dir3_data_first_offset(struct xfs_mount *mp) +{ + return xfs_dir3_data_dotdot_offset(mp) + + xfs_dir3_data_entsize(mp, 2); +} + +/* + * location of . and .. in data space (always block 0) + */ +static inline struct xfs_dir2_data_entry * +xfs_dir3_data_dot_entry_p( + struct xfs_mount *mp, + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir3_data_dot_offset(mp)); +} + +static inline struct xfs_dir2_data_entry * +xfs_dir3_data_dotdot_entry_p( + struct xfs_mount *mp, + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir3_data_dotdot_offset(mp)); +} + +static inline struct xfs_dir2_data_entry * +xfs_dir3_data_first_entry_p( + struct xfs_mount *mp, + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir3_data_first_offset(mp)); +} + +/* + * Leaf block structures. + * + * A pure leaf block looks like the following drawing on disk: + * + * +---------------------------+ + * | xfs_dir2_leaf_hdr_t | + * +---------------------------+ + * | xfs_dir2_leaf_entry_t | + * | xfs_dir2_leaf_entry_t | + * | xfs_dir2_leaf_entry_t | + * | xfs_dir2_leaf_entry_t | + * | ... | + * +---------------------------+ + * | xfs_dir2_data_off_t | + * | xfs_dir2_data_off_t | + * | xfs_dir2_data_off_t | + * | ... | + * +---------------------------+ + * | xfs_dir2_leaf_tail_t | + * +---------------------------+ + * + * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block + * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present + * for directories with separate leaf nodes and free space blocks + * (magic = XFS_DIR2_LEAFN_MAGIC). + * + * As all the entries are variable size structures the accessors below should + * be used to iterate over them. + */ + +/* + * Offset of the leaf/node space. First block in this space + * is the btree root. + */ +#define XFS_DIR2_LEAF_SPACE 1 +#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) +#define XFS_DIR2_LEAF_FIRSTDB(mp) \ + xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET) + +/* + * Leaf block header. + */ +typedef struct xfs_dir2_leaf_hdr { + xfs_da_blkinfo_t info; /* header for da routines */ + __be16 count; /* count of entries */ + __be16 stale; /* count of stale entries */ +} xfs_dir2_leaf_hdr_t; + +struct xfs_dir3_leaf_hdr { + struct xfs_da3_blkinfo info; /* header for da routines */ + __be16 count; /* count of entries */ + __be16 stale; /* count of stale entries */ + __be32 pad; /* 64 bit alignment */ +}; + +struct xfs_dir3_icleaf_hdr { + __uint32_t forw; + __uint32_t back; + __uint16_t magic; + __uint16_t count; + __uint16_t stale; +}; + +/* + * Leaf block entry. + */ +typedef struct xfs_dir2_leaf_entry { + __be32 hashval; /* hash value of name */ + __be32 address; /* address of data entry */ +} xfs_dir2_leaf_entry_t; + +/* + * Leaf block tail. + */ +typedef struct xfs_dir2_leaf_tail { + __be32 bestcount; +} xfs_dir2_leaf_tail_t; + +/* + * Leaf block. + */ +typedef struct xfs_dir2_leaf { + xfs_dir2_leaf_hdr_t hdr; /* leaf header */ + xfs_dir2_leaf_entry_t __ents[]; /* entries */ +} xfs_dir2_leaf_t; + +struct xfs_dir3_leaf { + struct xfs_dir3_leaf_hdr hdr; /* leaf header */ + struct xfs_dir2_leaf_entry __ents[]; /* entries */ +}; + +#define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc) + +extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to, + struct xfs_dir2_leaf *from); + +static inline int +xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp) +{ + if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || + lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) + return sizeof(struct xfs_dir3_leaf_hdr); + return sizeof(struct xfs_dir2_leaf_hdr); +} + +static inline int +xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) +{ + return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) / + (uint)sizeof(struct xfs_dir2_leaf_entry); +} + +/* + * Get address of the bestcount field in the single-leaf block. + */ +static inline struct xfs_dir2_leaf_entry * +xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp) +{ + if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || + lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { + struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp; + return lp3->__ents; + } + return lp->__ents; +} + +/* + * Get address of the bestcount field in the single-leaf block. + */ +static inline struct xfs_dir2_leaf_tail * +xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) +{ + return (struct xfs_dir2_leaf_tail *) + ((char *)lp + mp->m_dirblksize - + sizeof(struct xfs_dir2_leaf_tail)); +} + +/* + * Get address of the bests array in the single-leaf block. + */ +static inline __be16 * +xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp) +{ + return (__be16 *)ltp - be32_to_cpu(ltp->bestcount); +} + +/* + * DB blocks here are logical directory block numbers, not filesystem blocks. + */ + +/* + * Convert dataptr to byte in file space + */ +static inline xfs_dir2_off_t +xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) +{ + return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG; +} + +/* + * Convert byte in file space to dataptr. It had better be aligned. + */ +static inline xfs_dir2_dataptr_t +xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by) +{ + return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG); +} + +/* + * Convert byte in space to (DB) block + */ +static inline xfs_dir2_db_t +xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by) +{ + return (xfs_dir2_db_t) + (by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)); +} + +/* + * Convert dataptr to a block number + */ +static inline xfs_dir2_db_t +xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) +{ + return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp)); +} + +/* + * Convert byte in space to offset in a block + */ +static inline xfs_dir2_data_aoff_t +xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by) +{ + return (xfs_dir2_data_aoff_t)(by & + ((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1)); +} + +/* + * Convert dataptr to a byte offset in a block + */ +static inline xfs_dir2_data_aoff_t +xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) +{ + return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp)); +} + +/* + * Convert block and offset to byte in space + */ +static inline xfs_dir2_off_t +xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db, + xfs_dir2_data_aoff_t o) +{ + return ((xfs_dir2_off_t)db << + (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o; +} + +/* + * Convert block (DB) to block (dablk) + */ +static inline xfs_dablk_t +xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db) +{ + return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog); +} + +/* + * Convert byte in space to (DA) block + */ +static inline xfs_dablk_t +xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by) +{ + return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by)); +} + +/* + * Convert block and offset to dataptr + */ +static inline xfs_dir2_dataptr_t +xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db, + xfs_dir2_data_aoff_t o) +{ + return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o)); +} + +/* + * Convert block (dablk) to block (DB) + */ +static inline xfs_dir2_db_t +xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da) +{ + return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog); +} + +/* + * Convert block (dablk) to byte offset in space + */ +static inline xfs_dir2_off_t +xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da) +{ + return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0); +} + +/* + * Free space block defintions for the node format. + */ + +/* + * Offset of the freespace index. + */ +#define XFS_DIR2_FREE_SPACE 2 +#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) +#define XFS_DIR2_FREE_FIRSTDB(mp) \ + xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET) + +typedef struct xfs_dir2_free_hdr { + __be32 magic; /* XFS_DIR2_FREE_MAGIC */ + __be32 firstdb; /* db of first entry */ + __be32 nvalid; /* count of valid entries */ + __be32 nused; /* count of used entries */ +} xfs_dir2_free_hdr_t; + +typedef struct xfs_dir2_free { + xfs_dir2_free_hdr_t hdr; /* block header */ + __be16 bests[]; /* best free counts */ + /* unused entries are -1 */ +} xfs_dir2_free_t; + +struct xfs_dir3_free_hdr { + struct xfs_dir3_blk_hdr hdr; + __be32 firstdb; /* db of first entry */ + __be32 nvalid; /* count of valid entries */ + __be32 nused; /* count of used entries */ + __be32 pad; /* 64 bit alignment */ +}; + +struct xfs_dir3_free { + struct xfs_dir3_free_hdr hdr; + __be16 bests[]; /* best free counts */ + /* unused entries are -1 */ +}; + +#define XFS_DIR3_FREE_CRC_OFF offsetof(struct xfs_dir3_free, hdr.hdr.crc) + +/* + * In core version of the free block header, abstracted away from on-disk format + * differences. Use this in the code, and convert to/from the disk version using + * xfs_dir3_free_hdr_from_disk/xfs_dir3_free_hdr_to_disk. + */ +struct xfs_dir3_icfree_hdr { + __uint32_t magic; + __uint32_t firstdb; + __uint32_t nvalid; + __uint32_t nused; + +}; + +void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to, + struct xfs_dir2_free *from); + +static inline int +xfs_dir3_free_hdr_size(struct xfs_mount *mp) +{ + if (xfs_sb_version_hascrc(&mp->m_sb)) + return sizeof(struct xfs_dir3_free_hdr); + return sizeof(struct xfs_dir2_free_hdr); +} + +static inline int +xfs_dir3_free_max_bests(struct xfs_mount *mp) +{ + return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) / + sizeof(xfs_dir2_data_off_t); +} + +static inline __be16 * +xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free) +{ + return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp)); +} + +/* + * Convert data space db to the corresponding free db. + */ +static inline xfs_dir2_db_t +xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db) +{ + return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp); +} + +/* + * Convert data space db to the corresponding index in a free db. + */ +static inline int +xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) +{ + return db % xfs_dir3_free_max_bests(mp); +} + +/* + * Single block format. + * + * The single block format looks like the following drawing on disk: + * + * +-------------------------------------------------+ + * | xfs_dir2_data_hdr_t | + * +-------------------------------------------------+ + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | + * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t : + * | ... | + * +-------------------------------------------------+ + * | unused space | + * +-------------------------------------------------+ + * | ... | + * | xfs_dir2_leaf_entry_t | + * | xfs_dir2_leaf_entry_t | + * +-------------------------------------------------+ + * | xfs_dir2_block_tail_t | + * +-------------------------------------------------+ + * + * As all the entries are variable size structures the accessors below should + * be used to iterate over them. + */ + +typedef struct xfs_dir2_block_tail { + __be32 count; /* count of leaf entries */ + __be32 stale; /* count of stale lf entries */ +} xfs_dir2_block_tail_t; + +/* + * Pointer to the leaf header embedded in a data block (1-block format) + */ +static inline struct xfs_dir2_block_tail * +xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr) +{ + return ((struct xfs_dir2_block_tail *) + ((char *)hdr + mp->m_dirblksize)) - 1; +} + +/* + * Pointer to the leaf entries embedded in a data block (1-block format) + */ +static inline struct xfs_dir2_leaf_entry * +xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp) +{ + return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count); +} + + +/* + * Attribute storage layout + * + * Attribute lists are structured around Btrees where all the data + * elements are in the leaf nodes. Attribute names are hashed into an int, + * then that int is used as the index into the Btree. Since the hashval + * of an attribute name may not be unique, we may have duplicate keys. The + * internal links in the Btree are logical block offsets into the file. + * + *======================================================================== + * Attribute structure when equal to XFS_LBSIZE(mp) bytes. + *======================================================================== + * + * Struct leaf_entry's are packed from the top. Name/values grow from the + * bottom but are not packed. The freemap contains run-length-encoded entries + * for the free bytes after the leaf_entry's, but only the N largest such, + * smaller runs are dropped. When the freemap doesn't show enough space + * for an allocation, we compact the name/value area and try again. If we + * still don't have enough space, then we have to split the block. The + * name/value structs (both local and remote versions) must be 32bit aligned. + * + * Since we have duplicate hash keys, for each key that matches, compare + * the actual name string. The root and intermediate node search always + * takes the first-in-the-block key match found, so we should only have + * to work "forw"ard. If none matches, continue with the "forw"ard leaf + * nodes until the hash key changes or the attribute name is found. + * + * We store the fact that an attribute is a ROOT/USER/SECURE attribute in + * the leaf_entry. The namespaces are independent only because we also look + * at the namespace bit when we are looking for a matching attribute name. + * + * We also store an "incomplete" bit in the leaf_entry. It shows that an + * attribute is in the middle of being created and should not be shown to + * the user if we crash during the time that the bit is set. We clear the + * bit when we have finished setting up the attribute. We do this because + * we cannot create some large attributes inside a single transaction, and we + * need some indication that we weren't finished if we crash in the middle. + */ +#define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */ + +typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */ + __be16 base; /* base of free region */ + __be16 size; /* length of free region */ +} xfs_attr_leaf_map_t; + +typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */ + xfs_da_blkinfo_t info; /* block type, links, etc. */ + __be16 count; /* count of active leaf_entry's */ + __be16 usedbytes; /* num bytes of names/values stored */ + __be16 firstused; /* first used byte in name area */ + __u8 holes; /* != 0 if blk needs compaction */ + __u8 pad1; + xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE]; + /* N largest free regions */ +} xfs_attr_leaf_hdr_t; + +typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */ + __be32 hashval; /* hash value of name */ + __be16 nameidx; /* index into buffer of name/value */ + __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */ + __u8 pad2; /* unused pad byte */ +} xfs_attr_leaf_entry_t; + +typedef struct xfs_attr_leaf_name_local { + __be16 valuelen; /* number of bytes in value */ + __u8 namelen; /* length of name bytes */ + __u8 nameval[1]; /* name/value bytes */ +} xfs_attr_leaf_name_local_t; + +typedef struct xfs_attr_leaf_name_remote { + __be32 valueblk; /* block number of value bytes */ + __be32 valuelen; /* number of bytes in value */ + __u8 namelen; /* length of name bytes */ + __u8 name[1]; /* name bytes */ +} xfs_attr_leaf_name_remote_t; + +typedef struct xfs_attr_leafblock { + xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */ + xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */ + xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */ + xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */ +} xfs_attr_leafblock_t; + +/* + * CRC enabled leaf structures. Called "version 3" structures to match the + * version number of the directory and dablk structures for this feature, and + * attr2 is already taken by the variable inode attribute fork size feature. + */ +struct xfs_attr3_leaf_hdr { + struct xfs_da3_blkinfo info; + __be16 count; + __be16 usedbytes; + __be16 firstused; + __u8 holes; + __u8 pad1; + struct xfs_attr_leaf_map freemap[XFS_ATTR_LEAF_MAPSIZE]; + __be32 pad2; /* 64 bit alignment */ +}; + +#define XFS_ATTR3_LEAF_CRC_OFF (offsetof(struct xfs_attr3_leaf_hdr, info.crc)) + +struct xfs_attr3_leafblock { + struct xfs_attr3_leaf_hdr hdr; + struct xfs_attr_leaf_entry entries[1]; + + /* + * The rest of the block contains the following structures after the + * leaf entries, growing from the bottom up. The variables are never + * referenced, the locations accessed purely from helper functions. + * + * struct xfs_attr_leaf_name_local + * struct xfs_attr_leaf_name_remote + */ +}; + +/* + * incore, neutral version of the attribute leaf header + */ +struct xfs_attr3_icleaf_hdr { + __uint32_t forw; + __uint32_t back; + __uint16_t magic; + __uint16_t count; + __uint16_t usedbytes; + __uint16_t firstused; + __u8 holes; + struct { + __uint16_t base; + __uint16_t size; + } freemap[XFS_ATTR_LEAF_MAPSIZE]; +}; + +/* + * Flags used in the leaf_entry[i].flags field. + * NOTE: the INCOMPLETE bit must not collide with the flags bits specified + * on the system call, they are "or"ed together for various operations. + */ +#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ +#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ +#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ +#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ +#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) +#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) +#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT) +#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) + +/* + * Conversion macros for converting namespace bits from argument flags + * to ondisk flags. + */ +#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE) +#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE) +#define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK) +#define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK) +#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\ + ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0)) +#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\ + ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0)) + +/* + * Alignment for namelist and valuelist entries (since they are mixed + * there can be only one alignment value) + */ +#define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t)) + +static inline int +xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp) +{ + if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) + return sizeof(struct xfs_attr3_leaf_hdr); + return sizeof(struct xfs_attr_leaf_hdr); +} + +static inline struct xfs_attr_leaf_entry * +xfs_attr3_leaf_entryp(xfs_attr_leafblock_t *leafp) +{ + if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) + return &((struct xfs_attr3_leafblock *)leafp)->entries[0]; + return &leafp->entries[0]; +} + +/* + * Cast typed pointers for "local" and "remote" name/value structs. + */ +static inline char * +xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx) +{ + struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp); + + return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)]; +} + +static inline xfs_attr_leaf_name_remote_t * +xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx) +{ + return (xfs_attr_leaf_name_remote_t *)xfs_attr3_leaf_name(leafp, idx); +} + +static inline xfs_attr_leaf_name_local_t * +xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx) +{ + return (xfs_attr_leaf_name_local_t *)xfs_attr3_leaf_name(leafp, idx); +} + +/* + * Calculate total bytes used (including trailing pad for alignment) for + * a "local" name/value structure, a "remote" name/value structure, and + * a pointer which might be either. + */ +static inline int xfs_attr_leaf_entsize_remote(int nlen) +{ + return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \ + XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1); +} + +static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen) +{ + return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) + + XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1); +} + +static inline int xfs_attr_leaf_entsize_local_max(int bsize) +{ + return (((bsize) >> 1) + ((bsize) >> 2)); +} + + + +/* + * Remote attribute block format definition + * + * There is one of these headers per filesystem block in a remote attribute. + * This is done to ensure there is a 1:1 mapping between the attribute value + * length and the number of blocks needed to store the attribute. This makes the + * verification of a buffer a little more complex, but greatly simplifies the + * allocation, reading and writing of these attributes as we don't have to guess + * the number of blocks needed to store the attribute data. + */ +#define XFS_ATTR3_RMT_MAGIC 0x5841524d /* XARM */ + +struct xfs_attr3_rmt_hdr { + __be32 rm_magic; + __be32 rm_offset; + __be32 rm_bytes; + __be32 rm_crc; + uuid_t rm_uuid; + __be64 rm_owner; + __be64 rm_blkno; + __be64 rm_lsn; +}; + +#define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc) + +#define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \ + ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ + sizeof(struct xfs_attr3_rmt_hdr) : 0)) + +#endif /* __XFS_DA_FORMAT_H__ */ diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index edf203ab50af..f46777fa3077 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -24,6 +24,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" @@ -31,7 +32,6 @@ #include "xfs_inode.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 12dad188939d..5f172730bfa3 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -24,6 +24,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_dinode.h" @@ -31,7 +32,6 @@ #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_buf_item.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 47e1326c169a..8cf8034ebab1 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -24,11 +24,11 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h deleted file mode 100644 index 9cf67381adf6..000000000000 --- a/fs/xfs/xfs_dir2_format.h +++ /dev/null @@ -1,964 +0,0 @@ -/* - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. - * Copyright (c) 2013 Red Hat, 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_DIR2_FORMAT_H__ -#define __XFS_DIR2_FORMAT_H__ - -/* - * Directory version 2. - * - * There are 4 possible formats: - * - shortform - embedded into the inode - * - single block - data with embedded leaf at the end - * - multiple data blocks, single leaf+freeindex block - * - data blocks, node and leaf blocks (btree), freeindex blocks - * - * Note: many node blocks structures and constants are shared with the attr - * code and defined in xfs_da_btree.h. - */ - -#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: single block dirs */ -#define XFS_DIR2_DATA_MAGIC 0x58443244 /* XD2D: multiblock dirs */ -#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */ - -/* - * Directory Version 3 With CRCs. - * - * The tree formats are the same as for version 2 directories. The difference - * is in the block header and dirent formats. In many cases the v3 structures - * use v2 definitions as they are no different and this makes code sharing much - * easier. - * - * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the - * format is v2 then they switch to the existing v2 code, or the format is v3 - * they implement the v3 functionality. This means the existing dir2 is a mix of - * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called - * where there is a difference in the formats, otherwise the code is unchanged. - * - * Where it is possible, the code decides what to do based on the magic numbers - * in the blocks rather than feature bits in the superblock. This means the code - * is as independent of the external XFS code as possible as doesn't require - * passing struct xfs_mount pointers into places where it isn't really - * necessary. - * - * Version 3 includes: - * - * - a larger block header for CRC and identification purposes and so the - * offsets of all the structures inside the blocks are different. - * - * - new magic numbers to be able to detect the v2/v3 types on the fly. - */ - -#define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */ -#define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */ -#define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */ - -/* - * Dirents in version 3 directories have a file type field. Additions to this - * list are an on-disk format change, requiring feature bits. Valid values - * are as follows: - */ -#define XFS_DIR3_FT_UNKNOWN 0 -#define XFS_DIR3_FT_REG_FILE 1 -#define XFS_DIR3_FT_DIR 2 -#define XFS_DIR3_FT_CHRDEV 3 -#define XFS_DIR3_FT_BLKDEV 4 -#define XFS_DIR3_FT_FIFO 5 -#define XFS_DIR3_FT_SOCK 6 -#define XFS_DIR3_FT_SYMLINK 7 -#define XFS_DIR3_FT_WHT 8 - -#define XFS_DIR3_FT_MAX 9 - -/* - * Byte offset in data block and shortform entry. - */ -typedef __uint16_t xfs_dir2_data_off_t; -#define NULLDATAOFF 0xffffU -typedef uint xfs_dir2_data_aoff_t; /* argument form */ - -/* - * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. - * Only need 16 bits, this is the byte offset into the single block form. - */ -typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t; - -/* - * Offset in data space of a data entry. - */ -typedef __uint32_t xfs_dir2_dataptr_t; -#define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff) -#define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0) - -/* - * Byte offset in a directory. - */ -typedef xfs_off_t xfs_dir2_off_t; - -/* - * Directory block number (logical dirblk in file) - */ -typedef __uint32_t xfs_dir2_db_t; - -/* - * Inode number stored as 8 8-bit values. - */ -typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t; - -/* - * Inode number stored as 4 8-bit values. - * Works a lot of the time, when all the inode numbers in a directory - * fit in 32 bits. - */ -typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t; - -typedef union { - xfs_dir2_ino8_t i8; - xfs_dir2_ino4_t i4; -} xfs_dir2_inou_t; -#define XFS_DIR2_MAX_SHORT_INUM ((xfs_ino_t)0xffffffffULL) - -/* - * Directory layout when stored internal to an inode. - * - * Small directories are packed as tightly as possible so as to fit into the - * literal area of the inode. These "shortform" directories consist of a - * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry - * structures. Due the different inode number storage size and the variable - * length name field in the xfs_dir2_sf_entry all these structure are - * variable length, and the accessors in this file should be used to iterate - * over them. - */ -typedef struct xfs_dir2_sf_hdr { - __uint8_t count; /* count of entries */ - __uint8_t i8count; /* count of 8-byte inode #s */ - xfs_dir2_inou_t parent; /* parent dir inode number */ -} __arch_pack xfs_dir2_sf_hdr_t; - -typedef struct xfs_dir2_sf_entry { - __u8 namelen; /* actual name length */ - xfs_dir2_sf_off_t offset; /* saved offset */ - __u8 name[]; /* name, variable size */ - /* - * A single byte containing the file type field follows the inode - * number for version 3 directory entries. - * - * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a - * variable offset after the name. - */ -} __arch_pack xfs_dir2_sf_entry_t; - -static inline int xfs_dir2_sf_hdr_size(int i8count) -{ - return sizeof(struct xfs_dir2_sf_hdr) - - (i8count == 0) * - (sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t)); -} - -static inline xfs_dir2_data_aoff_t -xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep) -{ - return get_unaligned_be16(&sfep->offset.i); -} - -static inline void -xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off) -{ - put_unaligned_be16(off, &sfep->offset.i); -} - -static inline struct xfs_dir2_sf_entry * -xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) -{ - return (struct xfs_dir2_sf_entry *) - ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count)); -} - -static inline int -xfs_dir3_sf_entsize( - struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, - int len) -{ - int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */ - - count += len; /* name */ - count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) : - sizeof(xfs_dir2_ino4_t); /* ino # */ - if (xfs_sb_version_hasftype(&mp->m_sb)) - count += sizeof(__uint8_t); /* file type */ - return count; -} - -static inline struct xfs_dir2_sf_entry * -xfs_dir3_sf_nextentry( - struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, - struct xfs_dir2_sf_entry *sfep) -{ - return (struct xfs_dir2_sf_entry *) - ((char *)sfep + xfs_dir3_sf_entsize(mp, hdr, sfep->namelen)); -} - -/* - * in dir3 shortform directories, the file type field is stored at a variable - * offset after the inode number. Because it's only a single byte, endian - * conversion is not necessary. - */ -static inline __uint8_t * -xfs_dir3_sfe_ftypep( - struct xfs_dir2_sf_hdr *hdr, - struct xfs_dir2_sf_entry *sfep) -{ - return (__uint8_t *)&sfep->name[sfep->namelen]; -} - -static inline __uint8_t -xfs_dir3_sfe_get_ftype( - struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, - struct xfs_dir2_sf_entry *sfep) -{ - __uint8_t *ftp; - - if (!xfs_sb_version_hasftype(&mp->m_sb)) - return XFS_DIR3_FT_UNKNOWN; - - ftp = xfs_dir3_sfe_ftypep(hdr, sfep); - if (*ftp >= XFS_DIR3_FT_MAX) - return XFS_DIR3_FT_UNKNOWN; - return *ftp; -} - -static inline void -xfs_dir3_sfe_put_ftype( - struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, - struct xfs_dir2_sf_entry *sfep, - __uint8_t ftype) -{ - __uint8_t *ftp; - - ASSERT(ftype < XFS_DIR3_FT_MAX); - - if (!xfs_sb_version_hasftype(&mp->m_sb)) - return; - ftp = xfs_dir3_sfe_ftypep(hdr, sfep); - *ftp = ftype; -} - -/* - * Data block structures. - * - * A pure data block looks like the following drawing on disk: - * - * +-------------------------------------------------+ - * | xfs_dir2_data_hdr_t | - * +-------------------------------------------------+ - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | - * | ... | - * +-------------------------------------------------+ - * | unused space | - * +-------------------------------------------------+ - * - * As all the entries are variable size structures the accessors below should - * be used to iterate over them. - * - * In addition to the pure data blocks for the data and node formats, - * most structures are also used for the combined data/freespace "block" - * format below. - */ - -#define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */ -#define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG) -#define XFS_DIR2_DATA_FREE_TAG 0xffff -#define XFS_DIR2_DATA_FD_COUNT 3 - -/* - * Directory address space divided into sections, - * spaces separated by 32GB. - */ -#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) -#define XFS_DIR2_DATA_SPACE 0 -#define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE) -#define XFS_DIR2_DATA_FIRSTDB(mp) \ - xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET) - -/* - * Describe a free area in the data block. - * - * The freespace will be formatted as a xfs_dir2_data_unused_t. - */ -typedef struct xfs_dir2_data_free { - __be16 offset; /* start of freespace */ - __be16 length; /* length of freespace */ -} xfs_dir2_data_free_t; - -/* - * Header for the data blocks. - * - * The code knows that XFS_DIR2_DATA_FD_COUNT is 3. - */ -typedef struct xfs_dir2_data_hdr { - __be32 magic; /* XFS_DIR2_DATA_MAGIC or */ - /* XFS_DIR2_BLOCK_MAGIC */ - xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT]; -} xfs_dir2_data_hdr_t; - -/* - * define a structure for all the verification fields we are adding to the - * directory block structures. This will be used in several structures. - * The magic number must be the first entry to align with all the dir2 - * structures so we determine how to decode them just by the magic number. - */ -struct xfs_dir3_blk_hdr { - __be32 magic; /* magic number */ - __be32 crc; /* CRC of block */ - __be64 blkno; /* first block of the buffer */ - __be64 lsn; /* sequence number of last write */ - uuid_t uuid; /* filesystem we belong to */ - __be64 owner; /* inode that owns the block */ -}; - -struct xfs_dir3_data_hdr { - struct xfs_dir3_blk_hdr hdr; - xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT]; - __be32 pad; /* 64 bit alignment */ -}; - -#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc) - -static inline struct xfs_dir2_data_free * -xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) -{ - if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || - hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { - struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr; - return hdr3->best_free; - } - return hdr->bestfree; -} - -/* - * Active entry in a data block. - * - * Aligned to 8 bytes. After the variable length name field there is a - * 2 byte tag field, which can be accessed using xfs_dir3_data_entry_tag_p. - * - * For dir3 structures, there is file type field between the name and the tag. - * This can only be manipulated by helper functions. It is packed hard against - * the end of the name so any padding for rounding is between the file type and - * the tag. - */ -typedef struct xfs_dir2_data_entry { - __be64 inumber; /* inode number */ - __u8 namelen; /* name length */ - __u8 name[]; /* name bytes, no null */ - /* __u8 filetype; */ /* type of inode we point to */ - /* __be16 tag; */ /* starting offset of us */ -} xfs_dir2_data_entry_t; - -/* - * Unused entry in a data block. - * - * Aligned to 8 bytes. Tag appears as the last 2 bytes and must be accessed - * using xfs_dir2_data_unused_tag_p. - */ -typedef struct xfs_dir2_data_unused { - __be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */ - __be16 length; /* total free length */ - /* variable offset */ - __be16 tag; /* starting offset of us */ -} xfs_dir2_data_unused_t; - -/* - * Size of a data entry. - */ -static inline int -__xfs_dir3_data_entsize( - bool ftype, - int n) -{ - int size = offsetof(struct xfs_dir2_data_entry, name[0]); - - size += n; - size += sizeof(xfs_dir2_data_off_t); - if (ftype) - size += sizeof(__uint8_t); - return roundup(size, XFS_DIR2_DATA_ALIGN); -} -static inline int -xfs_dir3_data_entsize( - struct xfs_mount *mp, - int n) -{ - bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false; - return __xfs_dir3_data_entsize(ftype, n); -} - -static inline __uint8_t -xfs_dir3_dirent_get_ftype( - struct xfs_mount *mp, - struct xfs_dir2_data_entry *dep) -{ - if (xfs_sb_version_hasftype(&mp->m_sb)) { - __uint8_t type = dep->name[dep->namelen]; - - ASSERT(type < XFS_DIR3_FT_MAX); - if (type < XFS_DIR3_FT_MAX) - return type; - - } - return XFS_DIR3_FT_UNKNOWN; -} - -static inline void -xfs_dir3_dirent_put_ftype( - struct xfs_mount *mp, - struct xfs_dir2_data_entry *dep, - __uint8_t type) -{ - ASSERT(type < XFS_DIR3_FT_MAX); - ASSERT(dep->namelen != 0); - - if (xfs_sb_version_hasftype(&mp->m_sb)) - dep->name[dep->namelen] = type; -} - -/* - * Pointer to an entry's tag word. - */ -static inline __be16 * -xfs_dir3_data_entry_tag_p( - struct xfs_mount *mp, - struct xfs_dir2_data_entry *dep) -{ - return (__be16 *)((char *)dep + - xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16)); -} - -/* - * Pointer to a freespace's tag word. - */ -static inline __be16 * -xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) -{ - return (__be16 *)((char *)dup + - be16_to_cpu(dup->length) - sizeof(__be16)); -} - -static inline size_t -xfs_dir3_data_hdr_size(bool dir3) -{ - if (dir3) - return sizeof(struct xfs_dir3_data_hdr); - return sizeof(struct xfs_dir2_data_hdr); -} - -static inline size_t -xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr) -{ - bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || - hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); - return xfs_dir3_data_hdr_size(dir3); -} - -static inline struct xfs_dir2_data_entry * -xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) -{ - return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_entry_offset(hdr)); -} - -static inline struct xfs_dir2_data_unused * -xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) -{ - return (struct xfs_dir2_data_unused *) - ((char *)hdr + xfs_dir3_data_entry_offset(hdr)); -} - -/* - * Offsets of . and .. in data space (always block 0) - * - * XXX: there is scope for significant optimisation of the logic here. Right - * now we are checking for "dir3 format" over and over again. Ideally we should - * only do it once for each operation. - */ -static inline xfs_dir2_data_aoff_t -xfs_dir3_data_dot_offset(struct xfs_mount *mp) -{ - return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)); -} - -static inline xfs_dir2_data_aoff_t -xfs_dir3_data_dotdot_offset(struct xfs_mount *mp) -{ - return xfs_dir3_data_dot_offset(mp) + - xfs_dir3_data_entsize(mp, 1); -} - -static inline xfs_dir2_data_aoff_t -xfs_dir3_data_first_offset(struct xfs_mount *mp) -{ - return xfs_dir3_data_dotdot_offset(mp) + - xfs_dir3_data_entsize(mp, 2); -} - -/* - * location of . and .. in data space (always block 0) - */ -static inline struct xfs_dir2_data_entry * -xfs_dir3_data_dot_entry_p( - struct xfs_mount *mp, - struct xfs_dir2_data_hdr *hdr) -{ - return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_dot_offset(mp)); -} - -static inline struct xfs_dir2_data_entry * -xfs_dir3_data_dotdot_entry_p( - struct xfs_mount *mp, - struct xfs_dir2_data_hdr *hdr) -{ - return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_dotdot_offset(mp)); -} - -static inline struct xfs_dir2_data_entry * -xfs_dir3_data_first_entry_p( - struct xfs_mount *mp, - struct xfs_dir2_data_hdr *hdr) -{ - return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_first_offset(mp)); -} - -/* - * Leaf block structures. - * - * A pure leaf block looks like the following drawing on disk: - * - * +---------------------------+ - * | xfs_dir2_leaf_hdr_t | - * +---------------------------+ - * | xfs_dir2_leaf_entry_t | - * | xfs_dir2_leaf_entry_t | - * | xfs_dir2_leaf_entry_t | - * | xfs_dir2_leaf_entry_t | - * | ... | - * +---------------------------+ - * | xfs_dir2_data_off_t | - * | xfs_dir2_data_off_t | - * | xfs_dir2_data_off_t | - * | ... | - * +---------------------------+ - * | xfs_dir2_leaf_tail_t | - * +---------------------------+ - * - * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block - * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present - * for directories with separate leaf nodes and free space blocks - * (magic = XFS_DIR2_LEAFN_MAGIC). - * - * As all the entries are variable size structures the accessors below should - * be used to iterate over them. - */ - -/* - * Offset of the leaf/node space. First block in this space - * is the btree root. - */ -#define XFS_DIR2_LEAF_SPACE 1 -#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) -#define XFS_DIR2_LEAF_FIRSTDB(mp) \ - xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET) - -/* - * Leaf block header. - */ -typedef struct xfs_dir2_leaf_hdr { - xfs_da_blkinfo_t info; /* header for da routines */ - __be16 count; /* count of entries */ - __be16 stale; /* count of stale entries */ -} xfs_dir2_leaf_hdr_t; - -struct xfs_dir3_leaf_hdr { - struct xfs_da3_blkinfo info; /* header for da routines */ - __be16 count; /* count of entries */ - __be16 stale; /* count of stale entries */ - __be32 pad; /* 64 bit alignment */ -}; - -struct xfs_dir3_icleaf_hdr { - __uint32_t forw; - __uint32_t back; - __uint16_t magic; - __uint16_t count; - __uint16_t stale; -}; - -/* - * Leaf block entry. - */ -typedef struct xfs_dir2_leaf_entry { - __be32 hashval; /* hash value of name */ - __be32 address; /* address of data entry */ -} xfs_dir2_leaf_entry_t; - -/* - * Leaf block tail. - */ -typedef struct xfs_dir2_leaf_tail { - __be32 bestcount; -} xfs_dir2_leaf_tail_t; - -/* - * Leaf block. - */ -typedef struct xfs_dir2_leaf { - xfs_dir2_leaf_hdr_t hdr; /* leaf header */ - xfs_dir2_leaf_entry_t __ents[]; /* entries */ -} xfs_dir2_leaf_t; - -struct xfs_dir3_leaf { - struct xfs_dir3_leaf_hdr hdr; /* leaf header */ - struct xfs_dir2_leaf_entry __ents[]; /* entries */ -}; - -#define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc) - -extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to, - struct xfs_dir2_leaf *from); - -static inline int -xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp) -{ - if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || - lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) - return sizeof(struct xfs_dir3_leaf_hdr); - return sizeof(struct xfs_dir2_leaf_hdr); -} - -static inline int -xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) -{ - return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) / - (uint)sizeof(struct xfs_dir2_leaf_entry); -} - -/* - * Get address of the bestcount field in the single-leaf block. - */ -static inline struct xfs_dir2_leaf_entry * -xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp) -{ - if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || - lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { - struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp; - return lp3->__ents; - } - return lp->__ents; -} - -/* - * Get address of the bestcount field in the single-leaf block. - */ -static inline struct xfs_dir2_leaf_tail * -xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) -{ - return (struct xfs_dir2_leaf_tail *) - ((char *)lp + mp->m_dirblksize - - sizeof(struct xfs_dir2_leaf_tail)); -} - -/* - * Get address of the bests array in the single-leaf block. - */ -static inline __be16 * -xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp) -{ - return (__be16 *)ltp - be32_to_cpu(ltp->bestcount); -} - -/* - * DB blocks here are logical directory block numbers, not filesystem blocks. - */ - -/* - * Convert dataptr to byte in file space - */ -static inline xfs_dir2_off_t -xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) -{ - return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG; -} - -/* - * Convert byte in file space to dataptr. It had better be aligned. - */ -static inline xfs_dir2_dataptr_t -xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by) -{ - return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG); -} - -/* - * Convert byte in space to (DB) block - */ -static inline xfs_dir2_db_t -xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by) -{ - return (xfs_dir2_db_t) - (by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)); -} - -/* - * Convert dataptr to a block number - */ -static inline xfs_dir2_db_t -xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) -{ - return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp)); -} - -/* - * Convert byte in space to offset in a block - */ -static inline xfs_dir2_data_aoff_t -xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by) -{ - return (xfs_dir2_data_aoff_t)(by & - ((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1)); -} - -/* - * Convert dataptr to a byte offset in a block - */ -static inline xfs_dir2_data_aoff_t -xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) -{ - return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp)); -} - -/* - * Convert block and offset to byte in space - */ -static inline xfs_dir2_off_t -xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db, - xfs_dir2_data_aoff_t o) -{ - return ((xfs_dir2_off_t)db << - (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o; -} - -/* - * Convert block (DB) to block (dablk) - */ -static inline xfs_dablk_t -xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db) -{ - return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog); -} - -/* - * Convert byte in space to (DA) block - */ -static inline xfs_dablk_t -xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by) -{ - return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by)); -} - -/* - * Convert block and offset to dataptr - */ -static inline xfs_dir2_dataptr_t -xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db, - xfs_dir2_data_aoff_t o) -{ - return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o)); -} - -/* - * Convert block (dablk) to block (DB) - */ -static inline xfs_dir2_db_t -xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da) -{ - return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog); -} - -/* - * Convert block (dablk) to byte offset in space - */ -static inline xfs_dir2_off_t -xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da) -{ - return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0); -} - -/* - * Free space block defintions for the node format. - */ - -/* - * Offset of the freespace index. - */ -#define XFS_DIR2_FREE_SPACE 2 -#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) -#define XFS_DIR2_FREE_FIRSTDB(mp) \ - xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET) - -typedef struct xfs_dir2_free_hdr { - __be32 magic; /* XFS_DIR2_FREE_MAGIC */ - __be32 firstdb; /* db of first entry */ - __be32 nvalid; /* count of valid entries */ - __be32 nused; /* count of used entries */ -} xfs_dir2_free_hdr_t; - -typedef struct xfs_dir2_free { - xfs_dir2_free_hdr_t hdr; /* block header */ - __be16 bests[]; /* best free counts */ - /* unused entries are -1 */ -} xfs_dir2_free_t; - -struct xfs_dir3_free_hdr { - struct xfs_dir3_blk_hdr hdr; - __be32 firstdb; /* db of first entry */ - __be32 nvalid; /* count of valid entries */ - __be32 nused; /* count of used entries */ - __be32 pad; /* 64 bit alignment */ -}; - -struct xfs_dir3_free { - struct xfs_dir3_free_hdr hdr; - __be16 bests[]; /* best free counts */ - /* unused entries are -1 */ -}; - -#define XFS_DIR3_FREE_CRC_OFF offsetof(struct xfs_dir3_free, hdr.hdr.crc) - -/* - * In core version of the free block header, abstracted away from on-disk format - * differences. Use this in the code, and convert to/from the disk version using - * xfs_dir3_free_hdr_from_disk/xfs_dir3_free_hdr_to_disk. - */ -struct xfs_dir3_icfree_hdr { - __uint32_t magic; - __uint32_t firstdb; - __uint32_t nvalid; - __uint32_t nused; - -}; - -void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to, - struct xfs_dir2_free *from); - -static inline int -xfs_dir3_free_hdr_size(struct xfs_mount *mp) -{ - if (xfs_sb_version_hascrc(&mp->m_sb)) - return sizeof(struct xfs_dir3_free_hdr); - return sizeof(struct xfs_dir2_free_hdr); -} - -static inline int -xfs_dir3_free_max_bests(struct xfs_mount *mp) -{ - return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) / - sizeof(xfs_dir2_data_off_t); -} - -static inline __be16 * -xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free) -{ - return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp)); -} - -/* - * Convert data space db to the corresponding free db. - */ -static inline xfs_dir2_db_t -xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db) -{ - return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp); -} - -/* - * Convert data space db to the corresponding index in a free db. - */ -static inline int -xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) -{ - return db % xfs_dir3_free_max_bests(mp); -} - -/* - * Single block format. - * - * The single block format looks like the following drawing on disk: - * - * +-------------------------------------------------+ - * | xfs_dir2_data_hdr_t | - * +-------------------------------------------------+ - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | - * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t : - * | ... | - * +-------------------------------------------------+ - * | unused space | - * +-------------------------------------------------+ - * | ... | - * | xfs_dir2_leaf_entry_t | - * | xfs_dir2_leaf_entry_t | - * +-------------------------------------------------+ - * | xfs_dir2_block_tail_t | - * +-------------------------------------------------+ - * - * As all the entries are variable size structures the accessors below should - * be used to iterate over them. - */ - -typedef struct xfs_dir2_block_tail { - __be32 count; /* count of leaf entries */ - __be32 stale; /* count of stale lf entries */ -} xfs_dir2_block_tail_t; - -/* - * Pointer to the leaf header embedded in a data block (1-block format) - */ -static inline struct xfs_dir2_block_tail * -xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr) -{ - return ((struct xfs_dir2_block_tail *) - ((char *)hdr + mp->m_dirblksize)) - 1; -} - -/* - * Pointer to the leaf entries embedded in a data block (1-block format) - */ -static inline struct xfs_dir2_leaf_entry * -xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp) -{ - return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count); -} - -#endif /* __XFS_DIR2_FORMAT_H__ */ diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 1021c8356d08..d5937dab8f56 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -25,12 +25,12 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_bmap.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 34df052683eb..85ff354db4ae 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -24,12 +24,12 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_bmap.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 8f84153e98a8..6b1ffb37654a 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -25,11 +25,11 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 3ef6d402084c..8d925963a1f2 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -23,13 +23,13 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_inode_item.h" #include "xfs_error.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_trace.h" diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 066df425c14f..96be1d63da9b 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c @@ -22,8 +22,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_da_btree.h" -#include "xfs_dir2_format.h" +#include "xfs_da_format.h" #include "xfs_dir2.h" #include "xfs_export.h" #include "xfs_bmap_btree.h" diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 57d95b2f8692..cc22aa1b7b3b 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -23,6 +23,8 @@ #include "xfs_ag.h" #include "xfs_trans.h" #include "xfs_mount.h" +#include "xfs_da_format.h" +#include "xfs_da_btree.h" #include "xfs_bmap_btree.h" #include "xfs_alloc.h" #include "xfs_dinode.h" @@ -31,8 +33,6 @@ #include "xfs_bmap.h" #include "xfs_bmap_util.h" #include "xfs_error.h" -#include "xfs_da_btree.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_ioctl.h" diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 1aaef689794d..23d78885c743 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -29,8 +29,8 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 24fe333b8c41..d046dc8c1925 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -27,6 +27,7 @@ #include "xfs_alloc.h" #include "xfs_quota.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" @@ -42,7 +43,6 @@ #include "xfs_icache.h" #include "xfs_symlink.h" #include "xfs_da_btree.h" -#include "xfs_dir2_format.h" #include "xfs_dir2_priv.h" #include diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index cbefc1235083..4d4f4a0bb5e4 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -26,6 +26,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_error.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" @@ -50,7 +51,6 @@ /* Need all the magic numbers and buffer ops structures from these headers */ #include "xfs_symlink.h" #include "xfs_da_btree.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_attr_leaf.h" #include "xfs_attr_remote.h" diff --git a/fs/xfs/xfs_log_rlimit.c b/fs/xfs/xfs_log_rlimit.c index 0961310abe46..e598bb547dee 100644 --- a/fs/xfs/xfs_log_rlimit.c +++ b/fs/xfs/xfs_log_rlimit.c @@ -23,6 +23,7 @@ #include "xfs_ag.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_trans_space.h" #include "xfs_bmap_btree.h" #include "xfs_inode.h" diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 9515f96b4ab7..170e7294b7b0 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -27,8 +27,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_da_btree.h" -#include "xfs_dir2_format.h" +#include "xfs_da_format.h" #include "xfs_dir2.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index b4762279bb78..73b24e15cef7 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -26,8 +26,8 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 4886b35b1ef1..a28eca47aa4c 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -27,6 +27,7 @@ #include "xfs_alloc.h" #include "xfs_quota.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" @@ -45,7 +46,6 @@ #include "xfs_trans_priv.h" #include "xfs_filestream.h" #include "xfs_da_btree.h" -#include "xfs_dir2_format.h" #include "xfs_dir2.h" #include "xfs_extfree_item.h" #include "xfs_mru_cache.h" diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index cba781edb192..db32c504372c 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -26,8 +26,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_da_btree.h" -#include "xfs_dir2_format.h" +#include "xfs_da_format.h" #include "xfs_dir2.h" #include "xfs_bmap_btree.h" #include "xfs_ialloc_btree.h" diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c index 29705391c896..6ca992020326 100644 --- a/fs/xfs/xfs_trace.c +++ b/fs/xfs/xfs_trace.c @@ -23,13 +23,14 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" +#include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_btree.h" -#include "xfs_mount.h" #include "xfs_da_btree.h" #include "xfs_ialloc.h" #include "xfs_itable.h" diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 3693ce279143..06000a9647d5 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -26,7 +26,7 @@ #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_error.h" -#include "xfs_da_btree.h" +#include "xfs_da_format.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c index b5d952dbe6a4..cc8361255c8e 100644 --- a/fs/xfs/xfs_trans_resv.c +++ b/fs/xfs/xfs_trans_resv.c @@ -26,6 +26,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_error.h" #include "xfs_da_btree.h" #include "xfs_bmap_btree.h" diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index e01f35ea76ba..08047502683d 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -18,7 +18,12 @@ #include "xfs.h" #include "xfs_log_format.h" -#include "xfs_da_btree.h" +#include "xfs_log.h" +#include "xfs_trans.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "xfs_mount.h" +#include "xfs_da_format.h" #include "xfs_bmap_btree.h" #include "xfs_inode.h" #include "xfs_attr.h" -- cgit v1.2.3 From 9aede1d81b12a95771db0e2f9196dd37e10aaf20 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 15 Oct 2013 09:17:52 +1100 Subject: xfs: split dquot buffer operations out Parts of userspace want to be able to read and modify dquot buffers (e.g. xfs_db) so we need to split out the reading and writing of these buffers so it is easy to shared code with libxfs in userspace. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/Makefile | 1 + fs/xfs/xfs_dquot.c | 117 +------------------ fs/xfs/xfs_dquot_buf.c | 288 +++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_log_recover.c | 133 +--------------------- fs/xfs/xfs_qm.c | 22 +--- fs/xfs/xfs_qm.h | 2 - fs/xfs/xfs_quota.h | 2 - fs/xfs/xfs_quota_defs.h | 4 + 8 files changed, 303 insertions(+), 266 deletions(-) create mode 100644 fs/xfs/xfs_dquot_buf.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 0719e4db93f2..08f11bbf56ae 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -72,6 +72,7 @@ xfs-y += xfs_alloc.o \ xfs_dir2_leaf.o \ xfs_dir2_node.o \ xfs_dir2_sf.o \ + xfs_dquot_buf.o \ xfs_ialloc.o \ xfs_ialloc_btree.o \ xfs_icreate_item.o \ diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 8b1d2c0a9054..f85a893c2398 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -293,118 +293,6 @@ xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp) dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5; } -STATIC bool -xfs_dquot_buf_verify_crc( - struct xfs_mount *mp, - struct xfs_buf *bp) -{ - struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; - int ndquots; - int i; - - if (!xfs_sb_version_hascrc(&mp->m_sb)) - return true; - - /* - * if we are in log recovery, the quota subsystem has not been - * initialised so we have no quotainfo structure. In that case, we need - * to manually calculate the number of dquots in the buffer. - */ - if (mp->m_quotainfo) - ndquots = mp->m_quotainfo->qi_dqperchunk; - else - ndquots = xfs_qm_calc_dquots_per_chunk(mp, - XFS_BB_TO_FSB(mp, bp->b_length)); - - for (i = 0; i < ndquots; i++, d++) { - if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk), - XFS_DQUOT_CRC_OFF)) - return false; - if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid)) - return false; - } - return true; -} - -STATIC bool -xfs_dquot_buf_verify( - struct xfs_mount *mp, - struct xfs_buf *bp) -{ - struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; - xfs_dqid_t id = 0; - int ndquots; - int i; - - /* - * if we are in log recovery, the quota subsystem has not been - * initialised so we have no quotainfo structure. In that case, we need - * to manually calculate the number of dquots in the buffer. - */ - if (mp->m_quotainfo) - ndquots = mp->m_quotainfo->qi_dqperchunk; - else - ndquots = xfs_qm_calc_dquots_per_chunk(mp, bp->b_length); - - /* - * On the first read of the buffer, verify that each dquot is valid. - * We don't know what the id of the dquot is supposed to be, just that - * they should be increasing monotonically within the buffer. If the - * first id is corrupt, then it will fail on the second dquot in the - * buffer so corruptions could point to the wrong dquot in this case. - */ - for (i = 0; i < ndquots; i++) { - struct xfs_disk_dquot *ddq; - int error; - - ddq = &d[i].dd_diskdq; - - if (i == 0) - id = be32_to_cpu(ddq->d_id); - - error = xfs_qm_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN, - "xfs_dquot_buf_verify"); - if (error) - return false; - } - return true; -} - -static void -xfs_dquot_buf_read_verify( - struct xfs_buf *bp) -{ - struct xfs_mount *mp = bp->b_target->bt_mount; - - if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) { - XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); - xfs_buf_ioerror(bp, EFSCORRUPTED); - } -} - -/* - * we don't calculate the CRC here as that is done when the dquot is flushed to - * the buffer after the update is done. This ensures that the dquot in the - * buffer always has an up-to-date CRC value. - */ -void -xfs_dquot_buf_write_verify( - struct xfs_buf *bp) -{ - struct xfs_mount *mp = bp->b_target->bt_mount; - - if (!xfs_dquot_buf_verify(mp, bp)) { - XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); - xfs_buf_ioerror(bp, EFSCORRUPTED); - return; - } -} - -const struct xfs_buf_ops xfs_dquot_buf_ops = { - .verify_read = xfs_dquot_buf_read_verify, - .verify_write = xfs_dquot_buf_write_verify, -}; - /* * Allocate a block and fill it with dquots. * This is called when the bmapi finds a hole. @@ -515,6 +403,7 @@ xfs_qm_dqalloc( return (error); } + STATIC int xfs_qm_dqrepair( struct xfs_mount *mp, @@ -548,7 +437,7 @@ xfs_qm_dqrepair( /* Do the actual repair of dquots in this buffer */ for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++) { ddq = &d[i].dd_diskdq; - error = xfs_qm_dqcheck(mp, ddq, firstid + i, + error = xfs_dqcheck(mp, ddq, firstid + i, dqp->dq_flags & XFS_DQ_ALLTYPES, XFS_QMOPT_DQREPAIR, "xfs_qm_dqrepair"); if (error) { @@ -1134,7 +1023,7 @@ xfs_qm_dqflush( /* * A simple sanity check in case we got a corrupted dquot.. */ - error = xfs_qm_dqcheck(mp, &dqp->q_core, be32_to_cpu(ddqp->d_id), 0, + error = xfs_dqcheck(mp, &dqp->q_core, be32_to_cpu(ddqp->d_id), 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)"); if (error) { xfs_buf_relse(bp); diff --git a/fs/xfs/xfs_dquot_buf.c b/fs/xfs/xfs_dquot_buf.c new file mode 100644 index 000000000000..ad2c18fbdb05 --- /dev/null +++ b/fs/xfs/xfs_dquot_buf.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2000-2006 Silicon Graphics, Inc. + * Copyright (c) 2013 Red Hat, 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 + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_format.h" +#include "xfs_bit.h" +#include "xfs_log.h" +#include "xfs_trans.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "xfs_mount.h" +#include "xfs_bmap_btree.h" +#include "xfs_inode.h" +#include "xfs_quota.h" +#include "xfs_qm.h" +#include "xfs_error.h" +#include "xfs_cksum.h" +#include "xfs_trace.h" + +int +xfs_calc_dquots_per_chunk( + struct xfs_mount *mp, + unsigned int nbblks) /* basic block units */ +{ + unsigned int ndquots; + + ASSERT(nbblks > 0); + ndquots = BBTOB(nbblks); + do_div(ndquots, sizeof(xfs_dqblk_t)); + + return ndquots; +} + +/* + * Do some primitive error checking on ondisk dquot data structures. + */ +int +xfs_dqcheck( + struct xfs_mount *mp, + xfs_disk_dquot_t *ddq, + xfs_dqid_t id, + uint type, /* used only when IO_dorepair is true */ + uint flags, + char *str) +{ + xfs_dqblk_t *d = (xfs_dqblk_t *)ddq; + int errs = 0; + + /* + * We can encounter an uninitialized dquot buffer for 2 reasons: + * 1. If we crash while deleting the quotainode(s), and those blks got + * used for user data. This is because we take the path of regular + * file deletion; however, the size field of quotainodes is never + * updated, so all the tricks that we play in itruncate_finish + * don't quite matter. + * + * 2. We don't play the quota buffers when there's a quotaoff logitem. + * But the allocation will be replayed so we'll end up with an + * uninitialized quota block. + * + * This is all fine; things are still consistent, and we haven't lost + * any quota information. Just don't complain about bad dquot blks. + */ + if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) { + if (flags & XFS_QMOPT_DOWARN) + xfs_alert(mp, + "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x", + str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC); + errs++; + } + if (ddq->d_version != XFS_DQUOT_VERSION) { + if (flags & XFS_QMOPT_DOWARN) + xfs_alert(mp, + "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x", + str, id, ddq->d_version, XFS_DQUOT_VERSION); + errs++; + } + + if (ddq->d_flags != XFS_DQ_USER && + ddq->d_flags != XFS_DQ_PROJ && + ddq->d_flags != XFS_DQ_GROUP) { + if (flags & XFS_QMOPT_DOWARN) + xfs_alert(mp, + "%s : XFS dquot ID 0x%x, unknown flags 0x%x", + str, id, ddq->d_flags); + errs++; + } + + if (id != -1 && id != be32_to_cpu(ddq->d_id)) { + if (flags & XFS_QMOPT_DOWARN) + xfs_alert(mp, + "%s : ondisk-dquot 0x%p, ID mismatch: " + "0x%x expected, found id 0x%x", + str, ddq, id, be32_to_cpu(ddq->d_id)); + errs++; + } + + if (!errs && ddq->d_id) { + if (ddq->d_blk_softlimit && + be64_to_cpu(ddq->d_bcount) > + be64_to_cpu(ddq->d_blk_softlimit)) { + if (!ddq->d_btimer) { + if (flags & XFS_QMOPT_DOWARN) + xfs_alert(mp, + "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED", + str, (int)be32_to_cpu(ddq->d_id), ddq); + errs++; + } + } + if (ddq->d_ino_softlimit && + be64_to_cpu(ddq->d_icount) > + be64_to_cpu(ddq->d_ino_softlimit)) { + if (!ddq->d_itimer) { + if (flags & XFS_QMOPT_DOWARN) + xfs_alert(mp, + "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED", + str, (int)be32_to_cpu(ddq->d_id), ddq); + errs++; + } + } + if (ddq->d_rtb_softlimit && + be64_to_cpu(ddq->d_rtbcount) > + be64_to_cpu(ddq->d_rtb_softlimit)) { + if (!ddq->d_rtbtimer) { + if (flags & XFS_QMOPT_DOWARN) + xfs_alert(mp, + "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED", + str, (int)be32_to_cpu(ddq->d_id), ddq); + errs++; + } + } + } + + if (!errs || !(flags & XFS_QMOPT_DQREPAIR)) + return errs; + + if (flags & XFS_QMOPT_DOWARN) + xfs_notice(mp, "Re-initializing dquot ID 0x%x", id); + + /* + * Typically, a repair is only requested by quotacheck. + */ + ASSERT(id != -1); + ASSERT(flags & XFS_QMOPT_DQREPAIR); + memset(d, 0, sizeof(xfs_dqblk_t)); + + d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC); + d->dd_diskdq.d_version = XFS_DQUOT_VERSION; + d->dd_diskdq.d_flags = type; + d->dd_diskdq.d_id = cpu_to_be32(id); + + if (xfs_sb_version_hascrc(&mp->m_sb)) { + uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid); + xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), + XFS_DQUOT_CRC_OFF); + } + + return errs; +} + +STATIC bool +xfs_dquot_buf_verify_crc( + struct xfs_mount *mp, + struct xfs_buf *bp) +{ + struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; + int ndquots; + int i; + + if (!xfs_sb_version_hascrc(&mp->m_sb)) + return true; + + /* + * if we are in log recovery, the quota subsystem has not been + * initialised so we have no quotainfo structure. In that case, we need + * to manually calculate the number of dquots in the buffer. + */ + if (mp->m_quotainfo) + ndquots = mp->m_quotainfo->qi_dqperchunk; + else + ndquots = xfs_calc_dquots_per_chunk(mp, + XFS_BB_TO_FSB(mp, bp->b_length)); + + for (i = 0; i < ndquots; i++, d++) { + if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk), + XFS_DQUOT_CRC_OFF)) + return false; + if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid)) + return false; + } + return true; +} + +STATIC bool +xfs_dquot_buf_verify( + struct xfs_mount *mp, + struct xfs_buf *bp) +{ + struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; + xfs_dqid_t id = 0; + int ndquots; + int i; + + /* + * if we are in log recovery, the quota subsystem has not been + * initialised so we have no quotainfo structure. In that case, we need + * to manually calculate the number of dquots in the buffer. + */ + if (mp->m_quotainfo) + ndquots = mp->m_quotainfo->qi_dqperchunk; + else + ndquots = xfs_calc_dquots_per_chunk(mp, bp->b_length); + + /* + * On the first read of the buffer, verify that each dquot is valid. + * We don't know what the id of the dquot is supposed to be, just that + * they should be increasing monotonically within the buffer. If the + * first id is corrupt, then it will fail on the second dquot in the + * buffer so corruptions could point to the wrong dquot in this case. + */ + for (i = 0; i < ndquots; i++) { + struct xfs_disk_dquot *ddq; + int error; + + ddq = &d[i].dd_diskdq; + + if (i == 0) + id = be32_to_cpu(ddq->d_id); + + error = xfs_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN, + "xfs_dquot_buf_verify"); + if (error) + return false; + } + return true; +} + +static void +xfs_dquot_buf_read_verify( + struct xfs_buf *bp) +{ + struct xfs_mount *mp = bp->b_target->bt_mount; + + if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); + xfs_buf_ioerror(bp, EFSCORRUPTED); + } +} + +/* + * we don't calculate the CRC here as that is done when the dquot is flushed to + * the buffer after the update is done. This ensures that the dquot in the + * buffer always has an up-to-date CRC value. + */ +void +xfs_dquot_buf_write_verify( + struct xfs_buf *bp) +{ + struct xfs_mount *mp = bp->b_target->bt_mount; + + if (!xfs_dquot_buf_verify(mp, bp)) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); + xfs_buf_ioerror(bp, EFSCORRUPTED); + return; + } +} + +const struct xfs_buf_ops xfs_dquot_buf_ops = { + .verify_read = xfs_dquot_buf_read_verify, + .verify_write = xfs_dquot_buf_write_verify, +}; + diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 4d4f4a0bb5e4..cb3277e07844 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2363,7 +2363,7 @@ xlog_recover_do_reg_buffer( item->ri_buf[i].i_len, __func__); goto next; } - error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr, + error = xfs_dqcheck(mp, item->ri_buf[i].i_addr, -1, 0, XFS_QMOPT_DOWARN, "dquot_buf_recover"); if (error) @@ -2394,133 +2394,6 @@ xlog_recover_do_reg_buffer( xlog_recover_validate_buf_type(mp, bp, buf_f); } -/* - * Do some primitive error checking on ondisk dquot data structures. - */ -int -xfs_qm_dqcheck( - struct xfs_mount *mp, - xfs_disk_dquot_t *ddq, - xfs_dqid_t id, - uint type, /* used only when IO_dorepair is true */ - uint flags, - char *str) -{ - xfs_dqblk_t *d = (xfs_dqblk_t *)ddq; - int errs = 0; - - /* - * We can encounter an uninitialized dquot buffer for 2 reasons: - * 1. If we crash while deleting the quotainode(s), and those blks got - * used for user data. This is because we take the path of regular - * file deletion; however, the size field of quotainodes is never - * updated, so all the tricks that we play in itruncate_finish - * don't quite matter. - * - * 2. We don't play the quota buffers when there's a quotaoff logitem. - * But the allocation will be replayed so we'll end up with an - * uninitialized quota block. - * - * This is all fine; things are still consistent, and we haven't lost - * any quota information. Just don't complain about bad dquot blks. - */ - if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) { - if (flags & XFS_QMOPT_DOWARN) - xfs_alert(mp, - "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x", - str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC); - errs++; - } - if (ddq->d_version != XFS_DQUOT_VERSION) { - if (flags & XFS_QMOPT_DOWARN) - xfs_alert(mp, - "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x", - str, id, ddq->d_version, XFS_DQUOT_VERSION); - errs++; - } - - if (ddq->d_flags != XFS_DQ_USER && - ddq->d_flags != XFS_DQ_PROJ && - ddq->d_flags != XFS_DQ_GROUP) { - if (flags & XFS_QMOPT_DOWARN) - xfs_alert(mp, - "%s : XFS dquot ID 0x%x, unknown flags 0x%x", - str, id, ddq->d_flags); - errs++; - } - - if (id != -1 && id != be32_to_cpu(ddq->d_id)) { - if (flags & XFS_QMOPT_DOWARN) - xfs_alert(mp, - "%s : ondisk-dquot 0x%p, ID mismatch: " - "0x%x expected, found id 0x%x", - str, ddq, id, be32_to_cpu(ddq->d_id)); - errs++; - } - - if (!errs && ddq->d_id) { - if (ddq->d_blk_softlimit && - be64_to_cpu(ddq->d_bcount) > - be64_to_cpu(ddq->d_blk_softlimit)) { - if (!ddq->d_btimer) { - if (flags & XFS_QMOPT_DOWARN) - xfs_alert(mp, - "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED", - str, (int)be32_to_cpu(ddq->d_id), ddq); - errs++; - } - } - if (ddq->d_ino_softlimit && - be64_to_cpu(ddq->d_icount) > - be64_to_cpu(ddq->d_ino_softlimit)) { - if (!ddq->d_itimer) { - if (flags & XFS_QMOPT_DOWARN) - xfs_alert(mp, - "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED", - str, (int)be32_to_cpu(ddq->d_id), ddq); - errs++; - } - } - if (ddq->d_rtb_softlimit && - be64_to_cpu(ddq->d_rtbcount) > - be64_to_cpu(ddq->d_rtb_softlimit)) { - if (!ddq->d_rtbtimer) { - if (flags & XFS_QMOPT_DOWARN) - xfs_alert(mp, - "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED", - str, (int)be32_to_cpu(ddq->d_id), ddq); - errs++; - } - } - } - - if (!errs || !(flags & XFS_QMOPT_DQREPAIR)) - return errs; - - if (flags & XFS_QMOPT_DOWARN) - xfs_notice(mp, "Re-initializing dquot ID 0x%x", id); - - /* - * Typically, a repair is only requested by quotacheck. - */ - ASSERT(id != -1); - ASSERT(flags & XFS_QMOPT_DQREPAIR); - memset(d, 0, sizeof(xfs_dqblk_t)); - - d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC); - d->dd_diskdq.d_version = XFS_DQUOT_VERSION; - d->dd_diskdq.d_flags = type; - d->dd_diskdq.d_id = cpu_to_be32(id); - - if (xfs_sb_version_hascrc(&mp->m_sb)) { - uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid); - xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), - XFS_DQUOT_CRC_OFF); - } - - return errs; -} - /* * Perform a dquot buffer recovery. * Simple algorithm: if we have found a QUOTAOFF log item of the same type @@ -3126,7 +2999,7 @@ xlog_recover_dquot_pass2( */ dq_f = item->ri_buf[0].i_addr; ASSERT(dq_f); - error = xfs_qm_dqcheck(mp, recddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, + error = xfs_dqcheck(mp, recddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, "xlog_recover_dquot_pass2 (log copy)"); if (error) return XFS_ERROR(EIO); @@ -3146,7 +3019,7 @@ xlog_recover_dquot_pass2( * was among a chunk of dquots created earlier, and we did some * minimal initialization then. */ - error = xfs_qm_dqcheck(mp, ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, + error = xfs_dqcheck(mp, ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, "xlog_recover_dquot_pass2"); if (error) { xfs_buf_relse(bp); diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index dc2d4f7ad7c9..6dfb4e320498 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -665,20 +665,6 @@ xfs_qm_dqdetach( } } -int -xfs_qm_calc_dquots_per_chunk( - struct xfs_mount *mp, - unsigned int nbblks) /* basic block units */ -{ - unsigned int ndquots; - - ASSERT(nbblks > 0); - ndquots = BBTOB(nbblks); - do_div(ndquots, sizeof(xfs_dqblk_t)); - - return ndquots; -} - struct xfs_qm_isolate { struct list_head buffers; struct list_head dispose; @@ -859,7 +845,7 @@ xfs_qm_init_quotainfo( /* Precalc some constants */ qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB); - qinf->qi_dqperchunk = xfs_qm_calc_dquots_per_chunk(mp, + qinf->qi_dqperchunk = xfs_calc_dquots_per_chunk(mp, qinf->qi_dqchunklen); mp->m_qflags |= (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD); @@ -1093,10 +1079,10 @@ xfs_qm_reset_dqcounts( /* * Do a sanity check, and if needed, repair the dqblk. Don't * output any warnings because it's perfectly possible to - * find uninitialised dquot blks. See comment in xfs_qm_dqcheck. + * find uninitialised dquot blks. See comment in xfs_dqcheck. */ - (void) xfs_qm_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR, - "xfs_quotacheck"); + xfs_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR, + "xfs_quotacheck"); ddq->d_bcount = 0; ddq->d_icount = 0; ddq->d_rtbcount = 0; diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h index 2b602df9c242..a788b66a5cb1 100644 --- a/fs/xfs/xfs_qm.h +++ b/fs/xfs/xfs_qm.h @@ -103,8 +103,6 @@ xfs_dq_to_quota_inode(struct xfs_dquot *dqp) return NULL; } -extern int xfs_qm_calc_dquots_per_chunk(struct xfs_mount *mp, - unsigned int nbblks); extern void xfs_trans_mod_dquot(struct xfs_trans *, struct xfs_dquot *, uint, long); extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 84661d4431fa..5376dd406ba2 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -150,8 +150,6 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp, xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \ f | XFS_QMOPT_RES_REGBLKS) -extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *, - xfs_dqid_t, uint, uint, char *); extern int xfs_mount_reset_sbqflags(struct xfs_mount *); #endif /* __XFS_QUOTA_H__ */ diff --git a/fs/xfs/xfs_quota_defs.h b/fs/xfs/xfs_quota_defs.h index e6b0d6e1f4f2..b3b2b1065c0f 100644 --- a/fs/xfs/xfs_quota_defs.h +++ b/fs/xfs/xfs_quota_defs.h @@ -154,4 +154,8 @@ typedef __uint16_t xfs_qwarncnt_t; (XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA) #define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS) +extern int xfs_dqcheck(struct xfs_mount *mp, xfs_disk_dquot_t *ddq, + xfs_dqid_t id, uint type, uint flags, char *str); +extern int xfs_calc_dquots_per_chunk(struct xfs_mount *mp, unsigned int nbblks); + #endif /* __XFS_QUOTA_H__ */ -- cgit v1.2.3 From d420e5c810bce5debce0238021b410d0ef99cf08 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 15 Oct 2013 09:17:53 +1100 Subject: xfs: remove unused transaction callback variables We don't do callbacks at transaction commit time, no do we have any infrastructure to set up or run such callbacks, so remove the variables and typedefs for these operations. If we ever need to add callbacks, we can reintroduce the variables at that time. Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_trans.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 09cf40b89e8c..71c835e9e810 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -85,18 +85,11 @@ struct xfs_item_ops { #define XFS_ITEM_LOCKED 2 #define XFS_ITEM_FLUSHING 3 -/* - * This is the type of function which can be given to xfs_trans_callback() - * to be called upon the transaction's commit to disk. - */ -typedef void (*xfs_trans_callback_t)(struct xfs_trans *, void *); - /* * This is the structure maintained for every active transaction. */ typedef struct xfs_trans { unsigned int t_magic; /* magic number */ - xfs_log_callback_t t_logcb; /* log callback struct */ unsigned int t_type; /* transaction type */ unsigned int t_log_res; /* amt of log space resvd */ unsigned int t_log_count; /* count for perm log res */ -- cgit v1.2.3 From 239880ef6454ccff2ba8d762c3f86e8278f0ce1c Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 23 Oct 2013 10:50:10 +1100 Subject: xfs: decouple log and transaction headers xfs_trans.h has a dependency on xfs_log.h for a couple of structures. Most code that does transactions doesn't need to know anything about the log, but this dependency means that they have to include xfs_log.h. Decouple the xfs_trans.h and xfs_log.h header files and clean up the includes to be in dependency order. In doing this, remove the direct include of xfs_trans_reserve.h from xfs_trans.h so that we remove the dependency between xfs_trans.h and xfs_mount.h. Hence the xfs_trans.h include can be moved to the indicate the actual dependencies other header files have on it. Note that these are kernel only header files, so this does not translate to any userspace changes at all. Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_alloc.c | 6 ++++-- fs/xfs/xfs_alloc_btree.c | 6 +++--- fs/xfs/xfs_aops.c | 7 ++++--- fs/xfs/xfs_attr.c | 8 ++++---- fs/xfs/xfs_attr_inactive.c | 8 ++++---- fs/xfs/xfs_attr_leaf.c | 7 +++---- fs/xfs/xfs_attr_list.c | 6 +++--- fs/xfs/xfs_attr_remote.c | 7 +++---- fs/xfs/xfs_bit.c | 5 +---- fs/xfs/xfs_bmap.c | 7 ++++--- fs/xfs/xfs_bmap_btree.c | 5 +++-- fs/xfs/xfs_bmap_util.c | 9 +++++---- fs/xfs/xfs_btree.c | 5 +++-- fs/xfs/xfs_buf.c | 5 +++-- fs/xfs/xfs_buf_item.c | 7 ++++--- fs/xfs/xfs_da_btree.c | 7 ++++--- fs/xfs/xfs_dir2.c | 6 +++--- fs/xfs/xfs_dir2_block.c | 6 +++--- fs/xfs/xfs_dir2_data.c | 6 +++--- fs/xfs/xfs_dir2_leaf.c | 6 +++--- fs/xfs/xfs_dir2_node.c | 6 +++--- fs/xfs/xfs_dir2_readdir.c | 6 +++--- fs/xfs/xfs_dir2_sf.c | 6 +++--- fs/xfs/xfs_discard.c | 5 +++-- fs/xfs/xfs_dquot.c | 10 ++++++---- fs/xfs/xfs_dquot_buf.c | 5 +++-- fs/xfs/xfs_dquot_item.c | 6 ++++-- fs/xfs/xfs_error.c | 5 ++--- fs/xfs/xfs_export.c | 7 ++++--- fs/xfs/xfs_extent_busy.c | 6 ++++-- fs/xfs/xfs_extfree_item.c | 8 ++++---- fs/xfs/xfs_file.c | 6 ++++-- fs/xfs/xfs_filestream.c | 10 +++++----- fs/xfs/xfs_fsops.c | 9 +++++---- fs/xfs/xfs_ialloc.c | 7 ++++--- fs/xfs/xfs_ialloc_btree.c | 6 +++--- fs/xfs/xfs_icache.c | 9 ++++----- fs/xfs/xfs_icreate_item.c | 5 +++-- fs/xfs/xfs_inode.c | 12 +++++++----- fs/xfs/xfs_inode_buf.c | 7 ++++--- fs/xfs/xfs_inode_fork.c | 6 +++--- fs/xfs/xfs_inode_item.c | 8 ++++---- fs/xfs/xfs_ioctl.c | 7 ++++--- fs/xfs/xfs_ioctl32.c | 4 ++-- fs/xfs/xfs_iomap.c | 11 ++++++----- fs/xfs/xfs_iops.c | 13 +++++++------ fs/xfs/xfs_itable.c | 4 ++-- fs/xfs/xfs_log.c | 8 +++++--- fs/xfs/xfs_log.h | 10 ++-------- fs/xfs/xfs_log_cil.c | 10 ++++++---- fs/xfs/xfs_log_priv.h | 7 ++++--- fs/xfs/xfs_log_recover.c | 13 +++++-------- fs/xfs/xfs_log_rlimit.c | 4 ++-- fs/xfs/xfs_message.c | 5 ++--- fs/xfs/xfs_mount.c | 10 ++++++---- fs/xfs/xfs_qm.c | 9 +++++---- fs/xfs/xfs_qm_bhv.c | 5 +++-- fs/xfs/xfs_qm_syscalls.c | 7 ++++--- fs/xfs/xfs_quotaops.c | 2 +- fs/xfs/xfs_rtalloc.c | 7 ++++--- fs/xfs/xfs_sb.c | 7 ++++--- fs/xfs/xfs_super.c | 8 +++++--- fs/xfs/xfs_symlink.c | 8 +++++--- fs/xfs/xfs_symlink_remote.c | 5 +++-- fs/xfs/xfs_trace.c | 8 +++++--- fs/xfs/xfs_trans.c | 10 ++++++---- fs/xfs/xfs_trans.h | 10 +++++----- fs/xfs/xfs_trans_ail.c | 7 ++++--- fs/xfs/xfs_trans_buf.c | 5 +++-- fs/xfs/xfs_trans_dquot.c | 7 ++++--- fs/xfs/xfs_trans_extfree.c | 5 +++-- fs/xfs/xfs_trans_inode.c | 5 +++-- fs/xfs/xfs_trans_priv.h | 1 - fs/xfs/xfs_trans_resv.c | 6 +++--- fs/xfs/xfs_xattr.c | 3 +-- 75 files changed, 276 insertions(+), 239 deletions(-) diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 2bfca06e0ee7..999db7a95663 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -18,10 +18,10 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_log_format.h" #include "xfs_shared.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -36,7 +36,9 @@ #include "xfs_error.h" #include "xfs_cksum.h" #include "xfs_trace.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" +#include "xfs_log.h" struct workqueue_struct *xfs_alloc_wq; diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index cafc90251d19..0bd33bfbb789 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c @@ -17,9 +17,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -34,6 +33,7 @@ #include "xfs_error.h" #include "xfs_trace.h" #include "xfs_cksum.h" +#include "xfs_trans.h" STATIC struct xfs_btree_cur * diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 2c61e9622f57..caa63cb3e2fd 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -16,16 +16,17 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_alloc.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index dd0f48ff8832..ce6f9e0b6c5f 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -17,12 +17,11 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" -#include "xfs_trans_priv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -33,6 +32,7 @@ #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_alloc.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index 60b60c008fb7..45480f5b6aea 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c @@ -18,11 +18,11 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -36,6 +36,7 @@ #include "xfs_attr_remote.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_attr.h" @@ -43,7 +44,6 @@ #include "xfs_error.h" #include "xfs_quota.h" #include "xfs_trace.h" -#include "xfs_trans_priv.h" /* * Look at all the extents for this logical region, diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 94838fe67386..c10c70c88ec9 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -18,11 +18,9 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" -#include "xfs_trans_priv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -37,6 +35,7 @@ #include "xfs_attr_remote.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_attr.h" diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index 8ba8e4b5e310..a319eb4d123f 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -18,10 +18,9 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -36,6 +35,7 @@ #include "xfs_attr_remote.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_attr.h" diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c index 578f21b70875..1407191f90c3 100644 --- a/fs/xfs/xfs_attr_remote.c +++ b/fs/xfs/xfs_attr_remote.c @@ -18,11 +18,9 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" -#include "xfs_trans_priv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -33,6 +31,7 @@ #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_alloc.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c index 48228848f5ae..16ce44a2b43e 100644 --- a/fs/xfs/xfs_bit.c +++ b/fs/xfs/xfs_bit.c @@ -16,10 +16,7 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" -#include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" -#include "xfs_buf_item.h" +#include "xfs_log_format.h" /* * XFS bit manipulation routines, used in non-realtime code. diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index b5cb377bd2bb..c3756ac09658 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -17,12 +17,12 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" #include "xfs_inum.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -37,6 +37,7 @@ #include "xfs_btree.h" #include "xfs_mount.h" #include "xfs_itable.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_extfree_item.h" #include "xfs_alloc.h" diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index bb8de8e399c4..89ef4e67ff54 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -18,9 +18,9 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -29,6 +29,7 @@ #include "xfs_ialloc_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_alloc.h" #include "xfs_btree.h" diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 74ff478b9b75..271c0d6ceafd 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -18,12 +18,11 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_inum.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -34,6 +33,7 @@ #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_btree.h" +#include "xfs_trans.h" #include "xfs_extfree_item.h" #include "xfs_alloc.h" #include "xfs_bmap.h" @@ -44,6 +44,7 @@ #include "xfs_trans_space.h" #include "xfs_trace.h" #include "xfs_icache.h" +#include "xfs_log.h" /* Kernel only BMAP related definitions and functions */ diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 1a297e26e26c..08365117a933 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c @@ -18,9 +18,9 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -29,6 +29,7 @@ #include "xfs_ialloc_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_buf_item.h" #include "xfs_btree.h" diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 75e4ea7b109a..c7f0b77dcb00 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -34,12 +34,13 @@ #include #include -#include "xfs_sb.h" +#include "xfs_log_format.h" #include "xfs_trans_resv.h" -#include "xfs_log.h" +#include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_trace.h" +#include "xfs_log.h" static kmem_zone_t *xfs_buf_zone; diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index f1d85cfc0a54..b6d20c55282b 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -17,17 +17,18 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_trans_priv.h" #include "xfs_error.h" #include "xfs_trace.h" +#include "xfs_log.h" kmem_zone_t *xfs_buf_item_zone; diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 4ec68c361c4c..377011195975 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -18,11 +18,11 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -33,6 +33,7 @@ #include "xfs_dir2_priv.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_alloc.h" #include "xfs_bmap.h" diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index f46777fa3077..cef16615f761 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -17,10 +17,9 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_inum.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -30,6 +29,7 @@ #include "xfs_alloc_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_dir2.h" diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 5f172730bfa3..6c7cd3ce9e72 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -18,9 +18,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -29,6 +28,7 @@ #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_buf_item.h" diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 8cf8034ebab1..3f7edddb8eff 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -18,9 +18,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -32,6 +31,7 @@ #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_error.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_cksum.h" diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index d5937dab8f56..44fe4b83ac9b 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -18,10 +18,9 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -35,6 +34,7 @@ #include "xfs_dir2_priv.h" #include "xfs_error.h" #include "xfs_trace.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_cksum.h" diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 85ff354db4ae..7836f048102e 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -18,9 +18,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -34,6 +33,7 @@ #include "xfs_dir2_priv.h" #include "xfs_error.h" #include "xfs_trace.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_cksum.h" diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 6b1ffb37654a..048d582525cf 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -18,10 +18,9 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -35,6 +34,7 @@ #include "xfs_error.h" #include "xfs_trace.h" #include "xfs_bmap.h" +#include "xfs_trans.h" /* * Directory file type support functions diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 8d925963a1f2..ac3bb58b58b9 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -17,9 +17,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -28,6 +27,7 @@ #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_error.h" #include "xfs_dir2.h" diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c index 45560ee1a4ba..d38f34cecb40 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -17,8 +17,8 @@ */ #include "xfs.h" #include "xfs_format.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -33,6 +33,7 @@ #include "xfs_extent_busy.h" #include "xfs_discard.h" #include "xfs_trace.h" +#include "xfs_log.h" STATIC int xfs_trim_extents( diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index f85a893c2398..47a815d4a345 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -18,29 +18,31 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_log_format.h" #include "xfs_shared.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_alloc.h" -#include "xfs_quota.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" +#include "xfs_alloc.h" +#include "xfs_quota.h" #include "xfs_rtalloc.h" #include "xfs_error.h" #include "xfs_itable.h" #include "xfs_attr.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_trans_space.h" #include "xfs_trans_priv.h" #include "xfs_qm.h" #include "xfs_cksum.h" #include "xfs_trace.h" +#include "xfs_log.h" /* * Lock order: diff --git a/fs/xfs/xfs_dquot_buf.c b/fs/xfs/xfs_dquot_buf.c index ad2c18fbdb05..3e84b3a57f57 100644 --- a/fs/xfs/xfs_dquot_buf.c +++ b/fs/xfs/xfs_dquot_buf.c @@ -19,15 +19,16 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_inode.h" #include "xfs_quota.h" +#include "xfs_trans.h" #include "xfs_qm.h" #include "xfs_error.h" #include "xfs_cksum.h" diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c index e838d84b4e85..f8a47f77c3fa 100644 --- a/fs/xfs/xfs_dquot_item.c +++ b/fs/xfs/xfs_dquot_item.c @@ -18,8 +18,8 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_alloc.h" @@ -32,9 +32,11 @@ #include "xfs_error.h" #include "xfs_itable.h" #include "xfs_attr.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_trans_priv.h" #include "xfs_qm.h" +#include "xfs_log.h" static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip) { diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 40f2985a27bc..d6c188cc7d43 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -17,9 +17,8 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 96be1d63da9b..8502aee8e65d 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c @@ -16,9 +16,8 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -27,9 +26,11 @@ #include "xfs_export.h" #include "xfs_bmap_btree.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_trace.h" #include "xfs_icache.h" +#include "xfs_log.h" /* * Note that we only accept fileids which are long enough rather than allow diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c index 74828a7895eb..de462640606f 100644 --- a/fs/xfs/xfs_extent_busy.c +++ b/fs/xfs/xfs_extent_busy.c @@ -20,9 +20,9 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_log_format.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -31,6 +31,8 @@ #include "xfs_inode.h" #include "xfs_extent_busy.h" #include "xfs_trace.h" +#include "xfs_trans.h" +#include "xfs_log.h" void xfs_extent_busy_insert( diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index dc53e8febbbe..3680d04f973f 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c @@ -17,14 +17,14 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" -#include "xfs_buf_item.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_trans.h" #include "xfs_trans_priv.h" +#include "xfs_buf_item.h" #include "xfs_extfree_item.h" diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index cc22aa1b7b3b..8b43bfa023af 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -18,10 +18,10 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" -#include "xfs_log.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_trans.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" @@ -29,6 +29,7 @@ #include "xfs_alloc.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" @@ -37,6 +38,7 @@ #include "xfs_dir2_priv.h" #include "xfs_ioctl.h" #include "xfs_trace.h" +#include "xfs_log.h" #include #include diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index ce78e654d37b..7f2c3c1c8ba4 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c @@ -16,15 +16,15 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" -#include "xfs_log.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_ag.h" +#include "xfs_sb.h" +#include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_inum.h" #include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_ag.h" -#include "xfs_trans.h" -#include "xfs_sb.h" -#include "xfs_mount.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" #include "xfs_alloc.h" diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index e5d2c43c65c4..ceaec3165921 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -17,11 +17,10 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -30,6 +29,7 @@ #include "xfs_ialloc_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_btree.h" #include "xfs_error.h" @@ -41,6 +41,7 @@ #include "xfs_rtalloc.h" #include "xfs_filestream.h" #include "xfs_trace.h" +#include "xfs_log.h" /* * File system operations diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 8530cabf128d..c973ff8c4a7c 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -17,12 +17,12 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" #include "xfs_inum.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -38,6 +38,7 @@ #include "xfs_error.h" #include "xfs_bmap.h" #include "xfs_cksum.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_icreate_item.h" #include "xfs_icache.h" diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c index 5448eb6b8c12..2a0b6158e4c4 100644 --- a/fs/xfs/xfs_ialloc_btree.c +++ b/fs/xfs/xfs_ialloc_btree.c @@ -17,10 +17,9 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -35,6 +34,7 @@ #include "xfs_error.h" #include "xfs_trace.h" #include "xfs_cksum.h" +#include "xfs_trans.h" STATIC int diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 76a4ecd638c3..6db11556731d 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -18,12 +18,9 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_log_priv.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_inum.h" -#include "xfs_trans.h" -#include "xfs_trans_priv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -32,6 +29,8 @@ #include "xfs_dinode.h" #include "xfs_error.h" #include "xfs_filestream.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" #include "xfs_inode_item.h" #include "xfs_quota.h" #include "xfs_trace.h" diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c index df8baf38eb85..d2eaccfa73f4 100644 --- a/fs/xfs/xfs_icreate_item.c +++ b/fs/xfs/xfs_icreate_item.c @@ -18,12 +18,13 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_trans.h" #include "xfs_trans_priv.h" #include "xfs_error.h" #include "xfs_icreate_item.h" diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 23d78885c743..f0440dcb5d8c 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -19,13 +19,11 @@ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_log.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_inum.h" -#include "xfs_trans.h" -#include "xfs_trans_space.h" -#include "xfs_trans_priv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -39,6 +37,8 @@ #include "xfs_attr.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans_space.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_inode_item.h" #include "xfs_btree.h" @@ -53,6 +53,8 @@ #include "xfs_trace.h" #include "xfs_icache.h" #include "xfs_symlink.h" +#include "xfs_trans_priv.h" +#include "xfs_log.h" kmem_zone_t *xfs_inode_zone; diff --git a/fs/xfs/xfs_inode_buf.c b/fs/xfs/xfs_inode_buf.c index 65fa56edecf3..c0f974b6cd46 100644 --- a/fs/xfs/xfs_inode_buf.c +++ b/fs/xfs/xfs_inode_buf.c @@ -17,10 +17,10 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -32,6 +32,7 @@ #include "xfs_cksum.h" #include "xfs_icache.h" #include "xfs_ialloc.h" +#include "xfs_trans.h" /* * Check that none of the inode's in the buffer have a next diff --git a/fs/xfs/xfs_inode_fork.c b/fs/xfs/xfs_inode_fork.c index 4fa56fcb38d1..b89b58a3a350 100644 --- a/fs/xfs/xfs_inode_fork.c +++ b/fs/xfs/xfs_inode_fork.c @@ -20,10 +20,9 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" -#include "xfs_log.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_inum.h" -#include "xfs_trans.h" -#include "xfs_trans_priv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -33,6 +32,7 @@ #include "xfs_attr_sf.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_inode_item.h" #include "xfs_btree.h" diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 378081109844..9f8e85ef2681 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -17,19 +17,19 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_trans_priv.h" #include "xfs_bmap_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_error.h" #include "xfs_trace.h" +#include "xfs_trans_priv.h" kmem_zone_t *xfs_ili_zone; /* inode log item zone */ diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index c6c62d12a934..ea65a73d49ba 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -17,10 +17,10 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_alloc.h" @@ -35,6 +35,7 @@ #include "xfs_attr.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_fsops.h" #include "xfs_discard.h" diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index f671f7e472ac..1be3333b260c 100644 --- a/fs/xfs/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c @@ -22,8 +22,8 @@ #include #include "xfs.h" #include "xfs_fs.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index d8fb6dfe75ed..adadf80709b8 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -17,21 +17,22 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_alloc.h" -#include "xfs_quota.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" +#include "xfs_alloc.h" +#include "xfs_quota.h" #include "xfs_btree.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index d046dc8c1925..3f2ae19c8ca0 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -17,15 +17,12 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_acl.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_alloc.h" -#include "xfs_quota.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_bmap_btree.h" @@ -33,10 +30,14 @@ #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" +#include "xfs_acl.h" +#include "xfs_alloc.h" +#include "xfs_quota.h" #include "xfs_rtalloc.h" #include "xfs_error.h" #include "xfs_itable.h" #include "xfs_attr.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_inode_item.h" #include "xfs_trace.h" diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 4f50e637f33b..964b1caae085 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -18,9 +18,9 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" -#include "xfs_log.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_inum.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index fbaf70af3d61..5275ad886971 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -18,19 +18,21 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_error.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" +#include "xfs_log.h" #include "xfs_log_priv.h" #include "xfs_buf_item.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" #include "xfs_log_recover.h" -#include "xfs_trans_priv.h" #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trace.h" diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index 1c458487f000..e148719e0a5d 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h @@ -18,8 +18,6 @@ #ifndef __XFS_LOG_H__ #define __XFS_LOG_H__ -#include "xfs_log_format.h" - struct xfs_log_vec { struct xfs_log_vec *lv_next; /* next lv in build list */ int lv_niovecs; /* number of iovecs in lv */ @@ -82,11 +80,7 @@ struct xlog_ticket; struct xfs_log_item; struct xfs_item_ops; struct xfs_trans; - -void xfs_log_item_init(struct xfs_mount *mp, - struct xfs_log_item *item, - int type, - const struct xfs_item_ops *ops); +struct xfs_log_callback; xfs_lsn_t xfs_log_done(struct xfs_mount *mp, struct xlog_ticket *ticket, @@ -114,7 +108,7 @@ xfs_lsn_t xlog_assign_tail_lsn_locked(struct xfs_mount *mp); void xfs_log_space_wake(struct xfs_mount *mp); int xfs_log_notify(struct xfs_mount *mp, struct xlog_in_core *iclog, - xfs_log_callback_t *callback_entry); + struct xfs_log_callback *callback_entry); int xfs_log_release_iclog(struct xfs_mount *mp, struct xlog_in_core *iclog); int xfs_log_reserve(struct xfs_mount *mp, diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index a844f77d2cc3..5eb51fc5eb84 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -17,11 +17,9 @@ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_log_format.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" -#include "xfs_trans_priv.h" -#include "xfs_log_priv.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -29,6 +27,10 @@ #include "xfs_alloc.h" #include "xfs_extent_busy.h" #include "xfs_discard.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" +#include "xfs_log.h" +#include "xfs_log_priv.h" /* * Allocate a new ticket. Failing to get a new ticket makes it really hard to diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index f80cff26fda9..9bc403a9e54f 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -22,6 +22,7 @@ struct xfs_buf; struct xlog; struct xlog_ticket; struct xfs_mount; +struct xfs_log_callback; /* * Flags for log structure @@ -227,8 +228,8 @@ typedef struct xlog_in_core { /* Callback structures need their own cacheline */ spinlock_t ic_callback_lock ____cacheline_aligned_in_smp; - xfs_log_callback_t *ic_callback; - xfs_log_callback_t **ic_callback_tail; + struct xfs_log_callback *ic_callback; + struct xfs_log_callback **ic_callback_tail; /* reference counts need their own cacheline */ atomic_t ic_refcnt ____cacheline_aligned_in_smp; @@ -254,7 +255,7 @@ struct xfs_cil_ctx { int space_used; /* aggregate size of regions */ struct list_head busy_extents; /* busy extents in chkpt */ struct xfs_log_vec *lv_chain; /* logvecs being pushed */ - xfs_log_callback_t log_cb; /* completion callback hook. */ + struct xfs_log_callback log_cb; /* completion callback hook. */ struct list_head committing; /* ctx committing list */ }; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index cb3277e07844..832ba5d5eb3a 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -17,12 +17,12 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" #include "xfs_inum.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -34,11 +34,12 @@ #include "xfs_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_alloc.h" #include "xfs_ialloc.h" +#include "xfs_log.h" #include "xfs_log_priv.h" -#include "xfs_buf_item.h" #include "xfs_log_recover.h" #include "xfs_extfree_item.h" #include "xfs_trans_priv.h" @@ -46,14 +47,10 @@ #include "xfs_cksum.h" #include "xfs_trace.h" #include "xfs_icache.h" -#include "xfs_icreate_item.h" /* Need all the magic numbers and buffer ops structures from these headers */ -#include "xfs_symlink.h" #include "xfs_da_btree.h" #include "xfs_dir2.h" -#include "xfs_attr_leaf.h" -#include "xfs_attr_remote.h" #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) diff --git a/fs/xfs/xfs_log_rlimit.c b/fs/xfs/xfs_log_rlimit.c index e598bb547dee..3749bc1c00a4 100644 --- a/fs/xfs/xfs_log_rlimit.c +++ b/fs/xfs/xfs_log_rlimit.c @@ -18,8 +18,8 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_ag.h" #include "xfs_sb.h" #include "xfs_mount.h" diff --git a/fs/xfs/xfs_message.c b/fs/xfs/xfs_message.c index 9163dc140532..63ca2f0420b1 100644 --- a/fs/xfs/xfs_message.c +++ b/fs/xfs/xfs_message.c @@ -17,9 +17,8 @@ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 170e7294b7b0..83f7810c53cd 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -17,17 +17,19 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" #include "xfs_inum.h" -#include "xfs_trans.h" -#include "xfs_trans_priv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_da_format.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" +#include "xfs_log.h" #include "xfs_dir2.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 6dfb4e320498..e2f675644b4d 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -18,14 +18,12 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_log_format.h" #include "xfs_shared.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_alloc.h" -#include "xfs_quota.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_ialloc_btree.h" @@ -33,10 +31,13 @@ #include "xfs_inode.h" #include "xfs_ialloc.h" #include "xfs_itable.h" +#include "xfs_alloc.h" #include "xfs_rtalloc.h" +#include "xfs_quota.h" #include "xfs_error.h" #include "xfs_bmap.h" #include "xfs_attr.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_trans_space.h" #include "xfs_qm.h" diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c index 3af50ccdfac1..704628961159 100644 --- a/fs/xfs/xfs_qm_bhv.c +++ b/fs/xfs/xfs_qm_bhv.c @@ -18,8 +18,8 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_alloc.h" @@ -32,6 +32,7 @@ #include "xfs_rtalloc.h" #include "xfs_error.h" #include "xfs_attr.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_qm.h" diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index 174390703eb6..ab2326aaaeda 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c @@ -20,11 +20,11 @@ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_alloc.h" @@ -32,6 +32,7 @@ #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_itable.h" #include "xfs_bmap.h" diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c index 1326d81596c2..2dd467b0b475 100644 --- a/fs/xfs/xfs_quotaops.c +++ b/fs/xfs/xfs_quotaops.c @@ -17,8 +17,8 @@ */ #include "xfs.h" #include "xfs_format.h" +#include "xfs_log_format.h" #include "xfs_trans_resv.h" -#include "xfs_log.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 6f63de303e8e..23c5ca24a02d 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -17,11 +17,11 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -34,6 +34,7 @@ #include "xfs_rtalloc.h" #include "xfs_fsops.h" #include "xfs_error.h" +#include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_trans_space.h" #include "xfs_trace.h" diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index 73b24e15cef7..1b0a6420f1b8 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -18,11 +18,10 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" #include "xfs_inum.h" -#include "xfs_trans.h" -#include "xfs_trans_priv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -44,6 +43,8 @@ #include "xfs_fsops.h" #include "xfs_trace.h" #include "xfs_cksum.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" #include "xfs_buf_item.h" /* diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index a28eca47aa4c..4e20b420ff72 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -17,11 +17,11 @@ */ #include "xfs.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_log.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_inum.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_alloc.h" @@ -41,7 +41,9 @@ #include "xfs_itable.h" #include "xfs_fsops.h" #include "xfs_attr.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" +#include "xfs_log.h" #include "xfs_log_priv.h" #include "xfs_trans_priv.h" #include "xfs_filestream.h" diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index db32c504372c..93fc72c96fad 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -17,12 +17,12 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" +#include "xfs_shared.h" #include "xfs_fs.h" #include "xfs_format.h" -#include "xfs_shared.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -41,7 +41,9 @@ #include "xfs_trans_space.h" #include "xfs_trace.h" #include "xfs_symlink.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" +#include "xfs_log.h" /* ----- Kernel only functions below ----- */ STATIC int diff --git a/fs/xfs/xfs_symlink_remote.c b/fs/xfs/xfs_symlink_remote.c index 4251cd8e8fec..bf59a2b45f8c 100644 --- a/fs/xfs/xfs_symlink_remote.c +++ b/fs/xfs/xfs_symlink_remote.c @@ -19,9 +19,9 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_format.h" +#include "xfs_log_format.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_trans_resv.h" #include "xfs_ag.h" #include "xfs_sb.h" #include "xfs_mount.h" @@ -31,6 +31,7 @@ #include "xfs_trace.h" #include "xfs_symlink.h" #include "xfs_cksum.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c index 6ca992020326..889bb4233323 100644 --- a/fs/xfs/xfs_trace.c +++ b/fs/xfs/xfs_trace.c @@ -17,10 +17,10 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -38,6 +38,8 @@ #include "xfs_bmap.h" #include "xfs_attr.h" #include "xfs_attr_leaf.h" +#include "xfs_trans.h" +#include "xfs_log.h" #include "xfs_log_priv.h" #include "xfs_buf_item.h" #include "xfs_quota.h" diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 06000a9647d5..8d1595f9fd50 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -18,10 +18,10 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -38,10 +38,12 @@ #include "xfs_extent_busy.h" #include "xfs_bmap.h" #include "xfs_quota.h" -#include "xfs_qm.h" +#include "xfs_trans.h" #include "xfs_trans_priv.h" #include "xfs_trans_space.h" +#include "xfs_qm.h" #include "xfs_inode_item.h" +#include "xfs_log.h" #include "xfs_log_priv.h" #include "xfs_buf_item.h" #include "xfs_trace.h" diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 71c835e9e810..9cc5fbed4f26 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -18,10 +18,6 @@ #ifndef __XFS_TRANS_H__ #define __XFS_TRANS_H__ -struct xfs_log_item; - -#include "xfs_trans_resv.h" - /* kernel only transaction subsystem defines */ struct xfs_buf; @@ -77,6 +73,9 @@ struct xfs_item_ops { void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t); }; +void xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item, + int type, const struct xfs_item_ops *ops); + /* * Return values for the iop_push() routines. */ @@ -85,6 +84,7 @@ struct xfs_item_ops { #define XFS_ITEM_LOCKED 2 #define XFS_ITEM_FLUSHING 3 + /* * This is the structure maintained for every active transaction. */ @@ -125,7 +125,6 @@ typedef struct xfs_trans { int64_t t_rextents_delta;/* superblocks rextents chg */ int64_t t_rextslog_delta;/* superblocks rextslog chg */ struct list_head t_items; /* log item descriptors */ - xfs_trans_header_t t_header; /* header for in-log trans */ struct list_head t_busy; /* list of busy extents */ unsigned long t_pflags; /* saved process flags state */ } xfs_trans_t; @@ -230,6 +229,7 @@ void xfs_trans_log_efd_extent(xfs_trans_t *, xfs_fsblock_t, xfs_extlen_t); int xfs_trans_commit(xfs_trans_t *, uint flags); +int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); void xfs_trans_cancel(xfs_trans_t *, int); int xfs_trans_ail_init(struct xfs_mount *); void xfs_trans_ail_destroy(struct xfs_mount *); diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 21c6d7ddbc06..4b47cfebd25b 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -18,15 +18,16 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_types.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_trans.h" #include "xfs_trans_priv.h" #include "xfs_trace.h" #include "xfs_error.h" +#include "xfs_log.h" #ifdef DEBUG /* diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 0167a65ec851..6b1b993257d6 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -18,8 +18,8 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -28,6 +28,7 @@ #include "xfs_ialloc_btree.h" #include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_trans_priv.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index 4d630d2c2804..2025f6eea4aa 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -17,10 +17,10 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_alloc.h" @@ -33,6 +33,7 @@ #include "xfs_rtalloc.h" #include "xfs_error.h" #include "xfs_attr.h" +#include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_trans_priv.h" #include "xfs_qm.h" diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index 3bfb98bec050..47978ba89dae 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c @@ -18,11 +18,12 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_trans.h" #include "xfs_trans_priv.h" #include "xfs_extfree_item.h" diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index dcab52ec9cb6..b1a0efa6b32a 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c @@ -18,8 +18,8 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -29,6 +29,7 @@ #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_btree.h" +#include "xfs_trans.h" #include "xfs_trans_priv.h" #include "xfs_inode_item.h" #include "xfs_trace.h" diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h index c52def0b441c..12e86af9d9b9 100644 --- a/fs/xfs/xfs_trans_priv.h +++ b/fs/xfs/xfs_trans_priv.h @@ -27,7 +27,6 @@ struct xfs_log_vec; void xfs_trans_init(struct xfs_mount *); -int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); void xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *); void xfs_trans_del_item(struct xfs_log_item *); void xfs_trans_free_items(struct xfs_trans *tp, xfs_lsn_t commit_lsn, diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c index cc8361255c8e..89de046331da 100644 --- a/fs/xfs/xfs_trans_resv.c +++ b/fs/xfs/xfs_trans_resv.c @@ -18,11 +18,10 @@ */ #include "xfs.h" #include "xfs_fs.h" -#include "xfs_format.h" #include "xfs_shared.h" -#include "xfs_log.h" +#include "xfs_format.h" +#include "xfs_log_format.h" #include "xfs_trans_resv.h" -#include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" @@ -41,6 +40,7 @@ #include "xfs_bmap.h" #include "xfs_bmap_util.h" #include "xfs_quota.h" +#include "xfs_trans.h" #include "xfs_qm.h" #include "xfs_trans_space.h" #include "xfs_trace.h" diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index 08047502683d..23052992c7e2 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -18,8 +18,7 @@ #include "xfs.h" #include "xfs_log_format.h" -#include "xfs_log.h" -#include "xfs_trans.h" +#include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -- cgit v1.2.3 From a4fbe6ab1e7abecf42b75e9c73701ed33b4ab03b Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 23 Oct 2013 10:51:50 +1100 Subject: xfs: decouple inode and bmap btree header files Currently the xfs_inode.h header has a dependency on the definition of the BMAP btree records as the inode fork includes an array of xfs_bmbt_rec_host_t objects in it's definition. Move all the btree format definitions from xfs_btree.h, xfs_bmap_btree.h, xfs_alloc_btree.h and xfs_ialloc_btree.h to xfs_format.h to continue the process of centralising the on-disk format definitions. With this done, the xfs inode definitions are no longer dependent on btree header files. The enables a massive culling of unnecessary includes, with close to 200 #include directives removed from the XFS kernel code base. Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_acl.c | 8 +- fs/xfs/xfs_alloc.c | 5 +- fs/xfs/xfs_alloc_btree.c | 7 +- fs/xfs/xfs_alloc_btree.h | 33 ------ fs/xfs/xfs_aops.c | 4 +- fs/xfs/xfs_attr.c | 4 +- fs/xfs/xfs_attr_inactive.c | 8 +- fs/xfs/xfs_attr_leaf.c | 13 +-- fs/xfs/xfs_attr_list.c | 12 +-- fs/xfs/xfs_attr_remote.c | 5 +- fs/xfs/xfs_bmap.c | 12 +-- fs/xfs/xfs_bmap_btree.c | 7 +- fs/xfs/xfs_bmap_btree.h | 103 ------------------ fs/xfs/xfs_bmap_util.c | 6 +- fs/xfs/xfs_btree.c | 5 +- fs/xfs/xfs_btree.h | 79 +++----------- fs/xfs/xfs_buf_item.h | 4 - fs/xfs/xfs_da_btree.c | 2 - fs/xfs/xfs_dir2.c | 5 +- fs/xfs/xfs_dir2_block.c | 4 +- fs/xfs/xfs_dir2_data.c | 3 +- fs/xfs/xfs_dir2_leaf.c | 4 +- fs/xfs/xfs_dir2_node.c | 3 +- fs/xfs/xfs_dir2_readdir.c | 4 +- fs/xfs/xfs_dir2_sf.c | 4 +- fs/xfs/xfs_discard.c | 6 +- fs/xfs/xfs_dquot.c | 5 +- fs/xfs/xfs_dquot_buf.c | 2 - fs/xfs/xfs_dquot_item.c | 8 +- fs/xfs/xfs_error.c | 4 +- fs/xfs/xfs_export.c | 2 +- fs/xfs/xfs_extent_busy.c | 2 - fs/xfs/xfs_extent_busy.h | 4 + fs/xfs/xfs_file.c | 5 +- fs/xfs/xfs_filestream.c | 4 +- fs/xfs/xfs_format.h | 255 +++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_fsops.c | 12 +-- fs/xfs/xfs_ialloc.c | 6 +- fs/xfs/xfs_ialloc.h | 3 +- fs/xfs/xfs_ialloc_btree.c | 6 +- fs/xfs/xfs_ialloc_btree.h | 49 --------- fs/xfs/xfs_icache.c | 4 - fs/xfs/xfs_inode.c | 10 +- fs/xfs/xfs_inode.h | 1 - fs/xfs/xfs_inode_buf.c | 6 +- fs/xfs/xfs_inode_fork.c | 16 +-- fs/xfs/xfs_inode_fork.h | 1 + fs/xfs/xfs_inode_item.c | 4 +- fs/xfs/xfs_ioctl.c | 9 +- fs/xfs/xfs_ioctl32.c | 3 +- fs/xfs/xfs_iomap.c | 16 +-- fs/xfs/xfs_iops.c | 8 +- fs/xfs/xfs_itable.c | 9 +- fs/xfs/xfs_log.c | 6 +- fs/xfs/xfs_log_recover.c | 18 ++-- fs/xfs/xfs_log_rlimit.c | 3 +- fs/xfs/xfs_mount.c | 15 +-- fs/xfs/xfs_qm.c | 11 +- fs/xfs/xfs_qm_bhv.c | 7 -- fs/xfs/xfs_qm_syscalls.c | 10 +- fs/xfs/xfs_quotaops.c | 3 +- fs/xfs/xfs_rtalloc.c | 9 +- fs/xfs/xfs_sb.c | 18 +--- fs/xfs/xfs_super.c | 16 +-- fs/xfs/xfs_symlink.c | 6 +- fs/xfs/xfs_trace.c | 5 +- fs/xfs/xfs_trans.c | 16 +-- fs/xfs/xfs_trans.h | 5 + fs/xfs/xfs_trans_buf.c | 5 +- fs/xfs/xfs_trans_dquot.c | 9 +- fs/xfs/xfs_trans_inode.c | 6 +- fs/xfs/xfs_trans_resv.c | 12 +-- fs/xfs/xfs_xattr.c | 2 +- 73 files changed, 403 insertions(+), 583 deletions(-) diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 0e2f37efedd0..370eb3e121d1 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -16,15 +16,15 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" -#include "xfs_acl.h" -#include "xfs_attr.h" -#include "xfs_bmap_btree.h" -#include "xfs_inode.h" #include "xfs_ag.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_inode.h" +#include "xfs_acl.h" +#include "xfs_attr.h" #include "xfs_trace.h" #include #include diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 999db7a95663..bcf16528bac5 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -25,12 +25,9 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_btree.h" +#include "xfs_alloc_btree.h" #include "xfs_alloc.h" #include "xfs_extent_busy.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index 0bd33bfbb789..698587f6c60a 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c @@ -17,17 +17,14 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" #include "xfs_btree.h" +#include "xfs_alloc_btree.h" #include "xfs_alloc.h" #include "xfs_extent_busy.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_alloc_btree.h b/fs/xfs/xfs_alloc_btree.h index 72676c36b1bb..45e189e7e81c 100644 --- a/fs/xfs/xfs_alloc_btree.h +++ b/fs/xfs/xfs_alloc_btree.h @@ -26,39 +26,6 @@ struct xfs_buf; struct xfs_btree_cur; struct xfs_mount; -/* - * There are two on-disk btrees, one sorted by blockno and one sorted - * by blockcount and blockno. All blocks look the same to make the code - * simpler; if we have time later, we'll make the optimizations. - */ -#define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */ -#define XFS_ABTB_CRC_MAGIC 0x41423342 /* 'AB3B' */ -#define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */ -#define XFS_ABTC_CRC_MAGIC 0x41423343 /* 'AB3C' */ - -/* - * Data record/key structure - */ -typedef struct xfs_alloc_rec { - __be32 ar_startblock; /* starting block number */ - __be32 ar_blockcount; /* count of free blocks */ -} xfs_alloc_rec_t, xfs_alloc_key_t; - -typedef struct xfs_alloc_rec_incore { - xfs_agblock_t ar_startblock; /* starting block number */ - xfs_extlen_t ar_blockcount; /* count of free blocks */ -} xfs_alloc_rec_incore_t; - -/* btree pointer type */ -typedef __be32 xfs_alloc_ptr_t; - -/* - * Block numbers in the AG: - * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3. - */ -#define XFS_BNO_BLOCK(mp) ((xfs_agblock_t)(XFS_AGFL_BLOCK(mp) + 1)) -#define XFS_CNT_BLOCK(mp) ((xfs_agblock_t)(XFS_BNO_BLOCK(mp) + 1)) - /* * Btree block header size depends on a superblock flag. */ diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index caa63cb3e2fd..eb310caf13b1 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -23,8 +23,6 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" @@ -34,6 +32,8 @@ #include "xfs_trace.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" +#include "xfs_bmap_btree.h" +#include "xfs_dinode.h" #include #include #include diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index ce6f9e0b6c5f..b86127072ac3 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -27,15 +27,14 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" #include "xfs_attr_sf.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_alloc.h" #include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" +#include "xfs_bmap_btree.h" #include "xfs_attr.h" #include "xfs_attr_leaf.h" #include "xfs_attr_remote.h" @@ -43,6 +42,7 @@ #include "xfs_quota.h" #include "xfs_trans_space.h" #include "xfs_trace.h" +#include "xfs_dinode.h" /* * xfs_attr.c diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index 45480f5b6aea..f33fb62b7f17 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c @@ -28,14 +28,9 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" +#include "xfs_inode.h" #include "xfs_alloc.h" -#include "xfs_btree.h" #include "xfs_attr_remote.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" @@ -44,6 +39,7 @@ #include "xfs_error.h" #include "xfs_quota.h" #include "xfs_trace.h" +#include "xfs_dinode.h" /* * Look at all the extents for this logical region, diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index c10c70c88ec9..a0f90193a247 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" @@ -26,24 +27,20 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_alloc.h" -#include "xfs_btree.h" -#include "xfs_attr_sf.h" -#include "xfs_attr_remote.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" +#include "xfs_bmap_btree.h" #include "xfs_bmap.h" +#include "xfs_attr_sf.h" +#include "xfs_attr_remote.h" #include "xfs_attr.h" #include "xfs_attr_leaf.h" #include "xfs_error.h" #include "xfs_trace.h" #include "xfs_buf_item.h" #include "xfs_cksum.h" +#include "xfs_dinode.h" /* diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index a319eb4d123f..46c4ce148a43 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" @@ -26,24 +27,19 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_alloc.h" -#include "xfs_btree.h" -#include "xfs_attr_sf.h" -#include "xfs_attr_remote.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_bmap.h" #include "xfs_attr.h" +#include "xfs_attr_sf.h" +#include "xfs_attr_remote.h" #include "xfs_attr_leaf.h" #include "xfs_error.h" #include "xfs_trace.h" #include "xfs_buf_item.h" #include "xfs_cksum.h" +#include "xfs_dinode.h" STATIC int xfs_attr_shortform_compare(const void *a, const void *b) diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c index 1407191f90c3..2e5530467f2d 100644 --- a/fs/xfs/xfs_attr_remote.c +++ b/fs/xfs/xfs_attr_remote.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" @@ -25,10 +26,7 @@ #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_da_format.h" -#include "xfs_error.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_alloc.h" #include "xfs_trans.h" @@ -42,6 +40,7 @@ #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_buf_item.h" +#include "xfs_error.h" #define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */ diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index c3756ac09658..1c02da8bb7df 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -29,29 +29,25 @@ #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_dir2.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_btree.h" -#include "xfs_mount.h" -#include "xfs_itable.h" #include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_extfree_item.h" #include "xfs_alloc.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" +#include "xfs_bmap_btree.h" #include "xfs_rtalloc.h" #include "xfs_error.h" -#include "xfs_attr_leaf.h" #include "xfs_quota.h" #include "xfs_trans_space.h" #include "xfs_buf_item.h" -#include "xfs_filestream.h" #include "xfs_trace.h" #include "xfs_symlink.h" +#include "xfs_attr_leaf.h" +#include "xfs_dinode.h" +#include "xfs_filestream.h" kmem_zone_t *xfs_bmap_free_item_zone; diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 89ef4e67ff54..2fb4a2202e17 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -24,21 +24,18 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_alloc.h" #include "xfs_btree.h" -#include "xfs_itable.h" +#include "xfs_bmap_btree.h" #include "xfs_bmap.h" #include "xfs_error.h" #include "xfs_quota.h" #include "xfs_trace.h" #include "xfs_cksum.h" +#include "xfs_dinode.h" /* * Determine the extent state. diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h index e2b0768a89ba..6e42e1e50b89 100644 --- a/fs/xfs/xfs_bmap_btree.h +++ b/fs/xfs/xfs_bmap_btree.h @@ -18,94 +18,12 @@ #ifndef __XFS_BMAP_BTREE_H__ #define __XFS_BMAP_BTREE_H__ -#define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */ -#define XFS_BMAP_CRC_MAGIC 0x424d4133 /* 'BMA3' */ - struct xfs_btree_cur; struct xfs_btree_block; struct xfs_mount; struct xfs_inode; struct xfs_trans; -/* - * Bmap root header, on-disk form only. - */ -typedef struct xfs_bmdr_block { - __be16 bb_level; /* 0 is a leaf */ - __be16 bb_numrecs; /* current # of data records */ -} xfs_bmdr_block_t; - -/* - * Bmap btree record and extent descriptor. - * l0:63 is an extent flag (value 1 indicates non-normal). - * l0:9-62 are startoff. - * l0:0-8 and l1:21-63 are startblock. - * l1:0-20 are blockcount. - */ -#define BMBT_EXNTFLAG_BITLEN 1 -#define BMBT_STARTOFF_BITLEN 54 -#define BMBT_STARTBLOCK_BITLEN 52 -#define BMBT_BLOCKCOUNT_BITLEN 21 - -typedef struct xfs_bmbt_rec { - __be64 l0, l1; -} xfs_bmbt_rec_t; - -typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */ -typedef xfs_bmbt_rec_t xfs_bmdr_rec_t; - -typedef struct xfs_bmbt_rec_host { - __uint64_t l0, l1; -} xfs_bmbt_rec_host_t; - -/* - * Values and macros for delayed-allocation startblock fields. - */ -#define STARTBLOCKVALBITS 17 -#define STARTBLOCKMASKBITS (15 + XFS_BIG_BLKNOS * 20) -#define DSTARTBLOCKMASKBITS (15 + 20) -#define STARTBLOCKMASK \ - (((((xfs_fsblock_t)1) << STARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS) -#define DSTARTBLOCKMASK \ - (((((xfs_dfsbno_t)1) << DSTARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS) - -static inline int isnullstartblock(xfs_fsblock_t x) -{ - return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK; -} - -static inline int isnulldstartblock(xfs_dfsbno_t x) -{ - return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK; -} - -static inline xfs_fsblock_t nullstartblock(int k) -{ - ASSERT(k < (1 << STARTBLOCKVALBITS)); - return STARTBLOCKMASK | (k); -} - -static inline xfs_filblks_t startblockval(xfs_fsblock_t x) -{ - return (xfs_filblks_t)((x) & ~STARTBLOCKMASK); -} - -/* - * Possible extent formats. - */ -typedef enum { - XFS_EXTFMT_NOSTATE = 0, - XFS_EXTFMT_HASSTATE -} xfs_exntfmt_t; - -/* - * Possible extent states. - */ -typedef enum { - XFS_EXT_NORM, XFS_EXT_UNWRITTEN, - XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID -} xfs_exntst_t; - /* * Extent state and extent format macros. */ @@ -114,27 +32,6 @@ typedef enum { XFS_EXTFMT_HASSTATE : XFS_EXTFMT_NOSTATE) #define ISUNWRITTEN(x) ((x)->br_state == XFS_EXT_UNWRITTEN) -/* - * Incore version of above. - */ -typedef struct xfs_bmbt_irec -{ - xfs_fileoff_t br_startoff; /* starting file offset */ - xfs_fsblock_t br_startblock; /* starting block number */ - xfs_filblks_t br_blockcount; /* number of blocks */ - xfs_exntst_t br_state; /* extent state */ -} xfs_bmbt_irec_t; - -/* - * Key structure for non-leaf levels of the tree. - */ -typedef struct xfs_bmbt_key { - __be64 br_startoff; /* starting file offset */ -} xfs_bmbt_key_t, xfs_bmdr_key_t; - -/* btree pointer type */ -typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; - /* * Btree block header size depends on a superblock flag. */ diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 271c0d6ceafd..5887e41c0323 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -27,10 +27,6 @@ #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_da_format.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_trans.h" @@ -38,6 +34,7 @@ #include "xfs_alloc.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" +#include "xfs_bmap_btree.h" #include "xfs_rtalloc.h" #include "xfs_error.h" #include "xfs_quota.h" @@ -45,6 +42,7 @@ #include "xfs_trace.h" #include "xfs_icache.h" #include "xfs_log.h" +#include "xfs_dinode.h" /* Kernel only BMAP related definitions and functions */ diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 08365117a933..9adaae4f3e2f 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c @@ -18,16 +18,13 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h index 06729b67ad58..91e34f21bace 100644 --- a/fs/xfs/xfs_btree.h +++ b/fs/xfs/xfs_btree.h @@ -26,73 +26,6 @@ struct xfs_trans; extern kmem_zone_t *xfs_btree_cur_zone; -/* - * This nonsense is to make -wlint happy. - */ -#define XFS_LOOKUP_EQ ((xfs_lookup_t)XFS_LOOKUP_EQi) -#define XFS_LOOKUP_LE ((xfs_lookup_t)XFS_LOOKUP_LEi) -#define XFS_LOOKUP_GE ((xfs_lookup_t)XFS_LOOKUP_GEi) - -#define XFS_BTNUM_BNO ((xfs_btnum_t)XFS_BTNUM_BNOi) -#define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi) -#define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) -#define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) - -/* - * Generic btree header. - * - * This is a combination of the actual format used on disk for short and long - * format btrees. The first three fields are shared by both format, but the - * pointers are different and should be used with care. - * - * To get the size of the actual short or long form headers please use the size - * macros below. Never use sizeof(xfs_btree_block). - * - * The blkno, crc, lsn, owner and uuid fields are only available in filesystems - * with the crc feature bit, and all accesses to them must be conditional on - * that flag. - */ -struct xfs_btree_block { - __be32 bb_magic; /* magic number for block type */ - __be16 bb_level; /* 0 is a leaf */ - __be16 bb_numrecs; /* current # of data records */ - union { - struct { - __be32 bb_leftsib; - __be32 bb_rightsib; - - __be64 bb_blkno; - __be64 bb_lsn; - uuid_t bb_uuid; - __be32 bb_owner; - __le32 bb_crc; - } s; /* short form pointers */ - struct { - __be64 bb_leftsib; - __be64 bb_rightsib; - - __be64 bb_blkno; - __be64 bb_lsn; - uuid_t bb_uuid; - __be64 bb_owner; - __le32 bb_crc; - __be32 bb_pad; /* padding for alignment */ - } l; /* long form pointers */ - } bb_u; /* rest */ -}; - -#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */ -#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */ - -/* sizes of CRC enabled btree blocks */ -#define XFS_BTREE_SBLOCK_CRC_LEN (XFS_BTREE_SBLOCK_LEN + 40) -#define XFS_BTREE_LBLOCK_CRC_LEN (XFS_BTREE_LBLOCK_LEN + 48) - -#define XFS_BTREE_SBLOCK_CRC_OFF \ - offsetof(struct xfs_btree_block, bb_u.s.bb_crc) -#define XFS_BTREE_LBLOCK_CRC_OFF \ - offsetof(struct xfs_btree_block, bb_u.l.bb_crc) - /* * Generic key, ptr and record wrapper structures. * @@ -118,6 +51,18 @@ union xfs_btree_rec { xfs_inobt_rec_t inobt; }; +/* + * This nonsense is to make -wlint happy. + */ +#define XFS_LOOKUP_EQ ((xfs_lookup_t)XFS_LOOKUP_EQi) +#define XFS_LOOKUP_LE ((xfs_lookup_t)XFS_LOOKUP_LEi) +#define XFS_LOOKUP_GE ((xfs_lookup_t)XFS_LOOKUP_GEi) + +#define XFS_BTNUM_BNO ((xfs_btnum_t)XFS_BTNUM_BNOi) +#define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi) +#define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) +#define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) + /* * For logging record fields. */ diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index db6371087fe8..3f3455a41510 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h @@ -71,10 +71,6 @@ void xfs_buf_attach_iodone(struct xfs_buf *, void xfs_buf_iodone_callbacks(struct xfs_buf *); void xfs_buf_iodone(struct xfs_buf *, struct xfs_log_item *); -void xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *, - enum xfs_blft); -void xfs_trans_buf_copy_type(struct xfs_buf *dst_bp, struct xfs_buf *src_bp); - extern kmem_zone_t *xfs_buf_item_zone; #endif /* __XFS_BUF_ITEM_H__ */ diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 377011195975..eb65c546ffd8 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -28,10 +28,8 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index cef16615f761..38bf9324302c 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -17,6 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_inum.h" @@ -25,9 +26,6 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" @@ -36,6 +34,7 @@ #include "xfs_dir2_priv.h" #include "xfs_error.h" #include "xfs_trace.h" +#include "xfs_dinode.h" struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR }; diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 6c7cd3ce9e72..9f3f83a5e2da 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" @@ -25,8 +26,6 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" @@ -37,6 +36,7 @@ #include "xfs_error.h" #include "xfs_trace.h" #include "xfs_cksum.h" +#include "xfs_dinode.h" /* * Local function prototypes. diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 3f7edddb8eff..ccfeb4d8376a 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" @@ -25,8 +26,6 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 44fe4b83ac9b..51fdc11a1e2c 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -18,16 +18,14 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" -#include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_dir2.h" diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 7836f048102e..b8381646b8af 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" @@ -25,8 +26,6 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_dir2.h" diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 048d582525cf..45c9ce8cdb28 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" @@ -26,8 +27,6 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_dir2.h" #include "xfs_dir2_priv.h" @@ -35,6 +34,7 @@ #include "xfs_trace.h" #include "xfs_bmap.h" #include "xfs_trans.h" +#include "xfs_dinode.h" /* * Directory file type support functions diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index ac3bb58b58b9..8811ee5eaec6 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -17,6 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" @@ -24,8 +25,6 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" @@ -33,6 +32,7 @@ #include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_trace.h" +#include "xfs_dinode.h" /* * Prototypes for internal functions. diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c index d38f34cecb40..8367d6dc18c9 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -23,11 +23,9 @@ #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_quota.h" -#include "xfs_alloc_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_btree.h" #include "xfs_inode.h" +#include "xfs_btree.h" +#include "xfs_alloc_btree.h" #include "xfs_alloc.h" #include "xfs_error.h" #include "xfs_extent_busy.h" diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 47a815d4a345..6b1e695caf0e 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -25,16 +25,12 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" #include "xfs_alloc.h" #include "xfs_quota.h" -#include "xfs_rtalloc.h" #include "xfs_error.h" -#include "xfs_itable.h" -#include "xfs_attr.h" #include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_trans_space.h" @@ -43,6 +39,7 @@ #include "xfs_cksum.h" #include "xfs_trace.h" #include "xfs_log.h" +#include "xfs_bmap_btree.h" /* * Lock order: diff --git a/fs/xfs/xfs_dquot_buf.c b/fs/xfs/xfs_dquot_buf.c index 3e84b3a57f57..aaaf41b29869 100644 --- a/fs/xfs/xfs_dquot_buf.c +++ b/fs/xfs/xfs_dquot_buf.c @@ -21,11 +21,9 @@ #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" -#include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" #include "xfs_inode.h" #include "xfs_quota.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c index f8a47f77c3fa..92e5f62eefc6 100644 --- a/fs/xfs/xfs_dquot_item.c +++ b/fs/xfs/xfs_dquot_item.c @@ -22,16 +22,10 @@ #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_alloc.h" -#include "xfs_quota.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" #include "xfs_inode.h" -#include "xfs_bmap.h" -#include "xfs_rtalloc.h" +#include "xfs_quota.h" #include "xfs_error.h" -#include "xfs_itable.h" -#include "xfs_attr.h" #include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_trans_priv.h" diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index d6c188cc7d43..9995b807d627 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -16,15 +16,13 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" +#include "xfs_format.h" #include "xfs_fs.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" #include "xfs_error.h" #ifdef DEBUG diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 8502aee8e65d..1399e187d425 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c @@ -16,6 +16,7 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" @@ -24,7 +25,6 @@ #include "xfs_da_format.h" #include "xfs_dir2.h" #include "xfs_export.h" -#include "xfs_bmap_btree.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c index de462640606f..fd22f69049d4 100644 --- a/fs/xfs/xfs_extent_busy.c +++ b/fs/xfs/xfs_extent_busy.c @@ -26,9 +26,7 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" #include "xfs_alloc.h" -#include "xfs_inode.h" #include "xfs_extent_busy.h" #include "xfs_trace.h" #include "xfs_trans.h" diff --git a/fs/xfs/xfs_extent_busy.h b/fs/xfs/xfs_extent_busy.h index 985412d65ba5..bfff284d2dcc 100644 --- a/fs/xfs/xfs_extent_busy.h +++ b/fs/xfs/xfs_extent_busy.h @@ -20,6 +20,10 @@ #ifndef __XFS_EXTENT_BUSY_H__ #define __XFS_EXTENT_BUSY_H__ +struct xfs_mount; +struct xfs_trans; +struct xfs_alloc_arg; + /* * Busy block/extent entry. Indexed by a rbtree in perag to mark blocks that * have been freed but whose transactions aren't committed to disk yet. diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 8b43bfa023af..52c91e143725 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" @@ -25,9 +26,6 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" @@ -39,6 +37,7 @@ #include "xfs_ioctl.h" #include "xfs_trace.h" #include "xfs_log.h" +#include "xfs_dinode.h" #include #include diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index 7f2c3c1c8ba4..12b6e7701985 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c @@ -16,19 +16,19 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xfs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_ag.h" #include "xfs_sb.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" #include "xfs_inum.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" #include "xfs_alloc.h" #include "xfs_mru_cache.h" +#include "xfs_dinode.h" #include "xfs_filestream.h" #include "xfs_trace.h" diff --git a/fs/xfs/xfs_format.h b/fs/xfs/xfs_format.h index a790428f3bf4..b6ab5a3cfa12 100644 --- a/fs/xfs/xfs_format.h +++ b/fs/xfs/xfs_format.h @@ -156,4 +156,259 @@ struct xfs_dsymlink_hdr { ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ sizeof(struct xfs_dsymlink_hdr) : 0)) + +/* + * Allocation Btree format definitions + * + * There are two on-disk btrees, one sorted by blockno and one sorted + * by blockcount and blockno. All blocks look the same to make the code + * simpler; if we have time later, we'll make the optimizations. + */ +#define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */ +#define XFS_ABTB_CRC_MAGIC 0x41423342 /* 'AB3B' */ +#define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */ +#define XFS_ABTC_CRC_MAGIC 0x41423343 /* 'AB3C' */ + +/* + * Data record/key structure + */ +typedef struct xfs_alloc_rec { + __be32 ar_startblock; /* starting block number */ + __be32 ar_blockcount; /* count of free blocks */ +} xfs_alloc_rec_t, xfs_alloc_key_t; + +typedef struct xfs_alloc_rec_incore { + xfs_agblock_t ar_startblock; /* starting block number */ + xfs_extlen_t ar_blockcount; /* count of free blocks */ +} xfs_alloc_rec_incore_t; + +/* btree pointer type */ +typedef __be32 xfs_alloc_ptr_t; + +/* + * Block numbers in the AG: + * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3. + */ +#define XFS_BNO_BLOCK(mp) ((xfs_agblock_t)(XFS_AGFL_BLOCK(mp) + 1)) +#define XFS_CNT_BLOCK(mp) ((xfs_agblock_t)(XFS_BNO_BLOCK(mp) + 1)) + + +/* + * Inode Allocation Btree format definitions + * + * There is a btree for the inode map per allocation group. + */ +#define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */ +#define XFS_IBT_CRC_MAGIC 0x49414233 /* 'IAB3' */ + +typedef __uint64_t xfs_inofree_t; +#define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t)) +#define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3) +#define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) +#define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i)) + +static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) +{ + return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i; +} + +/* + * Data record structure + */ +typedef struct xfs_inobt_rec { + __be32 ir_startino; /* starting inode number */ + __be32 ir_freecount; /* count of free inodes (set bits) */ + __be64 ir_free; /* free inode mask */ +} xfs_inobt_rec_t; + +typedef struct xfs_inobt_rec_incore { + xfs_agino_t ir_startino; /* starting inode number */ + __int32_t ir_freecount; /* count of free inodes (set bits) */ + xfs_inofree_t ir_free; /* free inode mask */ +} xfs_inobt_rec_incore_t; + + +/* + * Key structure + */ +typedef struct xfs_inobt_key { + __be32 ir_startino; /* starting inode number */ +} xfs_inobt_key_t; + +/* btree pointer type */ +typedef __be32 xfs_inobt_ptr_t; + +/* + * block numbers in the AG. + */ +#define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1)) +#define XFS_PREALLOC_BLOCKS(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1)) + + + +/* + * BMAP Btree format definitions + * + * This includes both the root block definition that sits inside an inode fork + * and the record/pointer formats for the leaf/node in the blocks. + */ +#define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */ +#define XFS_BMAP_CRC_MAGIC 0x424d4133 /* 'BMA3' */ + +/* + * Bmap root header, on-disk form only. + */ +typedef struct xfs_bmdr_block { + __be16 bb_level; /* 0 is a leaf */ + __be16 bb_numrecs; /* current # of data records */ +} xfs_bmdr_block_t; + +/* + * Bmap btree record and extent descriptor. + * l0:63 is an extent flag (value 1 indicates non-normal). + * l0:9-62 are startoff. + * l0:0-8 and l1:21-63 are startblock. + * l1:0-20 are blockcount. + */ +#define BMBT_EXNTFLAG_BITLEN 1 +#define BMBT_STARTOFF_BITLEN 54 +#define BMBT_STARTBLOCK_BITLEN 52 +#define BMBT_BLOCKCOUNT_BITLEN 21 + +typedef struct xfs_bmbt_rec { + __be64 l0, l1; +} xfs_bmbt_rec_t; + +typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */ +typedef xfs_bmbt_rec_t xfs_bmdr_rec_t; + +typedef struct xfs_bmbt_rec_host { + __uint64_t l0, l1; +} xfs_bmbt_rec_host_t; + +/* + * Values and macros for delayed-allocation startblock fields. + */ +#define STARTBLOCKVALBITS 17 +#define STARTBLOCKMASKBITS (15 + XFS_BIG_BLKNOS * 20) +#define DSTARTBLOCKMASKBITS (15 + 20) +#define STARTBLOCKMASK \ + (((((xfs_fsblock_t)1) << STARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS) +#define DSTARTBLOCKMASK \ + (((((xfs_dfsbno_t)1) << DSTARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS) + +static inline int isnullstartblock(xfs_fsblock_t x) +{ + return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK; +} + +static inline int isnulldstartblock(xfs_dfsbno_t x) +{ + return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK; +} + +static inline xfs_fsblock_t nullstartblock(int k) +{ + ASSERT(k < (1 << STARTBLOCKVALBITS)); + return STARTBLOCKMASK | (k); +} + +static inline xfs_filblks_t startblockval(xfs_fsblock_t x) +{ + return (xfs_filblks_t)((x) & ~STARTBLOCKMASK); +} + +/* + * Possible extent formats. + */ +typedef enum { + XFS_EXTFMT_NOSTATE = 0, + XFS_EXTFMT_HASSTATE +} xfs_exntfmt_t; + +/* + * Possible extent states. + */ +typedef enum { + XFS_EXT_NORM, XFS_EXT_UNWRITTEN, + XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID +} xfs_exntst_t; + +/* + * Incore version of above. + */ +typedef struct xfs_bmbt_irec +{ + xfs_fileoff_t br_startoff; /* starting file offset */ + xfs_fsblock_t br_startblock; /* starting block number */ + xfs_filblks_t br_blockcount; /* number of blocks */ + xfs_exntst_t br_state; /* extent state */ +} xfs_bmbt_irec_t; + +/* + * Key structure for non-leaf levels of the tree. + */ +typedef struct xfs_bmbt_key { + __be64 br_startoff; /* starting file offset */ +} xfs_bmbt_key_t, xfs_bmdr_key_t; + +/* btree pointer type */ +typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; + + +/* + * Generic Btree block format definitions + * + * This is a combination of the actual format used on disk for short and long + * format btrees. The first three fields are shared by both format, but the + * pointers are different and should be used with care. + * + * To get the size of the actual short or long form headers please use the size + * macros below. Never use sizeof(xfs_btree_block). + * + * The blkno, crc, lsn, owner and uuid fields are only available in filesystems + * with the crc feature bit, and all accesses to them must be conditional on + * that flag. + */ +struct xfs_btree_block { + __be32 bb_magic; /* magic number for block type */ + __be16 bb_level; /* 0 is a leaf */ + __be16 bb_numrecs; /* current # of data records */ + union { + struct { + __be32 bb_leftsib; + __be32 bb_rightsib; + + __be64 bb_blkno; + __be64 bb_lsn; + uuid_t bb_uuid; + __be32 bb_owner; + __le32 bb_crc; + } s; /* short form pointers */ + struct { + __be64 bb_leftsib; + __be64 bb_rightsib; + + __be64 bb_blkno; + __be64 bb_lsn; + uuid_t bb_uuid; + __be64 bb_owner; + __le32 bb_crc; + __be32 bb_pad; /* padding for alignment */ + } l; /* long form pointers */ + } bb_u; /* rest */ +}; + +#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */ +#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */ + +/* sizes of CRC enabled btree blocks */ +#define XFS_BTREE_SBLOCK_CRC_LEN (XFS_BTREE_SBLOCK_LEN + 40) +#define XFS_BTREE_LBLOCK_CRC_LEN (XFS_BTREE_LBLOCK_LEN + 48) + +#define XFS_BTREE_SBLOCK_CRC_OFF \ + offsetof(struct xfs_btree_block, bb_u.s.bb_crc) +#define XFS_BTREE_LBLOCK_CRC_OFF \ + offsetof(struct xfs_btree_block, bb_u.l.bb_crc) + #endif /* __XFS_FORMAT_H__ */ diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index ceaec3165921..a6e54b3319bd 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -18,30 +18,28 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" -#include "xfs_log_format.h" #include "xfs_format.h" +#include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" -#include "xfs_btree.h" #include "xfs_error.h" +#include "xfs_btree.h" +#include "xfs_alloc_btree.h" #include "xfs_alloc.h" #include "xfs_ialloc.h" #include "xfs_fsops.h" #include "xfs_itable.h" #include "xfs_trans_space.h" #include "xfs_rtalloc.h" -#include "xfs_filestream.h" #include "xfs_trace.h" #include "xfs_log.h" +#include "xfs_dinode.h" +#include "xfs_filestream.h" /* * File system operations diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index c973ff8c4a7c..14d732f61a41 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -26,13 +26,10 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_ialloc.h" +#include "xfs_ialloc_btree.h" #include "xfs_alloc.h" #include "xfs_rtalloc.h" #include "xfs_error.h" @@ -42,6 +39,7 @@ #include "xfs_buf_item.h" #include "xfs_icreate_item.h" #include "xfs_icache.h" +#include "xfs_dinode.h" /* diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h index 155779803d67..a8f76a5ff418 100644 --- a/fs/xfs/xfs_ialloc.h +++ b/fs/xfs/xfs_ialloc.h @@ -23,6 +23,7 @@ struct xfs_dinode; struct xfs_imap; struct xfs_mount; struct xfs_trans; +struct xfs_btree_cur; /* * Allocation parameters for inode allocation. @@ -42,7 +43,7 @@ struct xfs_trans; static inline struct xfs_dinode * xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o) { - return (xfs_dinode_t *) + return (struct xfs_dinode *) (xfs_buf_offset(b, o << (mp)->m_sb.sb_inodelog)); } diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c index 2a0b6158e4c4..1fa142dc86cb 100644 --- a/fs/xfs/xfs_ialloc_btree.c +++ b/fs/xfs/xfs_ialloc_btree.c @@ -17,19 +17,17 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_ialloc.h" +#include "xfs_ialloc_btree.h" #include "xfs_alloc.h" #include "xfs_error.h" #include "xfs_trace.h" diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h index cfbfe461abbc..f38b22011c4e 100644 --- a/fs/xfs/xfs_ialloc_btree.h +++ b/fs/xfs/xfs_ialloc_btree.h @@ -26,55 +26,6 @@ struct xfs_buf; struct xfs_btree_cur; struct xfs_mount; -/* - * There is a btree for the inode map per allocation group. - */ -#define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */ -#define XFS_IBT_CRC_MAGIC 0x49414233 /* 'IAB3' */ - -typedef __uint64_t xfs_inofree_t; -#define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t)) -#define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3) -#define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) -#define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i)) - -static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) -{ - return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i; -} - -/* - * Data record structure - */ -typedef struct xfs_inobt_rec { - __be32 ir_startino; /* starting inode number */ - __be32 ir_freecount; /* count of free inodes (set bits) */ - __be64 ir_free; /* free inode mask */ -} xfs_inobt_rec_t; - -typedef struct xfs_inobt_rec_incore { - xfs_agino_t ir_startino; /* starting inode number */ - __int32_t ir_freecount; /* count of free inodes (set bits) */ - xfs_inofree_t ir_free; /* free inode mask */ -} xfs_inobt_rec_incore_t; - - -/* - * Key structure - */ -typedef struct xfs_inobt_key { - __be32 ir_startino; /* starting inode number */ -} xfs_inobt_key_t; - -/* btree pointer type */ -typedef __be32 xfs_inobt_ptr_t; - -/* - * block numbers in the AG. - */ -#define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1)) -#define XFS_PREALLOC_BLOCKS(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1)) - /* * Btree block header size depends on a superblock flag. */ diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 6db11556731d..98d35244eecc 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -24,17 +24,13 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" #include "xfs_inode.h" -#include "xfs_dinode.h" #include "xfs_error.h" -#include "xfs_filestream.h" #include "xfs_trans.h" #include "xfs_trans_priv.h" #include "xfs_inode_item.h" #include "xfs_quota.h" #include "xfs_trace.h" -#include "xfs_fsops.h" #include "xfs_icache.h" #include "xfs_bmap_util.h" diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index f0440dcb5d8c..326b94dbe159 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -27,27 +27,22 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_inode.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_dir2.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" #include "xfs_attr_sf.h" #include "xfs_attr.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" #include "xfs_trans_space.h" #include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_inode_item.h" -#include "xfs_btree.h" -#include "xfs_alloc.h" #include "xfs_ialloc.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" #include "xfs_error.h" #include "xfs_quota.h" +#include "xfs_dinode.h" #include "xfs_filestream.h" #include "xfs_cksum.h" #include "xfs_trace.h" @@ -55,6 +50,7 @@ #include "xfs_symlink.h" #include "xfs_trans_priv.h" #include "xfs_log.h" +#include "xfs_bmap_btree.h" kmem_zone_t *xfs_inode_zone; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index cce62ce1a73a..66675877f38c 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -24,7 +24,6 @@ /* * Kernel only inode definitions */ - struct xfs_dinode; struct xfs_inode; struct xfs_buf; diff --git a/fs/xfs/xfs_inode_buf.c b/fs/xfs/xfs_inode_buf.c index c0f974b6cd46..4fc9f39dd89e 100644 --- a/fs/xfs/xfs_inode_buf.c +++ b/fs/xfs/xfs_inode_buf.c @@ -24,15 +24,13 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_error.h" #include "xfs_cksum.h" #include "xfs_icache.h" -#include "xfs_ialloc.h" #include "xfs_trans.h" +#include "xfs_ialloc.h" +#include "xfs_dinode.h" /* * Check that none of the inode's in the buffer have a next diff --git a/fs/xfs/xfs_inode_fork.c b/fs/xfs/xfs_inode_fork.c index b89b58a3a350..22c9837c5d4b 100644 --- a/fs/xfs/xfs_inode_fork.c +++ b/fs/xfs/xfs_inode_fork.c @@ -26,25 +26,15 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_attr_sf.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" -#include "xfs_buf_item.h" #include "xfs_inode_item.h" -#include "xfs_btree.h" -#include "xfs_alloc.h" -#include "xfs_ialloc.h" +#include "xfs_bmap_btree.h" #include "xfs_bmap.h" #include "xfs_error.h" -#include "xfs_quota.h" -#include "xfs_filestream.h" -#include "xfs_cksum.h" #include "xfs_trace.h" -#include "xfs_icache.h" +#include "xfs_attr_sf.h" +#include "xfs_dinode.h" kmem_zone_t *xfs_ifork_zone; diff --git a/fs/xfs/xfs_inode_fork.h b/fs/xfs/xfs_inode_fork.h index 28661a0d9058..eb329a1ea888 100644 --- a/fs/xfs/xfs_inode_fork.h +++ b/fs/xfs/xfs_inode_fork.h @@ -19,6 +19,7 @@ #define __XFS_INODE_FORK_H__ struct xfs_inode_log_item; +struct xfs_dinode; /* * The following xfs_ext_irec_t struct introduces a second (top) level diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 9f8e85ef2681..7c0d391f9a6e 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -17,19 +17,19 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" #include "xfs_error.h" #include "xfs_trace.h" #include "xfs_trans_priv.h" +#include "xfs_dinode.h" kmem_zone_t *xfs_ili_zone; /* inode log item zone */ diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index ea65a73d49ba..4d613401a5e0 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -23,28 +23,25 @@ #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_alloc.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_ioctl.h" +#include "xfs_alloc.h" #include "xfs_rtalloc.h" #include "xfs_itable.h" #include "xfs_error.h" #include "xfs_attr.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" -#include "xfs_trans.h" -#include "xfs_buf_item.h" #include "xfs_fsops.h" #include "xfs_discard.h" #include "xfs_quota.h" -#include "xfs_inode_item.h" #include "xfs_export.h" #include "xfs_trace.h" #include "xfs_icache.h" #include "xfs_symlink.h" +#include "xfs_dinode.h" +#include "xfs_trans.h" #include #include diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index 1be3333b260c..e8fb1231db81 100644 --- a/fs/xfs/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c @@ -22,14 +22,13 @@ #include #include "xfs.h" #include "xfs_fs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" #include "xfs_vnode.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_itable.h" #include "xfs_error.h" diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index adadf80709b8..22d1cbea283d 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -24,29 +24,21 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_trans.h" -#include "xfs_inode_item.h" -#include "xfs_alloc.h" -#include "xfs_quota.h" #include "xfs_btree.h" +#include "xfs_bmap_btree.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" -#include "xfs_rtalloc.h" #include "xfs_error.h" -#include "xfs_itable.h" -#include "xfs_attr.h" -#include "xfs_buf_item.h" +#include "xfs_trans.h" #include "xfs_trans_space.h" #include "xfs_iomap.h" #include "xfs_trace.h" #include "xfs_icache.h" +#include "xfs_quota.h" #include "xfs_dquot_item.h" #include "xfs_dquot.h" +#include "xfs_dinode.h" #define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 3f2ae19c8ca0..718b62b0fe05 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -25,26 +25,20 @@ #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_da_format.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" #include "xfs_acl.h" -#include "xfs_alloc.h" #include "xfs_quota.h" -#include "xfs_rtalloc.h" #include "xfs_error.h" -#include "xfs_itable.h" #include "xfs_attr.h" #include "xfs_trans.h" -#include "xfs_buf_item.h" -#include "xfs_inode_item.h" #include "xfs_trace.h" #include "xfs_icache.h" #include "xfs_symlink.h" #include "xfs_da_btree.h" #include "xfs_dir2_priv.h" +#include "xfs_dinode.h" #include #include diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 964b1caae085..c237ad15d500 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -18,23 +18,22 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_inum.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" +#include "xfs_btree.h" #include "xfs_ialloc.h" +#include "xfs_ialloc_btree.h" #include "xfs_itable.h" #include "xfs_error.h" -#include "xfs_btree.h" #include "xfs_trace.h" #include "xfs_icache.h" +#include "xfs_dinode.h" STATIC int xfs_internal_inum( diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 5275ad886971..e523396753c5 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" @@ -28,12 +29,7 @@ #include "xfs_trans_priv.h" #include "xfs_log.h" #include "xfs_log_priv.h" -#include "xfs_buf_item.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" #include "xfs_log_recover.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trace.h" #include "xfs_fsops.h" diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 832ba5d5eb3a..b6b669df40f3 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -27,29 +27,23 @@ #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_da_format.h" -#include "xfs_error.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" -#include "xfs_inode_item.h" -#include "xfs_alloc.h" -#include "xfs_ialloc.h" #include "xfs_log.h" #include "xfs_log_priv.h" #include "xfs_log_recover.h" +#include "xfs_inode_item.h" #include "xfs_extfree_item.h" #include "xfs_trans_priv.h" +#include "xfs_alloc.h" +#include "xfs_ialloc.h" #include "xfs_quota.h" #include "xfs_cksum.h" #include "xfs_trace.h" #include "xfs_icache.h" - -/* Need all the magic numbers and buffer ops structures from these headers */ -#include "xfs_da_btree.h" +#include "xfs_bmap_btree.h" +#include "xfs_dinode.h" +#include "xfs_error.h" #include "xfs_dir2.h" #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) diff --git a/fs/xfs/xfs_log_rlimit.c b/fs/xfs/xfs_log_rlimit.c index 3749bc1c00a4..2af1a0a4d0f1 100644 --- a/fs/xfs/xfs_log_rlimit.c +++ b/fs/xfs/xfs_log_rlimit.c @@ -18,6 +18,7 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_ag.h" @@ -25,10 +26,10 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_trans_space.h" -#include "xfs_bmap_btree.h" #include "xfs_inode.h" #include "xfs_da_btree.h" #include "xfs_attr_leaf.h" +#include "xfs_bmap_btree.h" /* * Calculate the maximum length in bytes that would be required for a local diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 83f7810c53cd..da88f167af78 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -27,27 +27,20 @@ #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_da_format.h" -#include "xfs_trans.h" -#include "xfs_trans_priv.h" -#include "xfs_log.h" -#include "xfs_dir2.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_btree.h" +#include "xfs_dir2.h" #include "xfs_ialloc.h" #include "xfs_alloc.h" #include "xfs_rtalloc.h" #include "xfs_bmap.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" +#include "xfs_log.h" #include "xfs_error.h" #include "xfs_quota.h" #include "xfs_fsops.h" #include "xfs_trace.h" #include "xfs_icache.h" -#include "xfs_cksum.h" -#include "xfs_buf_item.h" #ifdef HAVE_PERCPU_SB diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index e2f675644b4d..14a4996cfec6 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -17,33 +17,28 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" -#include "xfs_shared.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_ialloc.h" #include "xfs_itable.h" -#include "xfs_alloc.h" -#include "xfs_rtalloc.h" #include "xfs_quota.h" #include "xfs_error.h" #include "xfs_bmap.h" -#include "xfs_attr.h" +#include "xfs_bmap_btree.h" #include "xfs_trans.h" -#include "xfs_buf_item.h" #include "xfs_trans_space.h" #include "xfs_qm.h" #include "xfs_trace.h" #include "xfs_icache.h" #include "xfs_cksum.h" +#include "xfs_dinode.h" /* * The global quota manager. There is only one of these for the entire diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c index 704628961159..e9be63abd8d2 100644 --- a/fs/xfs/xfs_qm_bhv.c +++ b/fs/xfs/xfs_qm_bhv.c @@ -22,18 +22,11 @@ #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_alloc.h" #include "xfs_quota.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" #include "xfs_inode.h" -#include "xfs_itable.h" -#include "xfs_bmap.h" -#include "xfs_rtalloc.h" #include "xfs_error.h" -#include "xfs_attr.h" #include "xfs_trans.h" -#include "xfs_buf_item.h" #include "xfs_qm.h" diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index ab2326aaaeda..437c9198031a 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c @@ -27,19 +27,11 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_alloc.h" -#include "xfs_quota.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" #include "xfs_inode.h" #include "xfs_trans.h" -#include "xfs_inode_item.h" -#include "xfs_itable.h" -#include "xfs_bmap.h" -#include "xfs_rtalloc.h" #include "xfs_error.h" -#include "xfs_attr.h" -#include "xfs_buf_item.h" +#include "xfs_quota.h" #include "xfs_qm.h" #include "xfs_trace.h" #include "xfs_icache.h" diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c index 2dd467b0b475..af33cafe69b6 100644 --- a/fs/xfs/xfs_quotaops.c +++ b/fs/xfs/xfs_quotaops.c @@ -22,10 +22,9 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" +#include "xfs_inode.h" #include "xfs_quota.h" #include "xfs_trans.h" -#include "xfs_bmap_btree.h" -#include "xfs_inode.h" #include "xfs_qm.h" #include diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 23c5ca24a02d..d5da15578185 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -25,21 +25,18 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_alloc.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" -#include "xfs_rtalloc.h" -#include "xfs_fsops.h" +#include "xfs_bmap_btree.h" +#include "xfs_alloc.h" #include "xfs_error.h" #include "xfs_trans.h" -#include "xfs_inode_item.h" #include "xfs_trans_space.h" #include "xfs_trace.h" #include "xfs_buf.h" #include "xfs_icache.h" +#include "xfs_dinode.h" /* diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index 1b0a6420f1b8..05b5493d2baa 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -21,31 +21,21 @@ #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" -#include "xfs_inum.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_da_format.h" -#include "xfs_da_btree.h" -#include "xfs_dir2.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_btree.h" #include "xfs_ialloc.h" #include "xfs_alloc.h" -#include "xfs_rtalloc.h" -#include "xfs_bmap.h" #include "xfs_error.h" -#include "xfs_quota.h" -#include "xfs_fsops.h" #include "xfs_trace.h" #include "xfs_cksum.h" #include "xfs_trans.h" -#include "xfs_trans_priv.h" #include "xfs_buf_item.h" +#include "xfs_dinode.h" +#include "xfs_bmap_btree.h" +#include "xfs_alloc_btree.h" +#include "xfs_ialloc_btree.h" /* * Physical superblock buffer manipulations. Shared with libxfs in userspace. diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 4e20b420ff72..4eb63ad87d7d 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -24,29 +24,18 @@ #include "xfs_inum.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_alloc.h" -#include "xfs_quota.h" #include "xfs_mount.h" #include "xfs_da_format.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_btree.h" -#include "xfs_ialloc.h" #include "xfs_bmap.h" -#include "xfs_rtalloc.h" +#include "xfs_alloc.h" #include "xfs_error.h" -#include "xfs_itable.h" #include "xfs_fsops.h" -#include "xfs_attr.h" #include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_log.h" #include "xfs_log_priv.h" -#include "xfs_trans_priv.h" -#include "xfs_filestream.h" #include "xfs_da_btree.h" #include "xfs_dir2.h" #include "xfs_extfree_item.h" @@ -55,6 +44,9 @@ #include "xfs_icache.h" #include "xfs_trace.h" #include "xfs_icreate_item.h" +#include "xfs_dinode.h" +#include "xfs_filestream.h" +#include "xfs_quota.h" #include #include diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 93fc72c96fad..14e58f2c96bd 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -28,13 +28,11 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_dir2.h" -#include "xfs_bmap_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_ialloc.h" #include "xfs_alloc.h" #include "xfs_bmap.h" +#include "xfs_bmap_btree.h" #include "xfs_bmap_util.h" #include "xfs_error.h" #include "xfs_quota.h" @@ -42,8 +40,8 @@ #include "xfs_trace.h" #include "xfs_symlink.h" #include "xfs_trans.h" -#include "xfs_buf_item.h" #include "xfs_log.h" +#include "xfs_dinode.h" /* ----- Kernel only functions below ----- */ STATIC int diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c index 889bb4233323..dee3279c095e 100644 --- a/fs/xfs/xfs_trace.c +++ b/fs/xfs/xfs_trace.c @@ -25,10 +25,6 @@ #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_da_format.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_da_btree.h" @@ -49,6 +45,7 @@ #include "xfs_dquot.h" #include "xfs_log_recover.h" #include "xfs_inode_item.h" +#include "xfs_bmap_btree.h" /* * We include this last to have the helpers above available for the trace diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 8d1595f9fd50..c812c5c060de 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -25,28 +25,14 @@ #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_error.h" -#include "xfs_da_format.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_btree.h" -#include "xfs_ialloc.h" -#include "xfs_alloc.h" #include "xfs_extent_busy.h" -#include "xfs_bmap.h" #include "xfs_quota.h" #include "xfs_trans.h" #include "xfs_trans_priv.h" -#include "xfs_trans_space.h" -#include "xfs_qm.h" -#include "xfs_inode_item.h" #include "xfs_log.h" -#include "xfs_log_priv.h" -#include "xfs_buf_item.h" #include "xfs_trace.h" +#include "xfs_error.h" kmem_zone_t *xfs_trans_zone; kmem_zone_t *xfs_log_item_desc_zone; diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 9cc5fbed4f26..9b96d35e483d 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -234,6 +234,11 @@ void xfs_trans_cancel(xfs_trans_t *, int); int xfs_trans_ail_init(struct xfs_mount *); void xfs_trans_ail_destroy(struct xfs_mount *); +void xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *, + enum xfs_blft); +void xfs_trans_buf_copy_type(struct xfs_buf *dst_bp, + struct xfs_buf *src_bp); + extern kmem_zone_t *xfs_trans_zone; extern kmem_zone_t *xfs_log_item_desc_zone; diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 6b1b993257d6..c035d11b7734 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -18,15 +18,12 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_buf_item.h" diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index 2025f6eea4aa..cd2a10e15d3a 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -23,19 +23,12 @@ #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_alloc.h" -#include "xfs_quota.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" #include "xfs_inode.h" -#include "xfs_itable.h" -#include "xfs_bmap.h" -#include "xfs_rtalloc.h" #include "xfs_error.h" -#include "xfs_attr.h" #include "xfs_trans.h" -#include "xfs_buf_item.h" #include "xfs_trans_priv.h" +#include "xfs_quota.h" #include "xfs_qm.h" STATIC void xfs_trans_alloc_dqinfo(xfs_trans_t *); diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index b1a0efa6b32a..1bba7f60d94c 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c @@ -18,17 +18,13 @@ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_btree.h" #include "xfs_trans.h" #include "xfs_trans_priv.h" #include "xfs_inode_item.h" diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c index 89de046331da..d53d9f0627a7 100644 --- a/fs/xfs/xfs_trans_resv.c +++ b/fs/xfs/xfs_trans_resv.c @@ -26,19 +26,9 @@ #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_da_format.h" -#include "xfs_error.h" -#include "xfs_da_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_alloc_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_dinode.h" #include "xfs_inode.h" -#include "xfs_btree.h" +#include "xfs_bmap_btree.h" #include "xfs_ialloc.h" -#include "xfs_alloc.h" -#include "xfs_extent_busy.h" -#include "xfs_bmap.h" -#include "xfs_bmap_util.h" #include "xfs_quota.h" #include "xfs_trans.h" #include "xfs_qm.h" diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index 23052992c7e2..9d479073ba41 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -17,13 +17,13 @@ */ #include "xfs.h" +#include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_ag.h" #include "xfs_mount.h" #include "xfs_da_format.h" -#include "xfs_bmap_btree.h" #include "xfs_inode.h" #include "xfs_attr.h" #include "xfs_attr_leaf.h" -- cgit v1.2.3 From c963c6193a5adaec58044e238ef23516d04e5a74 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 15 Oct 2013 09:17:56 +1100 Subject: xfs: split xfs_rtalloc.c for userspace sanity xfs_rtalloc.c is partially shared with userspace. Split the file up into two parts - one that is kernel private and the other which is wholly shared with userspace. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/Makefile | 6 +- fs/xfs/xfs_rtalloc.c | 1845 ++++++++++++------------------------------------- fs/xfs/xfs_rtalloc.h | 24 + fs/xfs/xfs_rtbitmap.c | 973 ++++++++++++++++++++++++++ 4 files changed, 1446 insertions(+), 1402 deletions(-) create mode 100644 fs/xfs/xfs_rtbitmap.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 08f11bbf56ae..33a69fabfd83 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -104,7 +104,11 @@ xfs-$(CONFIG_XFS_QUOTA) += xfs_dquot.o \ xfs_qm_bhv.o \ xfs_qm.o \ xfs_quotaops.o -xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o + +# xfs_rtbitmap is shared with libxfs +xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o \ + xfs_rtbitmap.o + xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o xfs-$(CONFIG_PROC_FS) += xfs_stats.o xfs-$(CONFIG_SYSCTL) += xfs_sysctl.o diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index d5da15578185..a6a76b2b6a85 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -37,247 +37,336 @@ #include "xfs_buf.h" #include "xfs_icache.h" #include "xfs_dinode.h" +#include "xfs_rtalloc.h" /* - * Prototypes for internal functions. - */ - - -STATIC int xfs_rtallocate_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, - xfs_extlen_t, xfs_buf_t **, xfs_fsblock_t *); -STATIC int xfs_rtany_summary(xfs_mount_t *, xfs_trans_t *, int, int, - xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, int *); -STATIC int xfs_rtcheck_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, - xfs_extlen_t, int, xfs_rtblock_t *, int *); -STATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, - xfs_rtblock_t, xfs_rtblock_t *); -STATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, - xfs_rtblock_t, xfs_rtblock_t *); -STATIC int xfs_rtget_summary( xfs_mount_t *, xfs_trans_t *, int, - xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, xfs_suminfo_t *); -STATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, - xfs_extlen_t, int); -STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int, - xfs_rtblock_t, int, xfs_buf_t **, xfs_fsblock_t *); - -/* - * Internal functions. - */ - -/* - * Allocate space to the bitmap or summary file, and zero it, for growfs. + * Read and return the summary information for a given extent size, + * bitmap block combination. + * Keeps track of a current summary block, so we don't keep reading + * it from the buffer cache. */ STATIC int /* error */ -xfs_growfs_rt_alloc( - xfs_mount_t *mp, /* file system mount point */ - xfs_extlen_t oblocks, /* old count of blocks */ - xfs_extlen_t nblocks, /* new count of blocks */ - xfs_inode_t *ip) /* inode (bitmap/summary) */ +xfs_rtget_summary( + xfs_mount_t *mp, /* file system mount structure */ + xfs_trans_t *tp, /* transaction pointer */ + int log, /* log2 of extent size */ + xfs_rtblock_t bbno, /* bitmap block number */ + xfs_buf_t **rbpp, /* in/out: summary block buffer */ + xfs_fsblock_t *rsb, /* in/out: summary block number */ + xfs_suminfo_t *sum) /* out: summary info for this block */ { - xfs_fileoff_t bno; /* block number in file */ - xfs_buf_t *bp; /* temporary buffer for zeroing */ - int committed; /* transaction committed flag */ - xfs_daddr_t d; /* disk block address */ - int error; /* error return value */ - xfs_fsblock_t firstblock; /* first block allocated in xaction */ - xfs_bmap_free_t flist; /* list of freed blocks */ - xfs_fsblock_t fsbno; /* filesystem block for bno */ - xfs_bmbt_irec_t map; /* block map output */ - int nmap; /* number of block maps */ - int resblks; /* space reservation */ + xfs_buf_t *bp; /* buffer for summary block */ + int error; /* error value */ + xfs_fsblock_t sb; /* summary fsblock */ + int so; /* index into the summary file */ + xfs_suminfo_t *sp; /* pointer to returned data */ /* - * Allocate space to the file, as necessary. + * Compute entry number in the summary file. */ - while (oblocks < nblocks) { - int cancelflags = 0; - xfs_trans_t *tp; - - tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC); - resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks); - /* - * Reserve space & log for one extent added to the file. - */ - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growdata, - resblks, 0); - if (error) - goto error_cancel; - cancelflags = XFS_TRANS_RELEASE_LOG_RES; - /* - * Lock the inode. - */ - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - - xfs_bmap_init(&flist, &firstblock); - /* - * Allocate blocks to the bitmap file. - */ - nmap = 1; - cancelflags |= XFS_TRANS_ABORT; - error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks, - XFS_BMAPI_METADATA, &firstblock, - resblks, &map, &nmap, &flist); - if (!error && nmap < 1) - error = XFS_ERROR(ENOSPC); - if (error) - goto error_cancel; - /* - * Free any blocks freed up in the transaction, then commit. - */ - error = xfs_bmap_finish(&tp, &flist, &committed); - if (error) - goto error_cancel; - error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); - if (error) - goto error; + so = XFS_SUMOFFS(mp, log, bbno); + /* + * Compute the block number in the summary file. + */ + sb = XFS_SUMOFFSTOBLOCK(mp, so); + /* + * If we have an old buffer, and the block number matches, use that. + */ + if (rbpp && *rbpp && *rsb == sb) + bp = *rbpp; + /* + * Otherwise we have to get the buffer. + */ + else { /* - * Now we need to clear the allocated blocks. - * Do this one block per transaction, to keep it simple. + * If there was an old one, get rid of it first. */ - cancelflags = 0; - for (bno = map.br_startoff, fsbno = map.br_startblock; - bno < map.br_startoff + map.br_blockcount; - bno++, fsbno++) { - tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO); - /* - * Reserve log for one block zeroing. - */ - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero, - 0, 0); - if (error) - goto error_cancel; - /* - * Lock the bitmap inode. - */ - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - /* - * Get a buffer for the block. - */ - d = XFS_FSB_TO_DADDR(mp, fsbno); - bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, - mp->m_bsize, 0); - if (bp == NULL) { - error = XFS_ERROR(EIO); -error_cancel: - xfs_trans_cancel(tp, cancelflags); - goto error; - } - memset(bp->b_addr, 0, mp->m_sb.sb_blocksize); - xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); - /* - * Commit the transaction. - */ - error = xfs_trans_commit(tp, 0); - if (error) - goto error; + if (rbpp && *rbpp) + xfs_trans_brelse(tp, *rbpp); + error = xfs_rtbuf_get(mp, tp, sb, 1, &bp); + if (error) { + return error; } /* - * Go on to the next extent, if any. + * Remember this buffer and block for the next call. */ - oblocks = map.br_startoff + map.br_blockcount; + if (rbpp) { + *rbpp = bp; + *rsb = sb; + } } + /* + * Point to the summary information & copy it out. + */ + sp = XFS_SUMPTR(mp, bp, so); + *sum = *sp; + /* + * Drop the buffer if we're not asked to remember it. + */ + if (!rbpp) + xfs_trans_brelse(tp, bp); return 0; - -error: - return error; } + /* - * Attempt to allocate an extent minlen<=len<=maxlen starting from - * bitmap block bbno. If we don't get maxlen then use prod to trim - * the length, if given. Returns error; returns starting block in *rtblock. - * The lengths are all in rtextents. + * Return whether there are any free extents in the size range given + * by low and high, for the bitmap block bbno. */ STATIC int /* error */ -xfs_rtallocate_extent_block( - xfs_mount_t *mp, /* file system mount point */ +xfs_rtany_summary( + xfs_mount_t *mp, /* file system mount structure */ xfs_trans_t *tp, /* transaction pointer */ + int low, /* low log2 extent size */ + int high, /* high log2 extent size */ xfs_rtblock_t bbno, /* bitmap block number */ - xfs_extlen_t minlen, /* minimum length to allocate */ - xfs_extlen_t maxlen, /* maximum length to allocate */ - xfs_extlen_t *len, /* out: actual length allocated */ - xfs_rtblock_t *nextp, /* out: next block to try */ xfs_buf_t **rbpp, /* in/out: summary block buffer */ xfs_fsblock_t *rsb, /* in/out: summary block number */ - xfs_extlen_t prod, /* extent product factor */ - xfs_rtblock_t *rtblock) /* out: start block allocated */ + int *stat) /* out: any good extents here? */ { - xfs_rtblock_t besti; /* best rtblock found so far */ - xfs_rtblock_t bestlen; /* best length found so far */ - xfs_rtblock_t end; /* last rtblock in chunk */ int error; /* error value */ - xfs_rtblock_t i; /* current rtblock trying */ - xfs_rtblock_t next; /* next rtblock to try */ - int stat; /* status from internal calls */ + int log; /* loop counter, log2 of ext. size */ + xfs_suminfo_t sum; /* summary data */ /* - * Loop over all the extents starting in this bitmap block, - * looking for one that's long enough. + * Loop over logs of extent sizes. Order is irrelevant. */ - for (i = XFS_BLOCKTOBIT(mp, bbno), besti = -1, bestlen = 0, - end = XFS_BLOCKTOBIT(mp, bbno + 1) - 1; - i <= end; - i++) { + for (log = low; log <= high; log++) { /* - * See if there's a free extent of maxlen starting at i. - * If it's not so then next will contain the first non-free. + * Get one summary datum. */ - error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, &next, &stat); + error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum); if (error) { return error; } - if (stat) { - /* - * i for maxlen is all free, allocate and return that. - */ - error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp, - rsb); - if (error) { - return error; - } - *len = maxlen; - *rtblock = i; - return 0; - } /* - * In the case where we have a variable-sized allocation - * request, figure out how big this free piece is, - * and if it's big enough for the minimum, and the best - * so far, remember it. + * If there are any, return success. */ - if (minlen < maxlen) { - xfs_rtblock_t thislen; /* this extent size */ - - thislen = next - i; - if (thislen >= minlen && thislen > bestlen) { - besti = i; - bestlen = thislen; - } + if (sum) { + *stat = 1; + return 0; } - /* - * If not done yet, find the start of the next free space. - */ - if (next < end) { - error = xfs_rtfind_forw(mp, tp, next, end, &i); - if (error) { - return error; - } - } else - break; } /* - * Searched the whole thing & didn't find a maxlen free extent. + * Found nothing, return failure. */ - if (minlen < maxlen && besti != -1) { - xfs_extlen_t p; /* amount to trim length by */ + *stat = 0; + return 0; +} - /* - * If size should be a multiple of prod, make that so. - */ - if (prod > 1 && (p = do_mod(bestlen, prod))) + +/* + * Copy and transform the summary file, given the old and new + * parameters in the mount structures. + */ +STATIC int /* error */ +xfs_rtcopy_summary( + xfs_mount_t *omp, /* old file system mount point */ + xfs_mount_t *nmp, /* new file system mount point */ + xfs_trans_t *tp) /* transaction pointer */ +{ + xfs_rtblock_t bbno; /* bitmap block number */ + xfs_buf_t *bp; /* summary buffer */ + int error; /* error return value */ + int log; /* summary level number (log length) */ + xfs_suminfo_t sum; /* summary data */ + xfs_fsblock_t sumbno; /* summary block number */ + + bp = NULL; + for (log = omp->m_rsumlevels - 1; log >= 0; log--) { + for (bbno = omp->m_sb.sb_rbmblocks - 1; + (xfs_srtblock_t)bbno >= 0; + bbno--) { + error = xfs_rtget_summary(omp, tp, log, bbno, &bp, + &sumbno, &sum); + if (error) + return error; + if (sum == 0) + continue; + error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum, + &bp, &sumbno); + if (error) + return error; + error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum, + &bp, &sumbno); + if (error) + return error; + ASSERT(sum > 0); + } + } + return 0; +} +/* + * Mark an extent specified by start and len allocated. + * Updates all the summary information as well as the bitmap. + */ +STATIC int /* error */ +xfs_rtallocate_range( + xfs_mount_t *mp, /* file system mount point */ + xfs_trans_t *tp, /* transaction pointer */ + xfs_rtblock_t start, /* start block to allocate */ + xfs_extlen_t len, /* length to allocate */ + xfs_buf_t **rbpp, /* in/out: summary block buffer */ + xfs_fsblock_t *rsb) /* in/out: summary block number */ +{ + xfs_rtblock_t end; /* end of the allocated extent */ + int error; /* error value */ + xfs_rtblock_t postblock = 0; /* first block allocated > end */ + xfs_rtblock_t preblock = 0; /* first block allocated < start */ + + end = start + len - 1; + /* + * Assume we're allocating out of the middle of a free extent. + * We need to find the beginning and end of the extent so we can + * properly update the summary. + */ + error = xfs_rtfind_back(mp, tp, start, 0, &preblock); + if (error) { + return error; + } + /* + * Find the next allocated block (end of free extent). + */ + error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, + &postblock); + if (error) { + return error; + } + /* + * Decrement the summary information corresponding to the entire + * (old) free extent. + */ + error = xfs_rtmodify_summary(mp, tp, + XFS_RTBLOCKLOG(postblock + 1 - preblock), + XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); + if (error) { + return error; + } + /* + * If there are blocks not being allocated at the front of the + * old extent, add summary data for them to be free. + */ + if (preblock < start) { + error = xfs_rtmodify_summary(mp, tp, + XFS_RTBLOCKLOG(start - preblock), + XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); + if (error) { + return error; + } + } + /* + * If there are blocks not being allocated at the end of the + * old extent, add summary data for them to be free. + */ + if (postblock > end) { + error = xfs_rtmodify_summary(mp, tp, + XFS_RTBLOCKLOG(postblock - end), + XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb); + if (error) { + return error; + } + } + /* + * Modify the bitmap to mark this extent allocated. + */ + error = xfs_rtmodify_range(mp, tp, start, len, 0); + return error; +} + +/* + * Attempt to allocate an extent minlen<=len<=maxlen starting from + * bitmap block bbno. If we don't get maxlen then use prod to trim + * the length, if given. Returns error; returns starting block in *rtblock. + * The lengths are all in rtextents. + */ +STATIC int /* error */ +xfs_rtallocate_extent_block( + xfs_mount_t *mp, /* file system mount point */ + xfs_trans_t *tp, /* transaction pointer */ + xfs_rtblock_t bbno, /* bitmap block number */ + xfs_extlen_t minlen, /* minimum length to allocate */ + xfs_extlen_t maxlen, /* maximum length to allocate */ + xfs_extlen_t *len, /* out: actual length allocated */ + xfs_rtblock_t *nextp, /* out: next block to try */ + xfs_buf_t **rbpp, /* in/out: summary block buffer */ + xfs_fsblock_t *rsb, /* in/out: summary block number */ + xfs_extlen_t prod, /* extent product factor */ + xfs_rtblock_t *rtblock) /* out: start block allocated */ +{ + xfs_rtblock_t besti; /* best rtblock found so far */ + xfs_rtblock_t bestlen; /* best length found so far */ + xfs_rtblock_t end; /* last rtblock in chunk */ + int error; /* error value */ + xfs_rtblock_t i; /* current rtblock trying */ + xfs_rtblock_t next; /* next rtblock to try */ + int stat; /* status from internal calls */ + + /* + * Loop over all the extents starting in this bitmap block, + * looking for one that's long enough. + */ + for (i = XFS_BLOCKTOBIT(mp, bbno), besti = -1, bestlen = 0, + end = XFS_BLOCKTOBIT(mp, bbno + 1) - 1; + i <= end; + i++) { + /* + * See if there's a free extent of maxlen starting at i. + * If it's not so then next will contain the first non-free. + */ + error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, &next, &stat); + if (error) { + return error; + } + if (stat) { + /* + * i for maxlen is all free, allocate and return that. + */ + error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp, + rsb); + if (error) { + return error; + } + *len = maxlen; + *rtblock = i; + return 0; + } + /* + * In the case where we have a variable-sized allocation + * request, figure out how big this free piece is, + * and if it's big enough for the minimum, and the best + * so far, remember it. + */ + if (minlen < maxlen) { + xfs_rtblock_t thislen; /* this extent size */ + + thislen = next - i; + if (thislen >= minlen && thislen > bestlen) { + besti = i; + bestlen = thislen; + } + } + /* + * If not done yet, find the start of the next free space. + */ + if (next < end) { + error = xfs_rtfind_forw(mp, tp, next, end, &i); + if (error) { + return error; + } + } else + break; + } + /* + * Searched the whole thing & didn't find a maxlen free extent. + */ + if (minlen < maxlen && besti != -1) { + xfs_extlen_t p; /* amount to trim length by */ + + /* + * If size should be a multiple of prod, make that so. + */ + if (prod > 1 && (p = do_mod(bestlen, prod))) bestlen -= p; /* * Allocate besti for bestlen & return that. @@ -638,1191 +727,205 @@ xfs_rtallocate_extent_size( */ if (r != NULLRTBLOCK) { *rtblock = r; - return 0; - } - /* - * If the "next block to try" returned from the - * allocator is beyond the next bitmap block, - * skip to that bitmap block. - */ - if (XFS_BITTOBLOCK(mp, n) > i + 1) - i = XFS_BITTOBLOCK(mp, n) - 1; - } - } - /* - * Didn't find any maxlen blocks. Try smaller ones, unless - * we're asking for a fixed size extent. - */ - if (minlen > --maxlen) { - *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 - * to succeed. - */ - for (l = xfs_highbit32(maxlen); l >= xfs_highbit32(minlen); l--) { - /* - * Loop over all the bitmap blocks, try an allocation - * starting in that block. - */ - for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) { - /* - * Get the summary information for this level/block. - */ - error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb, - &sum); - if (error) { - return error; - } - /* - * If nothing there, go on to next. - */ - if (!sum) - continue; - /* - * Try the allocation. Make sure the specified - * minlen/maxlen are in the possible range for - * this summary level. - */ - error = xfs_rtallocate_extent_block(mp, tp, i, - XFS_RTMAX(minlen, 1 << l), - XFS_RTMIN(maxlen, (1 << (l + 1)) - 1), - len, &n, rbpp, rsb, prod, &r); - if (error) { - return error; - } - /* - * If it worked, return that extent. - */ - if (r != NULLRTBLOCK) { - *rtblock = r; - return 0; - } - /* - * If the "next block to try" returned from the - * allocator is beyond the next bitmap block, - * skip to that bitmap block. - */ - if (XFS_BITTOBLOCK(mp, n) > i + 1) - i = XFS_BITTOBLOCK(mp, n) - 1; - } - } - /* - * Got nothing, return failure. - */ - *rtblock = NULLRTBLOCK; - return 0; -} - -/* - * Mark an extent specified by start and len allocated. - * Updates all the summary information as well as the bitmap. - */ -STATIC int /* error */ -xfs_rtallocate_range( - xfs_mount_t *mp, /* file system mount point */ - xfs_trans_t *tp, /* transaction pointer */ - xfs_rtblock_t start, /* start block to allocate */ - xfs_extlen_t len, /* length to allocate */ - xfs_buf_t **rbpp, /* in/out: summary block buffer */ - xfs_fsblock_t *rsb) /* in/out: summary block number */ -{ - xfs_rtblock_t end; /* end of the allocated extent */ - int error; /* error value */ - xfs_rtblock_t postblock = 0; /* first block allocated > end */ - xfs_rtblock_t preblock = 0; /* first block allocated < start */ - - end = start + len - 1; - /* - * Assume we're allocating out of the middle of a free extent. - * We need to find the beginning and end of the extent so we can - * properly update the summary. - */ - error = xfs_rtfind_back(mp, tp, start, 0, &preblock); - if (error) { - return error; - } - /* - * Find the next allocated block (end of free extent). - */ - error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, - &postblock); - if (error) { - return error; - } - /* - * Decrement the summary information corresponding to the entire - * (old) free extent. - */ - error = xfs_rtmodify_summary(mp, tp, - XFS_RTBLOCKLOG(postblock + 1 - preblock), - XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); - if (error) { - return error; - } - /* - * If there are blocks not being allocated at the front of the - * old extent, add summary data for them to be free. - */ - if (preblock < start) { - error = xfs_rtmodify_summary(mp, tp, - XFS_RTBLOCKLOG(start - preblock), - XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); - if (error) { - return error; - } - } - /* - * If there are blocks not being allocated at the end of the - * old extent, add summary data for them to be free. - */ - if (postblock > end) { - error = xfs_rtmodify_summary(mp, tp, - XFS_RTBLOCKLOG(postblock - end), - XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb); - if (error) { - return error; - } - } - /* - * Modify the bitmap to mark this extent allocated. - */ - error = xfs_rtmodify_range(mp, tp, start, len, 0); - return error; -} - -/* - * Return whether there are any free extents in the size range given - * by low and high, for the bitmap block bbno. - */ -STATIC int /* error */ -xfs_rtany_summary( - xfs_mount_t *mp, /* file system mount structure */ - xfs_trans_t *tp, /* transaction pointer */ - int low, /* low log2 extent size */ - int high, /* high log2 extent size */ - xfs_rtblock_t bbno, /* bitmap block number */ - xfs_buf_t **rbpp, /* in/out: summary block buffer */ - xfs_fsblock_t *rsb, /* in/out: summary block number */ - int *stat) /* out: any good extents here? */ -{ - int error; /* error value */ - int log; /* loop counter, log2 of ext. size */ - xfs_suminfo_t sum; /* summary data */ - - /* - * Loop over logs of extent sizes. Order is irrelevant. - */ - for (log = low; log <= high; log++) { - /* - * Get one summary datum. - */ - error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum); - if (error) { - return error; - } - /* - * If there are any, return success. - */ - if (sum) { - *stat = 1; - return 0; - } - } - /* - * Found nothing, return failure. - */ - *stat = 0; - return 0; -} - -/* - * Get a buffer for the bitmap or summary file block specified. - * The buffer is returned read and locked. - */ -STATIC int /* error */ -xfs_rtbuf_get( - xfs_mount_t *mp, /* file system mount structure */ - xfs_trans_t *tp, /* transaction pointer */ - xfs_rtblock_t block, /* block number in bitmap or summary */ - int issum, /* is summary not bitmap */ - xfs_buf_t **bpp) /* output: buffer for the block */ -{ - xfs_buf_t *bp; /* block buffer, result */ - xfs_inode_t *ip; /* bitmap or summary inode */ - xfs_bmbt_irec_t map; - int nmap = 1; - int error; /* error value */ - - ip = issum ? mp->m_rsumip : mp->m_rbmip; - - error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK); - if (error) - return error; - - ASSERT(map.br_startblock != NULLFSBLOCK); - error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, - XFS_FSB_TO_DADDR(mp, map.br_startblock), - mp->m_bsize, 0, &bp, NULL); - if (error) - return error; - ASSERT(!xfs_buf_geterror(bp)); - *bpp = bp; - return 0; -} - -#ifdef DEBUG -/* - * Check that the given extent (block range) is allocated already. - */ -STATIC int /* error */ -xfs_rtcheck_alloc_range( - xfs_mount_t *mp, /* file system mount point */ - xfs_trans_t *tp, /* transaction pointer */ - xfs_rtblock_t bno, /* starting block number of extent */ - xfs_extlen_t len, /* length of extent */ - int *stat) /* out: 1 for allocated, 0 for not */ -{ - xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */ - - return xfs_rtcheck_range(mp, tp, bno, len, 0, &new, stat); -} -#endif - -/* - * Check that the given range is either all allocated (val = 0) or - * all free (val = 1). - */ -STATIC int /* error */ -xfs_rtcheck_range( - xfs_mount_t *mp, /* file system mount point */ - xfs_trans_t *tp, /* transaction pointer */ - xfs_rtblock_t start, /* starting block number of extent */ - xfs_extlen_t len, /* length of extent */ - int val, /* 1 for free, 0 for allocated */ - xfs_rtblock_t *new, /* out: first block not matching */ - int *stat) /* out: 1 for matches, 0 for not */ -{ - xfs_rtword_t *b; /* current word in buffer */ - int bit; /* bit number in the word */ - xfs_rtblock_t block; /* bitmap block number */ - xfs_buf_t *bp; /* buf for the block */ - xfs_rtword_t *bufp; /* starting word in buffer */ - int error; /* error value */ - xfs_rtblock_t i; /* current bit number rel. to start */ - xfs_rtblock_t lastbit; /* last useful bit in word */ - xfs_rtword_t mask; /* mask of relevant bits for value */ - xfs_rtword_t wdiff; /* difference from wanted value */ - int word; /* word number in the buffer */ - - /* - * Compute starting bitmap block number - */ - block = XFS_BITTOBLOCK(mp, start); - /* - * Read the bitmap block. - */ - error = xfs_rtbuf_get(mp, tp, block, 0, &bp); - if (error) { - return error; - } - bufp = bp->b_addr; - /* - * Compute the starting word's address, and starting bit. - */ - word = XFS_BITTOWORD(mp, start); - b = &bufp[word]; - bit = (int)(start & (XFS_NBWORD - 1)); - /* - * 0 (allocated) => all zero's; 1 (free) => all one's. - */ - val = -val; - /* - * If not starting on a word boundary, deal with the first - * (partial) word. - */ - if (bit) { - /* - * Compute first bit not examined. - */ - lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); - /* - * Mask of relevant bits. - */ - mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; - /* - * Compute difference between actual and desired value. - */ - if ((wdiff = (*b ^ val) & mask)) { - /* - * Different, compute first wrong bit and return. - */ - xfs_trans_brelse(tp, bp); - i = XFS_RTLOBIT(wdiff) - bit; - *new = start + i; - *stat = 0; - return 0; - } - i = lastbit - bit; - /* - * Go on to next block if that's where the next word is - * and we need the next word. - */ - if (++word == XFS_BLOCKWSIZE(mp) && i < len) { - /* - * If done with this block, get the next one. - */ - xfs_trans_brelse(tp, bp); - error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); - if (error) { - return error; - } - b = bufp = bp->b_addr; - word = 0; - } else { - /* - * Go on to the next word in the buffer. - */ - b++; - } - } else { - /* - * Starting on a word boundary, no partial word. - */ - i = 0; - } - /* - * Loop over whole words in buffers. When we use up one buffer - * we move on to the next one. - */ - while (len - i >= XFS_NBWORD) { - /* - * Compute difference between actual and desired value. - */ - if ((wdiff = *b ^ val)) { - /* - * Different, compute first wrong bit and return. - */ - xfs_trans_brelse(tp, bp); - i += XFS_RTLOBIT(wdiff); - *new = start + i; - *stat = 0; - return 0; - } - i += XFS_NBWORD; - /* - * Go on to next block if that's where the next word is - * and we need the next word. - */ - if (++word == XFS_BLOCKWSIZE(mp) && i < len) { - /* - * If done with this block, get the next one. - */ - xfs_trans_brelse(tp, bp); - error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); - if (error) { - return error; - } - b = bufp = bp->b_addr; - word = 0; - } else { - /* - * Go on to the next word in the buffer. - */ - b++; - } - } - /* - * If not ending on a word boundary, deal with the last - * (partial) word. - */ - if ((lastbit = len - i)) { - /* - * Mask of relevant bits. - */ - mask = ((xfs_rtword_t)1 << lastbit) - 1; - /* - * Compute difference between actual and desired value. - */ - if ((wdiff = (*b ^ val) & mask)) { - /* - * Different, compute first wrong bit and return. - */ - xfs_trans_brelse(tp, bp); - i += XFS_RTLOBIT(wdiff); - *new = start + i; - *stat = 0; - return 0; - } else - i = len; - } - /* - * Successful, return. - */ - xfs_trans_brelse(tp, bp); - *new = start + i; - *stat = 1; - return 0; -} - -/* - * Copy and transform the summary file, given the old and new - * parameters in the mount structures. - */ -STATIC int /* error */ -xfs_rtcopy_summary( - xfs_mount_t *omp, /* old file system mount point */ - xfs_mount_t *nmp, /* new file system mount point */ - xfs_trans_t *tp) /* transaction pointer */ -{ - xfs_rtblock_t bbno; /* bitmap block number */ - xfs_buf_t *bp; /* summary buffer */ - int error; /* error return value */ - int log; /* summary level number (log length) */ - xfs_suminfo_t sum; /* summary data */ - xfs_fsblock_t sumbno; /* summary block number */ - - bp = NULL; - for (log = omp->m_rsumlevels - 1; log >= 0; log--) { - for (bbno = omp->m_sb.sb_rbmblocks - 1; - (xfs_srtblock_t)bbno >= 0; - bbno--) { - error = xfs_rtget_summary(omp, tp, log, bbno, &bp, - &sumbno, &sum); - if (error) - return error; - if (sum == 0) - continue; - error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum, - &bp, &sumbno); - if (error) - return error; - error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum, - &bp, &sumbno); - if (error) - return error; - ASSERT(sum > 0); - } - } - return 0; -} - -/* - * Searching backward from start to limit, find the first block whose - * allocated/free state is different from start's. - */ -STATIC int /* error */ -xfs_rtfind_back( - xfs_mount_t *mp, /* file system mount point */ - xfs_trans_t *tp, /* transaction pointer */ - xfs_rtblock_t start, /* starting block to look at */ - xfs_rtblock_t limit, /* last block to look at */ - xfs_rtblock_t *rtblock) /* out: start block found */ -{ - xfs_rtword_t *b; /* current word in buffer */ - int bit; /* bit number in the word */ - xfs_rtblock_t block; /* bitmap block number */ - xfs_buf_t *bp; /* buf for the block */ - xfs_rtword_t *bufp; /* starting word in buffer */ - int error; /* error value */ - xfs_rtblock_t firstbit; /* first useful bit in the word */ - xfs_rtblock_t i; /* current bit number rel. to start */ - xfs_rtblock_t len; /* length of inspected area */ - xfs_rtword_t mask; /* mask of relevant bits for value */ - xfs_rtword_t want; /* mask for "good" values */ - xfs_rtword_t wdiff; /* difference from wanted value */ - int word; /* word number in the buffer */ - - /* - * Compute and read in starting bitmap block for starting block. - */ - block = XFS_BITTOBLOCK(mp, start); - error = xfs_rtbuf_get(mp, tp, block, 0, &bp); - if (error) { - return error; - } - bufp = bp->b_addr; - /* - * Get the first word's index & point to it. - */ - word = XFS_BITTOWORD(mp, start); - b = &bufp[word]; - bit = (int)(start & (XFS_NBWORD - 1)); - len = start - limit + 1; - /* - * Compute match value, based on the bit at start: if 1 (free) - * then all-ones, else all-zeroes. - */ - want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0; - /* - * If the starting position is not word-aligned, deal with the - * partial word. - */ - if (bit < XFS_NBWORD - 1) { - /* - * Calculate first (leftmost) bit number to look at, - * and mask for all the relevant bits in this word. - */ - firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0); - mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) << - firstbit; - /* - * Calculate the difference between the value there - * and what we're looking for. - */ - if ((wdiff = (*b ^ want) & mask)) { - /* - * Different. Mark where we are and return. - */ - xfs_trans_brelse(tp, bp); - i = bit - XFS_RTHIBIT(wdiff); - *rtblock = start - i + 1; - return 0; - } - i = bit - firstbit + 1; - /* - * Go on to previous block if that's where the previous word is - * and we need the previous word. - */ - if (--word == -1 && i < len) { - /* - * If done with this block, get the previous one. - */ - xfs_trans_brelse(tp, bp); - error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); - if (error) { - return error; - } - bufp = bp->b_addr; - word = XFS_BLOCKWMASK(mp); - b = &bufp[word]; - } else { - /* - * Go on to the previous word in the buffer. - */ - b--; - } - } else { - /* - * Starting on a word boundary, no partial word. - */ - i = 0; - } - /* - * Loop over whole words in buffers. When we use up one buffer - * we move on to the previous one. - */ - while (len - i >= XFS_NBWORD) { - /* - * Compute difference between actual and desired value. - */ - if ((wdiff = *b ^ want)) { - /* - * Different, mark where we are and return. - */ - xfs_trans_brelse(tp, bp); - i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); - *rtblock = start - i + 1; - return 0; - } - i += XFS_NBWORD; - /* - * Go on to previous block if that's where the previous word is - * and we need the previous word. - */ - if (--word == -1 && i < len) { - /* - * If done with this block, get the previous one. - */ - xfs_trans_brelse(tp, bp); - error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); - if (error) { - return error; - } - bufp = bp->b_addr; - word = XFS_BLOCKWMASK(mp); - b = &bufp[word]; - } else { - /* - * Go on to the previous word in the buffer. - */ - b--; - } - } - /* - * If not ending on a word boundary, deal with the last - * (partial) word. - */ - if (len - i) { - /* - * Calculate first (leftmost) bit number to look at, - * and mask for all the relevant bits in this word. - */ - firstbit = XFS_NBWORD - (len - i); - mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit; - /* - * Compute difference between actual and desired value. - */ - if ((wdiff = (*b ^ want) & mask)) { - /* - * Different, mark where we are and return. - */ - xfs_trans_brelse(tp, bp); - i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); - *rtblock = start - i + 1; - return 0; - } else - i = len; - } - /* - * No match, return that we scanned the whole area. - */ - xfs_trans_brelse(tp, bp); - *rtblock = start - i + 1; - return 0; -} - -/* - * Searching forward from start to limit, find the first block whose - * allocated/free state is different from start's. - */ -STATIC int /* error */ -xfs_rtfind_forw( - xfs_mount_t *mp, /* file system mount point */ - xfs_trans_t *tp, /* transaction pointer */ - xfs_rtblock_t start, /* starting block to look at */ - xfs_rtblock_t limit, /* last block to look at */ - xfs_rtblock_t *rtblock) /* out: start block found */ -{ - xfs_rtword_t *b; /* current word in buffer */ - int bit; /* bit number in the word */ - xfs_rtblock_t block; /* bitmap block number */ - xfs_buf_t *bp; /* buf for the block */ - xfs_rtword_t *bufp; /* starting word in buffer */ - int error; /* error value */ - xfs_rtblock_t i; /* current bit number rel. to start */ - xfs_rtblock_t lastbit; /* last useful bit in the word */ - xfs_rtblock_t len; /* length of inspected area */ - xfs_rtword_t mask; /* mask of relevant bits for value */ - xfs_rtword_t want; /* mask for "good" values */ - xfs_rtword_t wdiff; /* difference from wanted value */ - int word; /* word number in the buffer */ - - /* - * Compute and read in starting bitmap block for starting block. - */ - block = XFS_BITTOBLOCK(mp, start); - error = xfs_rtbuf_get(mp, tp, block, 0, &bp); - if (error) { - return error; - } - bufp = bp->b_addr; - /* - * Get the first word's index & point to it. - */ - word = XFS_BITTOWORD(mp, start); - b = &bufp[word]; - bit = (int)(start & (XFS_NBWORD - 1)); - len = limit - start + 1; - /* - * Compute match value, based on the bit at start: if 1 (free) - * then all-ones, else all-zeroes. - */ - want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0; - /* - * If the starting position is not word-aligned, deal with the - * partial word. - */ - if (bit) { - /* - * Calculate last (rightmost) bit number to look at, - * and mask for all the relevant bits in this word. - */ - lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); - mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; - /* - * Calculate the difference between the value there - * and what we're looking for. - */ - if ((wdiff = (*b ^ want) & mask)) { - /* - * Different. Mark where we are and return. - */ - xfs_trans_brelse(tp, bp); - i = XFS_RTLOBIT(wdiff) - bit; - *rtblock = start + i - 1; - return 0; - } - i = lastbit - bit; - /* - * Go on to next block if that's where the next word is - * and we need the next word. - */ - if (++word == XFS_BLOCKWSIZE(mp) && i < len) { - /* - * If done with this block, get the previous one. - */ - xfs_trans_brelse(tp, bp); - error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); - if (error) { - return error; - } - b = bufp = bp->b_addr; - word = 0; - } else { - /* - * Go on to the previous word in the buffer. - */ - b++; - } - } else { - /* - * Starting on a word boundary, no partial word. - */ - i = 0; - } - /* - * Loop over whole words in buffers. When we use up one buffer - * we move on to the next one. - */ - while (len - i >= XFS_NBWORD) { - /* - * Compute difference between actual and desired value. - */ - if ((wdiff = *b ^ want)) { - /* - * Different, mark where we are and return. - */ - xfs_trans_brelse(tp, bp); - i += XFS_RTLOBIT(wdiff); - *rtblock = start + i - 1; - return 0; - } - i += XFS_NBWORD; - /* - * Go on to next block if that's where the next word is - * and we need the next word. - */ - if (++word == XFS_BLOCKWSIZE(mp) && i < len) { - /* - * If done with this block, get the next one. - */ - xfs_trans_brelse(tp, bp); - error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); - if (error) { - return error; - } - b = bufp = bp->b_addr; - word = 0; - } else { - /* - * Go on to the next word in the buffer. - */ - b++; - } - } - /* - * If not ending on a word boundary, deal with the last - * (partial) word. - */ - if ((lastbit = len - i)) { - /* - * Calculate mask for all the relevant bits in this word. - */ - mask = ((xfs_rtword_t)1 << lastbit) - 1; - /* - * Compute difference between actual and desired value. - */ - if ((wdiff = (*b ^ want) & mask)) { - /* - * Different, mark where we are and return. - */ - xfs_trans_brelse(tp, bp); - i += XFS_RTLOBIT(wdiff); - *rtblock = start + i - 1; - return 0; - } else - i = len; - } - /* - * No match, return that we scanned the whole area. - */ - xfs_trans_brelse(tp, bp); - *rtblock = start + i - 1; - return 0; -} - -/* - * Mark an extent specified by start and len freed. - * Updates all the summary information as well as the bitmap. - */ -STATIC int /* error */ -xfs_rtfree_range( - xfs_mount_t *mp, /* file system mount point */ - xfs_trans_t *tp, /* transaction pointer */ - xfs_rtblock_t start, /* starting block to free */ - xfs_extlen_t len, /* length to free */ - xfs_buf_t **rbpp, /* in/out: summary block buffer */ - xfs_fsblock_t *rsb) /* in/out: summary block number */ -{ - xfs_rtblock_t end; /* end of the freed extent */ - int error; /* error value */ - xfs_rtblock_t postblock; /* first block freed > end */ - xfs_rtblock_t preblock; /* first block freed < start */ - - end = start + len - 1; - /* - * Modify the bitmap to mark this extent freed. - */ - error = xfs_rtmodify_range(mp, tp, start, len, 1); - if (error) { - return error; - } - /* - * Assume we're freeing out of the middle of an allocated extent. - * We need to find the beginning and end of the extent so we can - * properly update the summary. - */ - error = xfs_rtfind_back(mp, tp, start, 0, &preblock); - if (error) { - return error; - } - /* - * Find the next allocated block (end of allocated extent). - */ - error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, - &postblock); - if (error) - return error; - /* - * If there are blocks not being freed at the front of the - * old extent, add summary data for them to be allocated. - */ - if (preblock < start) { - error = xfs_rtmodify_summary(mp, tp, - XFS_RTBLOCKLOG(start - preblock), - XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); - if (error) { - return error; - } - } - /* - * If there are blocks not being freed at the end of the - * old extent, add summary data for them to be allocated. - */ - if (postblock > end) { - error = xfs_rtmodify_summary(mp, tp, - XFS_RTBLOCKLOG(postblock - end), - XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb); - if (error) { - return error; - } - } - /* - * Increment the summary information corresponding to the entire - * (new) free extent. - */ - error = xfs_rtmodify_summary(mp, tp, - XFS_RTBLOCKLOG(postblock + 1 - preblock), - XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); - return error; -} - -/* - * Read and return the summary information for a given extent size, - * bitmap block combination. - * Keeps track of a current summary block, so we don't keep reading - * it from the buffer cache. - */ -STATIC int /* error */ -xfs_rtget_summary( - xfs_mount_t *mp, /* file system mount structure */ - xfs_trans_t *tp, /* transaction pointer */ - int log, /* log2 of extent size */ - xfs_rtblock_t bbno, /* bitmap block number */ - xfs_buf_t **rbpp, /* in/out: summary block buffer */ - xfs_fsblock_t *rsb, /* in/out: summary block number */ - xfs_suminfo_t *sum) /* out: summary info for this block */ -{ - xfs_buf_t *bp; /* buffer for summary block */ - int error; /* error value */ - xfs_fsblock_t sb; /* summary fsblock */ - int so; /* index into the summary file */ - xfs_suminfo_t *sp; /* pointer to returned data */ - - /* - * Compute entry number in the summary file. - */ - so = XFS_SUMOFFS(mp, log, bbno); - /* - * Compute the block number in the summary file. - */ - sb = XFS_SUMOFFSTOBLOCK(mp, so); - /* - * If we have an old buffer, and the block number matches, use that. - */ - if (rbpp && *rbpp && *rsb == sb) - bp = *rbpp; - /* - * Otherwise we have to get the buffer. - */ - else { - /* - * If there was an old one, get rid of it first. - */ - if (rbpp && *rbpp) - xfs_trans_brelse(tp, *rbpp); - error = xfs_rtbuf_get(mp, tp, sb, 1, &bp); - if (error) { - return error; - } - /* - * Remember this buffer and block for the next call. - */ - if (rbpp) { - *rbpp = bp; - *rsb = sb; - } - } - /* - * Point to the summary information & copy it out. - */ - sp = XFS_SUMPTR(mp, bp, so); - *sum = *sp; - /* - * Drop the buffer if we're not asked to remember it. - */ - if (!rbpp) - xfs_trans_brelse(tp, bp); - return 0; -} - -/* - * Set the given range of bitmap bits to the given value. - * Do whatever I/O and logging is required. - */ -STATIC int /* error */ -xfs_rtmodify_range( - xfs_mount_t *mp, /* file system mount point */ - xfs_trans_t *tp, /* transaction pointer */ - xfs_rtblock_t start, /* starting block to modify */ - xfs_extlen_t len, /* length of extent to modify */ - int val) /* 1 for free, 0 for allocated */ -{ - xfs_rtword_t *b; /* current word in buffer */ - int bit; /* bit number in the word */ - xfs_rtblock_t block; /* bitmap block number */ - xfs_buf_t *bp; /* buf for the block */ - xfs_rtword_t *bufp; /* starting word in buffer */ - int error; /* error value */ - xfs_rtword_t *first; /* first used word in the buffer */ - int i; /* current bit number rel. to start */ - int lastbit; /* last useful bit in word */ - xfs_rtword_t mask; /* mask o frelevant bits for value */ - int word; /* word number in the buffer */ - - /* - * Compute starting bitmap block number. - */ - block = XFS_BITTOBLOCK(mp, start); - /* - * Read the bitmap block, and point to its data. - */ - error = xfs_rtbuf_get(mp, tp, block, 0, &bp); - if (error) { - return error; + return 0; + } + /* + * If the "next block to try" returned from the + * allocator is beyond the next bitmap block, + * skip to that bitmap block. + */ + if (XFS_BITTOBLOCK(mp, n) > i + 1) + i = XFS_BITTOBLOCK(mp, n) - 1; + } } - bufp = bp->b_addr; - /* - * Compute the starting word's address, and starting bit. - */ - word = XFS_BITTOWORD(mp, start); - first = b = &bufp[word]; - bit = (int)(start & (XFS_NBWORD - 1)); /* - * 0 (allocated) => all zeroes; 1 (free) => all ones. + * Didn't find any maxlen blocks. Try smaller ones, unless + * we're asking for a fixed size extent. */ - val = -val; + if (minlen > --maxlen) { + *rtblock = NULLRTBLOCK; + return 0; + } + ASSERT(minlen != 0); + ASSERT(maxlen != 0); + /* - * If not starting on a word boundary, deal with the first - * (partial) word. + * Loop over sizes, from maxlen down to minlen. + * This time, when we do the allocations, allow smaller ones + * to succeed. */ - if (bit) { - /* - * Compute first bit not changed and mask of relevant bits. - */ - lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); - mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; - /* - * Set/clear the active bits. - */ - if (val) - *b |= mask; - else - *b &= ~mask; - i = lastbit - bit; + for (l = xfs_highbit32(maxlen); l >= xfs_highbit32(minlen); l--) { /* - * Go on to the next block if that's where the next word is - * and we need the next word. + * Loop over all the bitmap blocks, try an allocation + * starting in that block. */ - if (++word == XFS_BLOCKWSIZE(mp) && i < len) { + for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) { /* - * Log the changed part of this block. - * Get the next one. + * Get the summary information for this level/block. */ - xfs_trans_log_buf(tp, bp, - (uint)((char *)first - (char *)bufp), - (uint)((char *)b - (char *)bufp)); - error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); + error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb, + &sum); if (error) { return error; } - first = b = bufp = bp->b_addr; - word = 0; - } else { /* - * Go on to the next word in the buffer + * If nothing there, go on to next. */ - b++; - } - } else { - /* - * Starting on a word boundary, no partial word. - */ - i = 0; - } - /* - * Loop over whole words in buffers. When we use up one buffer - * we move on to the next one. - */ - while (len - i >= XFS_NBWORD) { - /* - * Set the word value correctly. - */ - *b = val; - i += XFS_NBWORD; - /* - * Go on to the next block if that's where the next word is - * and we need the next word. - */ - if (++word == XFS_BLOCKWSIZE(mp) && i < len) { + if (!sum) + continue; /* - * Log the changed part of this block. - * Get the next one. + * Try the allocation. Make sure the specified + * minlen/maxlen are in the possible range for + * this summary level. */ - xfs_trans_log_buf(tp, bp, - (uint)((char *)first - (char *)bufp), - (uint)((char *)b - (char *)bufp)); - error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); + error = xfs_rtallocate_extent_block(mp, tp, i, + XFS_RTMAX(minlen, 1 << l), + XFS_RTMIN(maxlen, (1 << (l + 1)) - 1), + len, &n, rbpp, rsb, prod, &r); if (error) { return error; } - first = b = bufp = bp->b_addr; - word = 0; - } else { /* - * Go on to the next word in the buffer + * If it worked, return that extent. + */ + if (r != NULLRTBLOCK) { + *rtblock = r; + return 0; + } + /* + * If the "next block to try" returned from the + * allocator is beyond the next bitmap block, + * skip to that bitmap block. */ - b++; + if (XFS_BITTOBLOCK(mp, n) > i + 1) + i = XFS_BITTOBLOCK(mp, n) - 1; } } /* - * If not ending on a word boundary, deal with the last - * (partial) word. - */ - if ((lastbit = len - i)) { - /* - * Compute a mask of relevant bits. - */ - bit = 0; - mask = ((xfs_rtword_t)1 << lastbit) - 1; - /* - * Set/clear the active bits. - */ - if (val) - *b |= mask; - else - *b &= ~mask; - b++; - } - /* - * Log any remaining changed bytes. + * Got nothing, return failure. */ - if (b > first) - xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp), - (uint)((char *)b - (char *)bufp - 1)); + *rtblock = NULLRTBLOCK; return 0; } /* - * Read and modify the summary information for a given extent size, - * bitmap block combination. - * Keeps track of a current summary block, so we don't keep reading - * it from the buffer cache. + * Allocate space to the bitmap or summary file, and zero it, for growfs. */ STATIC int /* error */ -xfs_rtmodify_summary( +xfs_growfs_rt_alloc( xfs_mount_t *mp, /* file system mount point */ - xfs_trans_t *tp, /* transaction pointer */ - int log, /* log2 of extent size */ - xfs_rtblock_t bbno, /* bitmap block number */ - int delta, /* change to make to summary info */ - xfs_buf_t **rbpp, /* in/out: summary block buffer */ - xfs_fsblock_t *rsb) /* in/out: summary block number */ + xfs_extlen_t oblocks, /* old count of blocks */ + xfs_extlen_t nblocks, /* new count of blocks */ + xfs_inode_t *ip) /* inode (bitmap/summary) */ { - xfs_buf_t *bp; /* buffer for the summary block */ - int error; /* error value */ - xfs_fsblock_t sb; /* summary fsblock */ - int so; /* index into the summary file */ - xfs_suminfo_t *sp; /* pointer to returned data */ + xfs_fileoff_t bno; /* block number in file */ + xfs_buf_t *bp; /* temporary buffer for zeroing */ + int committed; /* transaction committed flag */ + xfs_daddr_t d; /* disk block address */ + int error; /* error return value */ + xfs_fsblock_t firstblock; /* first block allocated in xaction */ + xfs_bmap_free_t flist; /* list of freed blocks */ + xfs_fsblock_t fsbno; /* filesystem block for bno */ + xfs_bmbt_irec_t map; /* block map output */ + int nmap; /* number of block maps */ + int resblks; /* space reservation */ /* - * Compute entry number in the summary file. - */ - so = XFS_SUMOFFS(mp, log, bbno); - /* - * Compute the block number in the summary file. - */ - sb = XFS_SUMOFFSTOBLOCK(mp, so); - /* - * If we have an old buffer, and the block number matches, use that. - */ - if (rbpp && *rbpp && *rsb == sb) - bp = *rbpp; - /* - * Otherwise we have to get the buffer. + * Allocate space to the file, as necessary. */ - else { + while (oblocks < nblocks) { + int cancelflags = 0; + xfs_trans_t *tp; + + tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC); + resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks); /* - * If there was an old one, get rid of it first. + * Reserve space & log for one extent added to the file. */ - if (rbpp && *rbpp) - xfs_trans_brelse(tp, *rbpp); - error = xfs_rtbuf_get(mp, tp, sb, 1, &bp); - if (error) { - return error; - } + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growdata, + resblks, 0); + if (error) + goto error_cancel; + cancelflags = XFS_TRANS_RELEASE_LOG_RES; /* - * Remember this buffer and block for the next call. + * Lock the inode. */ - if (rbpp) { - *rbpp = bp; - *rsb = sb; + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + + xfs_bmap_init(&flist, &firstblock); + /* + * Allocate blocks to the bitmap file. + */ + nmap = 1; + cancelflags |= XFS_TRANS_ABORT; + error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks, + XFS_BMAPI_METADATA, &firstblock, + resblks, &map, &nmap, &flist); + if (!error && nmap < 1) + error = XFS_ERROR(ENOSPC); + if (error) + goto error_cancel; + /* + * Free any blocks freed up in the transaction, then commit. + */ + error = xfs_bmap_finish(&tp, &flist, &committed); + if (error) + goto error_cancel; + error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); + if (error) + goto error; + /* + * Now we need to clear the allocated blocks. + * Do this one block per transaction, to keep it simple. + */ + cancelflags = 0; + for (bno = map.br_startoff, fsbno = map.br_startblock; + bno < map.br_startoff + map.br_blockcount; + bno++, fsbno++) { + tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO); + /* + * Reserve log for one block zeroing. + */ + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero, + 0, 0); + if (error) + goto error_cancel; + /* + * Lock the bitmap inode. + */ + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + /* + * Get a buffer for the block. + */ + d = XFS_FSB_TO_DADDR(mp, fsbno); + bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, + mp->m_bsize, 0); + if (bp == NULL) { + error = XFS_ERROR(EIO); +error_cancel: + xfs_trans_cancel(tp, cancelflags); + goto error; + } + memset(bp->b_addr, 0, mp->m_sb.sb_blocksize); + xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); + /* + * Commit the transaction. + */ + error = xfs_trans_commit(tp, 0); + if (error) + goto error; } + /* + * Go on to the next extent, if any. + */ + oblocks = map.br_startoff + map.br_blockcount; } - /* - * Point to the summary information, modify and log it. - */ - sp = XFS_SUMPTR(mp, bp, so); - *sp += delta; - xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr), - (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1)); return 0; + +error: + return error; } /* @@ -2127,66 +1230,6 @@ xfs_rtallocate_extent( return 0; } -/* - * Free an extent in the realtime subvolume. Length is expressed in - * realtime extents, as is the block number. - */ -int /* error */ -xfs_rtfree_extent( - xfs_trans_t *tp, /* transaction pointer */ - xfs_rtblock_t bno, /* starting block number to free */ - xfs_extlen_t len) /* length of extent freed */ -{ - int error; /* error value */ - xfs_mount_t *mp; /* file system mount structure */ - xfs_fsblock_t sb; /* summary file block number */ - xfs_buf_t *sumbp; /* summary file block buffer */ - - mp = tp->t_mountp; - - ASSERT(mp->m_rbmip->i_itemp != NULL); - ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); - -#ifdef DEBUG - /* - * Check to see that this whole range is currently allocated. - */ - { - int stat; /* result from checking range */ - - error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &stat); - if (error) { - return error; - } - ASSERT(stat); - } -#endif - sumbp = NULL; - /* - * Free the range of realtime blocks. - */ - error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb); - if (error) { - return error; - } - /* - * Mark more blocks free in the superblock. - */ - xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len); - /* - * If we've now freed all the blocks, reset the file sequence - * number to 0. - */ - if (tp->t_frextents_delta + mp->m_sb.sb_frextents == - mp->m_sb.sb_rextents) { - if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) - mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; - *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0; - xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); - } - return 0; -} - /* * Initialize realtime fields in the mount structure. */ diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h index b2a1a24c0e2f..752b63d10300 100644 --- a/fs/xfs/xfs_rtalloc.h +++ b/fs/xfs/xfs_rtalloc.h @@ -95,6 +95,30 @@ xfs_growfs_rt( struct xfs_mount *mp, /* file system mount structure */ xfs_growfs_rt_t *in); /* user supplied growfs struct */ +/* + * From xfs_rtbitmap.c + */ +int xfs_rtbuf_get(struct xfs_mount *mp, struct xfs_trans *tp, + xfs_rtblock_t block, int issum, struct xfs_buf **bpp); +int xfs_rtcheck_range(struct xfs_mount *mp, struct xfs_trans *tp, + xfs_rtblock_t start, xfs_extlen_t len, int val, + xfs_rtblock_t *new, int *stat); +int xfs_rtfind_back(struct xfs_mount *mp, struct xfs_trans *tp, + xfs_rtblock_t start, xfs_rtblock_t limit, + xfs_rtblock_t *rtblock); +int xfs_rtfind_forw(struct xfs_mount *mp, struct xfs_trans *tp, + xfs_rtblock_t start, xfs_rtblock_t limit, + xfs_rtblock_t *rtblock); +int xfs_rtmodify_range(struct xfs_mount *mp, struct xfs_trans *tp, + xfs_rtblock_t start, xfs_extlen_t len, int val); +int xfs_rtmodify_summary(struct xfs_mount *mp, struct xfs_trans *tp, int log, + xfs_rtblock_t bbno, int delta, xfs_buf_t **rbpp, + xfs_fsblock_t *rsb); +int xfs_rtfree_range(struct xfs_mount *mp, struct xfs_trans *tp, + xfs_rtblock_t start, xfs_extlen_t len, + struct xfs_buf **rbpp, xfs_fsblock_t *rsb); + + #else # define xfs_rtallocate_extent(t,b,min,max,l,a,f,p,rb) (ENOSYS) # define xfs_rtfree_extent(t,b,l) (ENOSYS) diff --git a/fs/xfs/xfs_rtbitmap.c b/fs/xfs/xfs_rtbitmap.c new file mode 100644 index 000000000000..e30efe8be5e6 --- /dev/null +++ b/fs/xfs/xfs_rtbitmap.c @@ -0,0 +1,973 @@ +/* + * Copyright (c) 2000-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 + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_bit.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "xfs_mount.h" +#include "xfs_inode.h" +#include "xfs_bmap.h" +#include "xfs_bmap_util.h" +#include "xfs_bmap_btree.h" +#include "xfs_alloc.h" +#include "xfs_error.h" +#include "xfs_trans.h" +#include "xfs_trans_space.h" +#include "xfs_trace.h" +#include "xfs_buf.h" +#include "xfs_icache.h" +#include "xfs_dinode.h" + + +/* + * Realtime allocator bitmap functions shared with userspace. + */ + +/* + * Get a buffer for the bitmap or summary file block specified. + * The buffer is returned read and locked. + */ +int +xfs_rtbuf_get( + xfs_mount_t *mp, /* file system mount structure */ + xfs_trans_t *tp, /* transaction pointer */ + xfs_rtblock_t block, /* block number in bitmap or summary */ + int issum, /* is summary not bitmap */ + xfs_buf_t **bpp) /* output: buffer for the block */ +{ + xfs_buf_t *bp; /* block buffer, result */ + xfs_inode_t *ip; /* bitmap or summary inode */ + xfs_bmbt_irec_t map; + int nmap = 1; + int error; /* error value */ + + ip = issum ? mp->m_rsumip : mp->m_rbmip; + + error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK); + if (error) + return error; + + ASSERT(map.br_startblock != NULLFSBLOCK); + error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, + XFS_FSB_TO_DADDR(mp, map.br_startblock), + mp->m_bsize, 0, &bp, NULL); + if (error) + return error; + ASSERT(!xfs_buf_geterror(bp)); + *bpp = bp; + return 0; +} + +/* + * Searching backward from start to limit, find the first block whose + * allocated/free state is different from start's. + */ +int +xfs_rtfind_back( + xfs_mount_t *mp, /* file system mount point */ + xfs_trans_t *tp, /* transaction pointer */ + xfs_rtblock_t start, /* starting block to look at */ + xfs_rtblock_t limit, /* last block to look at */ + xfs_rtblock_t *rtblock) /* out: start block found */ +{ + xfs_rtword_t *b; /* current word in buffer */ + int bit; /* bit number in the word */ + xfs_rtblock_t block; /* bitmap block number */ + xfs_buf_t *bp; /* buf for the block */ + xfs_rtword_t *bufp; /* starting word in buffer */ + int error; /* error value */ + xfs_rtblock_t firstbit; /* first useful bit in the word */ + xfs_rtblock_t i; /* current bit number rel. to start */ + xfs_rtblock_t len; /* length of inspected area */ + xfs_rtword_t mask; /* mask of relevant bits for value */ + xfs_rtword_t want; /* mask for "good" values */ + xfs_rtword_t wdiff; /* difference from wanted value */ + int word; /* word number in the buffer */ + + /* + * Compute and read in starting bitmap block for starting block. + */ + block = XFS_BITTOBLOCK(mp, start); + error = xfs_rtbuf_get(mp, tp, block, 0, &bp); + if (error) { + return error; + } + bufp = bp->b_addr; + /* + * Get the first word's index & point to it. + */ + word = XFS_BITTOWORD(mp, start); + b = &bufp[word]; + bit = (int)(start & (XFS_NBWORD - 1)); + len = start - limit + 1; + /* + * Compute match value, based on the bit at start: if 1 (free) + * then all-ones, else all-zeroes. + */ + want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0; + /* + * If the starting position is not word-aligned, deal with the + * partial word. + */ + if (bit < XFS_NBWORD - 1) { + /* + * Calculate first (leftmost) bit number to look at, + * and mask for all the relevant bits in this word. + */ + firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0); + mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) << + firstbit; + /* + * Calculate the difference between the value there + * and what we're looking for. + */ + if ((wdiff = (*b ^ want) & mask)) { + /* + * Different. Mark where we are and return. + */ + xfs_trans_brelse(tp, bp); + i = bit - XFS_RTHIBIT(wdiff); + *rtblock = start - i + 1; + return 0; + } + i = bit - firstbit + 1; + /* + * Go on to previous block if that's where the previous word is + * and we need the previous word. + */ + if (--word == -1 && i < len) { + /* + * If done with this block, get the previous one. + */ + xfs_trans_brelse(tp, bp); + error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); + if (error) { + return error; + } + bufp = bp->b_addr; + word = XFS_BLOCKWMASK(mp); + b = &bufp[word]; + } else { + /* + * Go on to the previous word in the buffer. + */ + b--; + } + } else { + /* + * Starting on a word boundary, no partial word. + */ + i = 0; + } + /* + * Loop over whole words in buffers. When we use up one buffer + * we move on to the previous one. + */ + while (len - i >= XFS_NBWORD) { + /* + * Compute difference between actual and desired value. + */ + if ((wdiff = *b ^ want)) { + /* + * Different, mark where we are and return. + */ + xfs_trans_brelse(tp, bp); + i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); + *rtblock = start - i + 1; + return 0; + } + i += XFS_NBWORD; + /* + * Go on to previous block if that's where the previous word is + * and we need the previous word. + */ + if (--word == -1 && i < len) { + /* + * If done with this block, get the previous one. + */ + xfs_trans_brelse(tp, bp); + error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); + if (error) { + return error; + } + bufp = bp->b_addr; + word = XFS_BLOCKWMASK(mp); + b = &bufp[word]; + } else { + /* + * Go on to the previous word in the buffer. + */ + b--; + } + } + /* + * If not ending on a word boundary, deal with the last + * (partial) word. + */ + if (len - i) { + /* + * Calculate first (leftmost) bit number to look at, + * and mask for all the relevant bits in this word. + */ + firstbit = XFS_NBWORD - (len - i); + mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit; + /* + * Compute difference between actual and desired value. + */ + if ((wdiff = (*b ^ want) & mask)) { + /* + * Different, mark where we are and return. + */ + xfs_trans_brelse(tp, bp); + i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); + *rtblock = start - i + 1; + return 0; + } else + i = len; + } + /* + * No match, return that we scanned the whole area. + */ + xfs_trans_brelse(tp, bp); + *rtblock = start - i + 1; + return 0; +} + +/* + * Searching forward from start to limit, find the first block whose + * allocated/free state is different from start's. + */ +int +xfs_rtfind_forw( + xfs_mount_t *mp, /* file system mount point */ + xfs_trans_t *tp, /* transaction pointer */ + xfs_rtblock_t start, /* starting block to look at */ + xfs_rtblock_t limit, /* last block to look at */ + xfs_rtblock_t *rtblock) /* out: start block found */ +{ + xfs_rtword_t *b; /* current word in buffer */ + int bit; /* bit number in the word */ + xfs_rtblock_t block; /* bitmap block number */ + xfs_buf_t *bp; /* buf for the block */ + xfs_rtword_t *bufp; /* starting word in buffer */ + int error; /* error value */ + xfs_rtblock_t i; /* current bit number rel. to start */ + xfs_rtblock_t lastbit; /* last useful bit in the word */ + xfs_rtblock_t len; /* length of inspected area */ + xfs_rtword_t mask; /* mask of relevant bits for value */ + xfs_rtword_t want; /* mask for "good" values */ + xfs_rtword_t wdiff; /* difference from wanted value */ + int word; /* word number in the buffer */ + + /* + * Compute and read in starting bitmap block for starting block. + */ + block = XFS_BITTOBLOCK(mp, start); + error = xfs_rtbuf_get(mp, tp, block, 0, &bp); + if (error) { + return error; + } + bufp = bp->b_addr; + /* + * Get the first word's index & point to it. + */ + word = XFS_BITTOWORD(mp, start); + b = &bufp[word]; + bit = (int)(start & (XFS_NBWORD - 1)); + len = limit - start + 1; + /* + * Compute match value, based on the bit at start: if 1 (free) + * then all-ones, else all-zeroes. + */ + want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0; + /* + * If the starting position is not word-aligned, deal with the + * partial word. + */ + if (bit) { + /* + * Calculate last (rightmost) bit number to look at, + * and mask for all the relevant bits in this word. + */ + lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); + mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; + /* + * Calculate the difference between the value there + * and what we're looking for. + */ + if ((wdiff = (*b ^ want) & mask)) { + /* + * Different. Mark where we are and return. + */ + xfs_trans_brelse(tp, bp); + i = XFS_RTLOBIT(wdiff) - bit; + *rtblock = start + i - 1; + return 0; + } + i = lastbit - bit; + /* + * Go on to next block if that's where the next word is + * and we need the next word. + */ + if (++word == XFS_BLOCKWSIZE(mp) && i < len) { + /* + * If done with this block, get the previous one. + */ + xfs_trans_brelse(tp, bp); + error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); + if (error) { + return error; + } + b = bufp = bp->b_addr; + word = 0; + } else { + /* + * Go on to the previous word in the buffer. + */ + b++; + } + } else { + /* + * Starting on a word boundary, no partial word. + */ + i = 0; + } + /* + * Loop over whole words in buffers. When we use up one buffer + * we move on to the next one. + */ + while (len - i >= XFS_NBWORD) { + /* + * Compute difference between actual and desired value. + */ + if ((wdiff = *b ^ want)) { + /* + * Different, mark where we are and return. + */ + xfs_trans_brelse(tp, bp); + i += XFS_RTLOBIT(wdiff); + *rtblock = start + i - 1; + return 0; + } + i += XFS_NBWORD; + /* + * Go on to next block if that's where the next word is + * and we need the next word. + */ + if (++word == XFS_BLOCKWSIZE(mp) && i < len) { + /* + * If done with this block, get the next one. + */ + xfs_trans_brelse(tp, bp); + error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); + if (error) { + return error; + } + b = bufp = bp->b_addr; + word = 0; + } else { + /* + * Go on to the next word in the buffer. + */ + b++; + } + } + /* + * If not ending on a word boundary, deal with the last + * (partial) word. + */ + if ((lastbit = len - i)) { + /* + * Calculate mask for all the relevant bits in this word. + */ + mask = ((xfs_rtword_t)1 << lastbit) - 1; + /* + * Compute difference between actual and desired value. + */ + if ((wdiff = (*b ^ want) & mask)) { + /* + * Different, mark where we are and return. + */ + xfs_trans_brelse(tp, bp); + i += XFS_RTLOBIT(wdiff); + *rtblock = start + i - 1; + return 0; + } else + i = len; + } + /* + * No match, return that we scanned the whole area. + */ + xfs_trans_brelse(tp, bp); + *rtblock = start + i - 1; + return 0; +} + +/* + * Read and modify the summary information for a given extent size, + * bitmap block combination. + * Keeps track of a current summary block, so we don't keep reading + * it from the buffer cache. + */ +int +xfs_rtmodify_summary( + xfs_mount_t *mp, /* file system mount point */ + xfs_trans_t *tp, /* transaction pointer */ + int log, /* log2 of extent size */ + xfs_rtblock_t bbno, /* bitmap block number */ + int delta, /* change to make to summary info */ + xfs_buf_t **rbpp, /* in/out: summary block buffer */ + xfs_fsblock_t *rsb) /* in/out: summary block number */ +{ + xfs_buf_t *bp; /* buffer for the summary block */ + int error; /* error value */ + xfs_fsblock_t sb; /* summary fsblock */ + int so; /* index into the summary file */ + xfs_suminfo_t *sp; /* pointer to returned data */ + + /* + * Compute entry number in the summary file. + */ + so = XFS_SUMOFFS(mp, log, bbno); + /* + * Compute the block number in the summary file. + */ + sb = XFS_SUMOFFSTOBLOCK(mp, so); + /* + * If we have an old buffer, and the block number matches, use that. + */ + if (rbpp && *rbpp && *rsb == sb) + bp = *rbpp; + /* + * Otherwise we have to get the buffer. + */ + else { + /* + * If there was an old one, get rid of it first. + */ + if (rbpp && *rbpp) + xfs_trans_brelse(tp, *rbpp); + error = xfs_rtbuf_get(mp, tp, sb, 1, &bp); + if (error) { + return error; + } + /* + * Remember this buffer and block for the next call. + */ + if (rbpp) { + *rbpp = bp; + *rsb = sb; + } + } + /* + * Point to the summary information, modify and log it. + */ + sp = XFS_SUMPTR(mp, bp, so); + *sp += delta; + xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr), + (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1)); + return 0; +} + +/* + * Set the given range of bitmap bits to the given value. + * Do whatever I/O and logging is required. + */ +int +xfs_rtmodify_range( + xfs_mount_t *mp, /* file system mount point */ + xfs_trans_t *tp, /* transaction pointer */ + xfs_rtblock_t start, /* starting block to modify */ + xfs_extlen_t len, /* length of extent to modify */ + int val) /* 1 for free, 0 for allocated */ +{ + xfs_rtword_t *b; /* current word in buffer */ + int bit; /* bit number in the word */ + xfs_rtblock_t block; /* bitmap block number */ + xfs_buf_t *bp; /* buf for the block */ + xfs_rtword_t *bufp; /* starting word in buffer */ + int error; /* error value */ + xfs_rtword_t *first; /* first used word in the buffer */ + int i; /* current bit number rel. to start */ + int lastbit; /* last useful bit in word */ + xfs_rtword_t mask; /* mask o frelevant bits for value */ + int word; /* word number in the buffer */ + + /* + * Compute starting bitmap block number. + */ + block = XFS_BITTOBLOCK(mp, start); + /* + * Read the bitmap block, and point to its data. + */ + error = xfs_rtbuf_get(mp, tp, block, 0, &bp); + if (error) { + return error; + } + bufp = bp->b_addr; + /* + * Compute the starting word's address, and starting bit. + */ + word = XFS_BITTOWORD(mp, start); + first = b = &bufp[word]; + bit = (int)(start & (XFS_NBWORD - 1)); + /* + * 0 (allocated) => all zeroes; 1 (free) => all ones. + */ + val = -val; + /* + * If not starting on a word boundary, deal with the first + * (partial) word. + */ + if (bit) { + /* + * Compute first bit not changed and mask of relevant bits. + */ + lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); + mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; + /* + * Set/clear the active bits. + */ + if (val) + *b |= mask; + else + *b &= ~mask; + i = lastbit - bit; + /* + * Go on to the next block if that's where the next word is + * and we need the next word. + */ + if (++word == XFS_BLOCKWSIZE(mp) && i < len) { + /* + * Log the changed part of this block. + * Get the next one. + */ + xfs_trans_log_buf(tp, bp, + (uint)((char *)first - (char *)bufp), + (uint)((char *)b - (char *)bufp)); + error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); + if (error) { + return error; + } + first = b = bufp = bp->b_addr; + word = 0; + } else { + /* + * Go on to the next word in the buffer + */ + b++; + } + } else { + /* + * Starting on a word boundary, no partial word. + */ + i = 0; + } + /* + * Loop over whole words in buffers. When we use up one buffer + * we move on to the next one. + */ + while (len - i >= XFS_NBWORD) { + /* + * Set the word value correctly. + */ + *b = val; + i += XFS_NBWORD; + /* + * Go on to the next block if that's where the next word is + * and we need the next word. + */ + if (++word == XFS_BLOCKWSIZE(mp) && i < len) { + /* + * Log the changed part of this block. + * Get the next one. + */ + xfs_trans_log_buf(tp, bp, + (uint)((char *)first - (char *)bufp), + (uint)((char *)b - (char *)bufp)); + error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); + if (error) { + return error; + } + first = b = bufp = bp->b_addr; + word = 0; + } else { + /* + * Go on to the next word in the buffer + */ + b++; + } + } + /* + * If not ending on a word boundary, deal with the last + * (partial) word. + */ + if ((lastbit = len - i)) { + /* + * Compute a mask of relevant bits. + */ + bit = 0; + mask = ((xfs_rtword_t)1 << lastbit) - 1; + /* + * Set/clear the active bits. + */ + if (val) + *b |= mask; + else + *b &= ~mask; + b++; + } + /* + * Log any remaining changed bytes. + */ + if (b > first) + xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp), + (uint)((char *)b - (char *)bufp - 1)); + return 0; +} + +/* + * Mark an extent specified by start and len freed. + * Updates all the summary information as well as the bitmap. + */ +int +xfs_rtfree_range( + xfs_mount_t *mp, /* file system mount point */ + xfs_trans_t *tp, /* transaction pointer */ + xfs_rtblock_t start, /* starting block to free */ + xfs_extlen_t len, /* length to free */ + xfs_buf_t **rbpp, /* in/out: summary block buffer */ + xfs_fsblock_t *rsb) /* in/out: summary block number */ +{ + xfs_rtblock_t end; /* end of the freed extent */ + int error; /* error value */ + xfs_rtblock_t postblock; /* first block freed > end */ + xfs_rtblock_t preblock; /* first block freed < start */ + + end = start + len - 1; + /* + * Modify the bitmap to mark this extent freed. + */ + error = xfs_rtmodify_range(mp, tp, start, len, 1); + if (error) { + return error; + } + /* + * Assume we're freeing out of the middle of an allocated extent. + * We need to find the beginning and end of the extent so we can + * properly update the summary. + */ + error = xfs_rtfind_back(mp, tp, start, 0, &preblock); + if (error) { + return error; + } + /* + * Find the next allocated block (end of allocated extent). + */ + error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, + &postblock); + if (error) + return error; + /* + * If there are blocks not being freed at the front of the + * old extent, add summary data for them to be allocated. + */ + if (preblock < start) { + error = xfs_rtmodify_summary(mp, tp, + XFS_RTBLOCKLOG(start - preblock), + XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); + if (error) { + return error; + } + } + /* + * If there are blocks not being freed at the end of the + * old extent, add summary data for them to be allocated. + */ + if (postblock > end) { + error = xfs_rtmodify_summary(mp, tp, + XFS_RTBLOCKLOG(postblock - end), + XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb); + if (error) { + return error; + } + } + /* + * Increment the summary information corresponding to the entire + * (new) free extent. + */ + error = xfs_rtmodify_summary(mp, tp, + XFS_RTBLOCKLOG(postblock + 1 - preblock), + XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); + return error; +} + +/* + * Check that the given range is either all allocated (val = 0) or + * all free (val = 1). + */ +int +xfs_rtcheck_range( + xfs_mount_t *mp, /* file system mount point */ + xfs_trans_t *tp, /* transaction pointer */ + xfs_rtblock_t start, /* starting block number of extent */ + xfs_extlen_t len, /* length of extent */ + int val, /* 1 for free, 0 for allocated */ + xfs_rtblock_t *new, /* out: first block not matching */ + int *stat) /* out: 1 for matches, 0 for not */ +{ + xfs_rtword_t *b; /* current word in buffer */ + int bit; /* bit number in the word */ + xfs_rtblock_t block; /* bitmap block number */ + xfs_buf_t *bp; /* buf for the block */ + xfs_rtword_t *bufp; /* starting word in buffer */ + int error; /* error value */ + xfs_rtblock_t i; /* current bit number rel. to start */ + xfs_rtblock_t lastbit; /* last useful bit in word */ + xfs_rtword_t mask; /* mask of relevant bits for value */ + xfs_rtword_t wdiff; /* difference from wanted value */ + int word; /* word number in the buffer */ + + /* + * Compute starting bitmap block number + */ + block = XFS_BITTOBLOCK(mp, start); + /* + * Read the bitmap block. + */ + error = xfs_rtbuf_get(mp, tp, block, 0, &bp); + if (error) { + return error; + } + bufp = bp->b_addr; + /* + * Compute the starting word's address, and starting bit. + */ + word = XFS_BITTOWORD(mp, start); + b = &bufp[word]; + bit = (int)(start & (XFS_NBWORD - 1)); + /* + * 0 (allocated) => all zero's; 1 (free) => all one's. + */ + val = -val; + /* + * If not starting on a word boundary, deal with the first + * (partial) word. + */ + if (bit) { + /* + * Compute first bit not examined. + */ + lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); + /* + * Mask of relevant bits. + */ + mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; + /* + * Compute difference between actual and desired value. + */ + if ((wdiff = (*b ^ val) & mask)) { + /* + * Different, compute first wrong bit and return. + */ + xfs_trans_brelse(tp, bp); + i = XFS_RTLOBIT(wdiff) - bit; + *new = start + i; + *stat = 0; + return 0; + } + i = lastbit - bit; + /* + * Go on to next block if that's where the next word is + * and we need the next word. + */ + if (++word == XFS_BLOCKWSIZE(mp) && i < len) { + /* + * If done with this block, get the next one. + */ + xfs_trans_brelse(tp, bp); + error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); + if (error) { + return error; + } + b = bufp = bp->b_addr; + word = 0; + } else { + /* + * Go on to the next word in the buffer. + */ + b++; + } + } else { + /* + * Starting on a word boundary, no partial word. + */ + i = 0; + } + /* + * Loop over whole words in buffers. When we use up one buffer + * we move on to the next one. + */ + while (len - i >= XFS_NBWORD) { + /* + * Compute difference between actual and desired value. + */ + if ((wdiff = *b ^ val)) { + /* + * Different, compute first wrong bit and return. + */ + xfs_trans_brelse(tp, bp); + i += XFS_RTLOBIT(wdiff); + *new = start + i; + *stat = 0; + return 0; + } + i += XFS_NBWORD; + /* + * Go on to next block if that's where the next word is + * and we need the next word. + */ + if (++word == XFS_BLOCKWSIZE(mp) && i < len) { + /* + * If done with this block, get the next one. + */ + xfs_trans_brelse(tp, bp); + error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); + if (error) { + return error; + } + b = bufp = bp->b_addr; + word = 0; + } else { + /* + * Go on to the next word in the buffer. + */ + b++; + } + } + /* + * If not ending on a word boundary, deal with the last + * (partial) word. + */ + if ((lastbit = len - i)) { + /* + * Mask of relevant bits. + */ + mask = ((xfs_rtword_t)1 << lastbit) - 1; + /* + * Compute difference between actual and desired value. + */ + if ((wdiff = (*b ^ val) & mask)) { + /* + * Different, compute first wrong bit and return. + */ + xfs_trans_brelse(tp, bp); + i += XFS_RTLOBIT(wdiff); + *new = start + i; + *stat = 0; + return 0; + } else + i = len; + } + /* + * Successful, return. + */ + xfs_trans_brelse(tp, bp); + *new = start + i; + *stat = 1; + return 0; +} + +#ifdef DEBUG +/* + * Check that the given extent (block range) is allocated already. + */ +STATIC int /* error */ +xfs_rtcheck_alloc_range( + xfs_mount_t *mp, /* file system mount point */ + xfs_trans_t *tp, /* transaction pointer */ + xfs_rtblock_t bno, /* starting block number of extent */ + xfs_extlen_t len) /* length of extent */ +{ + xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */ + int stat; + int error; + + error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat); + if (error) + return error; + ASSERT(stat); + return 0; +} +#else +#define xfs_rtcheck_alloc_range(m,t,b,l) (0) +#endif +/* + * Free an extent in the realtime subvolume. Length is expressed in + * realtime extents, as is the block number. + */ +int /* error */ +xfs_rtfree_extent( + xfs_trans_t *tp, /* transaction pointer */ + xfs_rtblock_t bno, /* starting block number to free */ + xfs_extlen_t len) /* length of extent freed */ +{ + int error; /* error value */ + xfs_mount_t *mp; /* file system mount structure */ + xfs_fsblock_t sb; /* summary file block number */ + xfs_buf_t *sumbp = NULL; /* summary file block buffer */ + + mp = tp->t_mountp; + + ASSERT(mp->m_rbmip->i_itemp != NULL); + ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); + + error = xfs_rtcheck_alloc_range(mp, tp, bno, len); + if (error) + return error; + + /* + * Free the range of realtime blocks. + */ + error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb); + if (error) { + return error; + } + /* + * Mark more blocks free in the superblock. + */ + xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len); + /* + * If we've now freed all the blocks, reset the file sequence + * number to 0. + */ + if (tp->t_frextents_delta + mp->m_sb.sb_frextents == + mp->m_sb.sb_rextents) { + if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) + mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; + *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0; + xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); + } + return 0; +} + -- cgit v1.2.3 From 32c5483a8a13a43264809144210ec114dd70b611 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:46 +1100 Subject: xfs: abstract the differences in dir2/dir3 via an ops vector Lots of the dir code now goes through switches to determine what is the correct on-disk format to parse. It generally involves a "xfs_sbversion_hasfoo" check, deferencing the superblock version and feature fields and hence touching several cache lines per operation in the process. Some operations do multiple checks because they nest conditional operations and they don't pass the information in a direct fashion between each other. Hence, add an ops vector to the xfs_inode structure that is configured when the inode is initialised to point to all the correct decode and encoding operations. This will significantly reduce the branchiness and cacheline footprint of the directory object decoding and encoding. This is the first patch in a series of conversion patches. It will introduce the ops structure, the setup of it and add the first operation to the vector. Subsequent patches will convert directory ops one at a time to keep the changes simple and obvious. Just this patch shows the benefit of such an approach on code size. Just converting the two shortform dir operations as this patch does decreases the built binary size by ~1500 bytes: $ size fs/xfs/xfs.o.orig fs/xfs/xfs.o.p1 text data bss dec hex filename 794490 96802 1096 892388 d9de4 fs/xfs/xfs.o.orig 792986 96802 1096 890884 d9804 fs/xfs/xfs.o.p1 $ That's a significant decrease in the instruction cache footprint of the directory code for such a simple change, and indicates that this approach is definitely worth pursuing further. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/Makefile | 1 + fs/xfs/xfs_da_btree.h | 1 + fs/xfs/xfs_da_format.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_da_format.h | 26 --------------- fs/xfs/xfs_dir2.c | 7 ++++ fs/xfs/xfs_dir2.h | 14 ++++++++ fs/xfs/xfs_dir2_block.c | 2 +- fs/xfs/xfs_dir2_readdir.c | 4 +-- fs/xfs/xfs_dir2_sf.c | 31 +++++++++-------- fs/xfs/xfs_inode.h | 3 ++ fs/xfs/xfs_iops.c | 1 + fs/xfs/xfs_mount.h | 2 ++ 12 files changed, 132 insertions(+), 45 deletions(-) create mode 100644 fs/xfs/xfs_da_format.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 33a69fabfd83..c21f43506661 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -66,6 +66,7 @@ xfs-y += xfs_alloc.o \ xfs_bmap_btree.o \ xfs_btree.o \ xfs_da_btree.o \ + xfs_da_format.o \ xfs_dir2.o \ xfs_dir2_block.o \ xfs_dir2_data.o \ diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index e492dcadd032..6e95ea79f5d7 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h @@ -23,6 +23,7 @@ struct xfs_bmap_free; struct xfs_inode; struct xfs_trans; struct zone; +struct xfs_dir_ops; /*======================================================================== * Btree searching and modification structure definitions. diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c new file mode 100644 index 000000000000..982d105d012f --- /dev/null +++ b/fs/xfs/xfs_da_format.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. + * Copyright (c) 2013 Red Hat, 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 + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "xfs_mount.h" +#include "xfs_da_format.h" +#include "xfs_inode.h" +#include "xfs_dir2.h" + + +static int +xfs_dir2_sf_entsize( + struct xfs_dir2_sf_hdr *hdr, + int len) +{ + int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */ + + count += len; /* name */ + count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) : + sizeof(xfs_dir2_ino4_t); /* ino # */ + return count; +} + +static int +xfs_dir3_sf_entsize( + struct xfs_dir2_sf_hdr *hdr, + int len) +{ + return xfs_dir2_sf_entsize(hdr, len) + sizeof(__uint8_t); +} + +static struct xfs_dir2_sf_entry * +xfs_dir2_sf_nextentry( + struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep) +{ + return (struct xfs_dir2_sf_entry *) + ((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen)); +} + +static struct xfs_dir2_sf_entry * +xfs_dir3_sf_nextentry( + struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep) +{ + return (struct xfs_dir2_sf_entry *) + ((char *)sfep + xfs_dir3_sf_entsize(hdr, sfep->namelen)); +} + + +const struct xfs_dir_ops xfs_dir2_ops = { + .sf_entsize = xfs_dir2_sf_entsize, + .sf_nextentry = xfs_dir2_sf_nextentry, +}; + +const struct xfs_dir_ops xfs_dir2_ftype_ops = { + .sf_entsize = xfs_dir3_sf_entsize, + .sf_nextentry = xfs_dir3_sf_nextentry, +}; + +const struct xfs_dir_ops xfs_dir3_ops = { + .sf_entsize = xfs_dir3_sf_entsize, + .sf_nextentry = xfs_dir3_sf_nextentry, +}; diff --git a/fs/xfs/xfs_da_format.h b/fs/xfs/xfs_da_format.h index 89a1a219c8ff..d54726d0fc10 100644 --- a/fs/xfs/xfs_da_format.h +++ b/fs/xfs/xfs_da_format.h @@ -329,32 +329,6 @@ xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count)); } -static inline int -xfs_dir3_sf_entsize( - struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, - int len) -{ - int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */ - - count += len; /* name */ - count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) : - sizeof(xfs_dir2_ino4_t); /* ino # */ - if (xfs_sb_version_hasftype(&mp->m_sb)) - count += sizeof(__uint8_t); /* file type */ - return count; -} - -static inline struct xfs_dir2_sf_entry * -xfs_dir3_sf_nextentry( - struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, - struct xfs_dir2_sf_entry *sfep) -{ - return (struct xfs_dir2_sf_entry *) - ((char *)sfep + xfs_dir3_sf_entsize(mp, hdr, sfep->namelen)); -} - /* * in dir3 shortform directories, the file type field is stored at a variable * offset after the inode number. Because it's only a single byte, endian diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 38bf9324302c..7911136453cd 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -112,6 +112,13 @@ xfs_dir_mount( mp->m_dirnameops = &xfs_ascii_ci_nameops; else mp->m_dirnameops = &xfs_default_nameops; + + if (xfs_sb_version_hascrc(&mp->m_sb)) + mp->m_dir_inode_ops = &xfs_dir3_ops; + else if (xfs_sb_version_hasftype(&mp->m_sb)) + mp->m_dir_inode_ops = &xfs_dir2_ftype_ops; + else + mp->m_dir_inode_ops = &xfs_dir2_ops; } /* diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 9910401327d4..1909d9faff71 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -31,6 +31,20 @@ struct xfs_dir2_data_unused; extern struct xfs_name xfs_name_dotdot; +/* + * directory operations vector for encode/decode routines + */ +struct xfs_dir_ops { + int (*sf_entsize)(struct xfs_dir2_sf_hdr *hdr, int len); + struct xfs_dir2_sf_entry * + (*sf_nextentry)(struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep); +}; + +extern const struct xfs_dir_ops xfs_dir2_ops; +extern const struct xfs_dir_ops xfs_dir2_ftype_ops; +extern const struct xfs_dir_ops xfs_dir3_ops; + /* * Generic directory interface routines */ diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 9f3f83a5e2da..9d86b6f9e80f 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -1240,7 +1240,7 @@ xfs_dir2_sf_to_block( if (++i == sfp->count) sfep = NULL; else - sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); + sfep = dp->d_ops->sf_nextentry(sfp, sfep); } /* Done with the temporary buffer */ kmem_free(sfp); diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 45c9ce8cdb28..80333055df34 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -153,7 +153,7 @@ xfs_dir2_sf_getdents( xfs_dir2_sf_get_offset(sfep)); if (ctx->pos > off) { - sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); + sfep = dp->d_ops->sf_nextentry(sfp, sfep); continue; } @@ -163,7 +163,7 @@ xfs_dir2_sf_getdents( if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino, xfs_dir3_get_dtype(mp, filetype))) return 0; - sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); + sfep = dp->d_ops->sf_nextentry(sfp, sfep); } ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 8811ee5eaec6..73881c9f40d6 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -336,7 +336,7 @@ xfs_dir2_block_to_sf( xfs_dir3_sfe_put_ftype(mp, sfp, sfep, xfs_dir3_dirent_get_ftype(mp, dep)); - sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); + sfep = dp->d_ops->sf_nextentry(sfp, sfep); } ptr += xfs_dir3_data_entsize(mp, dep->namelen); } @@ -389,7 +389,7 @@ xfs_dir2_sf_addname( /* * Compute entry (and change in) size. */ - add_entsize = xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen); + add_entsize = dp->d_ops->sf_entsize(sfp, args->namelen); incr_isize = add_entsize; objchange = 0; #if XFS_BIG_INUMS @@ -483,8 +483,7 @@ xfs_dir2_sf_addname_easy( /* * Grow the in-inode space. */ - xfs_idata_realloc(dp, - xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen), + xfs_idata_realloc(dp, dp->d_ops->sf_entsize(sfp, args->namelen), XFS_DATA_FORK); /* * Need to set up again due to realloc of the inode data. @@ -563,7 +562,7 @@ xfs_dir2_sf_addname_hard( eof = (char *)oldsfep == &buf[old_isize]; !eof; offset = new_offset + xfs_dir3_data_entsize(mp, oldsfep->namelen), - oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep), + oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep), eof = (char *)oldsfep == &buf[old_isize]) { new_offset = xfs_dir2_sf_get_offset(oldsfep); if (offset + add_datasize <= new_offset) @@ -603,7 +602,7 @@ xfs_dir2_sf_addname_hard( * If there's more left to copy, do that. */ if (!eof) { - sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); + sfep = dp->d_ops->sf_nextentry(sfp, sfep); memcpy(sfep, oldsfep, old_isize - nbytes); } kmem_free(buf); @@ -653,7 +652,7 @@ xfs_dir2_sf_addname_pick( holefit = offset + size <= xfs_dir2_sf_get_offset(sfep); offset = xfs_dir2_sf_get_offset(sfep) + xfs_dir3_data_entsize(mp, sfep->namelen); - sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep); + sfep = dp->d_ops->sf_nextentry(sfp, sfep); } /* * Calculate data bytes used excluding the new entry, if this @@ -719,7 +718,7 @@ xfs_dir2_sf_check( for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; - i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep)) { + i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset); ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep); i8count += ino > XFS_DIR2_MAX_SHORT_INUM; @@ -848,7 +847,7 @@ xfs_dir2_sf_lookup( */ ci_sfep = NULL; for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; - i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) { + i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { /* * Compare name and if it's an exact match, return the inode * number. If it's the first case-insensitive match, store the @@ -917,7 +916,7 @@ xfs_dir2_sf_removename( * Find the one we're deleting. */ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; - i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) { + i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { if (xfs_da_compname(args, sfep->name, sfep->namelen) == XFS_CMP_EXACT) { ASSERT(xfs_dir3_sfe_get_ino(dp->i_mount, sfp, sfep) == @@ -934,7 +933,7 @@ xfs_dir2_sf_removename( * Calculate sizes. */ byteoff = (int)((char *)sfep - (char *)sfp); - entsize = xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen); + entsize = dp->d_ops->sf_entsize(sfp, args->namelen); newsize = oldsize - entsize; /* * Copy the part if any after the removed entry, sliding it down. @@ -1051,7 +1050,7 @@ xfs_dir2_sf_replace( */ else { for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; - i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) { + i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { if (xfs_da_compname(args, sfep->name, sfep->namelen) == XFS_CMP_EXACT) { #if XFS_BIG_INUMS || defined(DEBUG) @@ -1172,8 +1171,8 @@ xfs_dir2_sf_toino4( for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), oldsfep = xfs_dir2_sf_firstentry(oldsfp); i < sfp->count; - i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep), - oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep)) { + i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep), + oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) { sfep->namelen = oldsfep->namelen; sfep->offset = oldsfep->offset; memcpy(sfep->name, oldsfep->name, sfep->namelen); @@ -1251,8 +1250,8 @@ xfs_dir2_sf_toino8( for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), oldsfep = xfs_dir2_sf_firstentry(oldsfp); i < sfp->count; - i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep), - oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep)) { + i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep), + oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) { sfep->namelen = oldsfep->namelen; sfep->offset = oldsfep->offset; memcpy(sfep->name, oldsfep->name, sfep->namelen); diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 66675877f38c..9e6efccbae04 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -49,6 +49,9 @@ typedef struct xfs_inode { xfs_ifork_t *i_afp; /* attribute fork pointer */ xfs_ifork_t i_df; /* data fork */ + /* operations vectors */ + const struct xfs_dir_ops *d_ops; /* directory ops vector */ + /* Transaction and locking information. */ struct xfs_inode_log_item *i_itemp; /* logging information */ mrlock_t i_lock; /* inode lock */ diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 718b62b0fe05..0493587ea6bc 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1215,6 +1215,7 @@ xfs_setup_inode( else inode->i_op = &xfs_dir_inode_operations; inode->i_fop = &xfs_dir_file_operations; + ip->d_ops = ip->i_mount->m_dir_inode_ops; break; case S_IFLNK: inode->i_op = &xfs_symlink_inode_operations; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 1fa0584b5627..973397f66c6b 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -26,6 +26,7 @@ struct xfs_mru_cache; struct xfs_nameops; struct xfs_ail; struct xfs_quotainfo; +struct xfs_dir_ops; #ifdef HAVE_PERCPU_SB @@ -148,6 +149,7 @@ typedef struct xfs_mount { int m_dir_magicpct; /* 37% of the dir blocksize */ __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */ + const struct xfs_dir_ops *m_dir_inode_ops; /* vector of dir inode ops */ int m_dirblksize; /* directory block sz--bytes */ int m_dirblkfsbs; /* directory block sz--fsbs */ xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ -- cgit v1.2.3 From 4740175e75f70ab71f76ae98ab00f7db731a48f7 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:47 +1100 Subject: xfs: vectorise remaining shortform dir2 ops Following from the initial patch to introduce the directory operations vector, convert the rest of the shortform directory operations to use vectored ops rather than superblock feature checks. This further reduces the size of the built binary: text data bss dec hex filename 794490 96802 1096 892388 d9de4 fs/xfs/xfs.o.orig 792986 96802 1096 890884 d9804 fs/xfs/xfs.o.p1 792350 96802 1096 890248 d9588 fs/xfs/xfs.o.p2 Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_da_format.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_da_format.h | 47 -------------- fs/xfs/xfs_dir2.h | 20 +++--- fs/xfs/xfs_dir2_block.c | 6 +- fs/xfs/xfs_dir2_readdir.c | 6 +- fs/xfs/xfs_dir2_sf.c | 151 +++++++++------------------------------------ 6 files changed, 199 insertions(+), 183 deletions(-) diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index 982d105d012f..62f55a0186ae 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c @@ -69,17 +69,169 @@ xfs_dir3_sf_nextentry( } +/* + * For filetype enabled shortform directories, the file type field is stored at + * the end of the name. Because it's only a single byte, endian conversion is + * not necessary. For non-filetype enable directories, the type is always + * unknown and we never store the value. + */ +static __uint8_t +xfs_dir2_sfe_get_ftype( + struct xfs_dir2_sf_entry *sfep) +{ + return XFS_DIR3_FT_UNKNOWN; +} + +static void +xfs_dir2_sfe_put_ftype( + struct xfs_dir2_sf_entry *sfep, + __uint8_t ftype) +{ + ASSERT(ftype < XFS_DIR3_FT_MAX); +} + +static __uint8_t +xfs_dir3_sfe_get_ftype( + struct xfs_dir2_sf_entry *sfep) +{ + __uint8_t ftype; + + ftype = sfep->name[sfep->namelen]; + if (ftype >= XFS_DIR3_FT_MAX) + return XFS_DIR3_FT_UNKNOWN; + return ftype; +} + +static void +xfs_dir3_sfe_put_ftype( + struct xfs_dir2_sf_entry *sfep, + __uint8_t ftype) +{ + ASSERT(ftype < XFS_DIR3_FT_MAX); + + sfep->name[sfep->namelen] = ftype; +} + +/* + * Inode numbers in short-form directories can come in two versions, + * either 4 bytes or 8 bytes wide. These helpers deal with the + * two forms transparently by looking at the headers i8count field. + * + * For 64-bit inode number the most significant byte must be zero. + */ +static xfs_ino_t +xfs_dir2_sf_get_ino( + struct xfs_dir2_sf_hdr *hdr, + xfs_dir2_inou_t *from) +{ + if (hdr->i8count) + return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL; + else + return get_unaligned_be32(&from->i4.i); +} + +static void +xfs_dir2_sf_put_ino( + struct xfs_dir2_sf_hdr *hdr, + xfs_dir2_inou_t *to, + xfs_ino_t ino) +{ + ASSERT((ino & 0xff00000000000000ULL) == 0); + + if (hdr->i8count) + put_unaligned_be64(ino, &to->i8.i); + else + put_unaligned_be32(ino, &to->i4.i); +} + +static xfs_ino_t +xfs_dir2_sf_get_parent_ino( + struct xfs_dir2_sf_hdr *hdr) +{ + return xfs_dir2_sf_get_ino(hdr, &hdr->parent); +} + +static void +xfs_dir2_sf_put_parent_ino( + struct xfs_dir2_sf_hdr *hdr, + xfs_ino_t ino) +{ + xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino); +} + +/* + * In short-form directory entries the inode numbers are stored at variable + * offset behind the entry name. If the entry stores a filetype value, then it + * sits between the name and the inode number. Hence the inode numbers may only + * be accessed through the helpers below. + */ +static xfs_ino_t +xfs_dir2_sfe_get_ino( + struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep) +{ + return xfs_dir2_sf_get_ino(hdr, + (xfs_dir2_inou_t *)&sfep->name[sfep->namelen]); +} + +static void +xfs_dir2_sfe_put_ino( + struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep, + xfs_ino_t ino) +{ + xfs_dir2_sf_put_ino(hdr, + (xfs_dir2_inou_t *)&sfep->name[sfep->namelen], ino); +} + +static xfs_ino_t +xfs_dir3_sfe_get_ino( + struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep) +{ + return xfs_dir2_sf_get_ino(hdr, + (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1]); +} + +static void +xfs_dir3_sfe_put_ino( + struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep, + xfs_ino_t ino) +{ + xfs_dir2_sf_put_ino(hdr, + (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1], ino); +} + const struct xfs_dir_ops xfs_dir2_ops = { .sf_entsize = xfs_dir2_sf_entsize, .sf_nextentry = xfs_dir2_sf_nextentry, + .sf_get_ftype = xfs_dir2_sfe_get_ftype, + .sf_put_ftype = xfs_dir2_sfe_put_ftype, + .sf_get_ino = xfs_dir2_sfe_get_ino, + .sf_put_ino = xfs_dir2_sfe_put_ino, + .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, + .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, }; const struct xfs_dir_ops xfs_dir2_ftype_ops = { .sf_entsize = xfs_dir3_sf_entsize, .sf_nextentry = xfs_dir3_sf_nextentry, + .sf_get_ftype = xfs_dir3_sfe_get_ftype, + .sf_put_ftype = xfs_dir3_sfe_put_ftype, + .sf_get_ino = xfs_dir3_sfe_get_ino, + .sf_put_ino = xfs_dir3_sfe_put_ino, + .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, + .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, }; const struct xfs_dir_ops xfs_dir3_ops = { .sf_entsize = xfs_dir3_sf_entsize, .sf_nextentry = xfs_dir3_sf_nextentry, + .sf_get_ftype = xfs_dir3_sfe_get_ftype, + .sf_put_ftype = xfs_dir3_sfe_put_ftype, + .sf_get_ino = xfs_dir3_sfe_get_ino, + .sf_put_ino = xfs_dir3_sfe_put_ino, + .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, + .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, }; diff --git a/fs/xfs/xfs_da_format.h b/fs/xfs/xfs_da_format.h index d54726d0fc10..68c2ad5ba54f 100644 --- a/fs/xfs/xfs_da_format.h +++ b/fs/xfs/xfs_da_format.h @@ -329,53 +329,6 @@ xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count)); } -/* - * in dir3 shortform directories, the file type field is stored at a variable - * offset after the inode number. Because it's only a single byte, endian - * conversion is not necessary. - */ -static inline __uint8_t * -xfs_dir3_sfe_ftypep( - struct xfs_dir2_sf_hdr *hdr, - struct xfs_dir2_sf_entry *sfep) -{ - return (__uint8_t *)&sfep->name[sfep->namelen]; -} - -static inline __uint8_t -xfs_dir3_sfe_get_ftype( - struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, - struct xfs_dir2_sf_entry *sfep) -{ - __uint8_t *ftp; - - if (!xfs_sb_version_hasftype(&mp->m_sb)) - return XFS_DIR3_FT_UNKNOWN; - - ftp = xfs_dir3_sfe_ftypep(hdr, sfep); - if (*ftp >= XFS_DIR3_FT_MAX) - return XFS_DIR3_FT_UNKNOWN; - return *ftp; -} - -static inline void -xfs_dir3_sfe_put_ftype( - struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, - struct xfs_dir2_sf_entry *sfep, - __uint8_t ftype) -{ - __uint8_t *ftp; - - ASSERT(ftype < XFS_DIR3_FT_MAX); - - if (!xfs_sb_version_hasftype(&mp->m_sb)) - return; - ftp = xfs_dir3_sfe_ftypep(hdr, sfep); - *ftp = ftype; -} - /* * Data block structures. * diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 1909d9faff71..0e94b3e662af 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -39,6 +39,17 @@ struct xfs_dir_ops { struct xfs_dir2_sf_entry * (*sf_nextentry)(struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep); + __uint8_t (*sf_get_ftype)(struct xfs_dir2_sf_entry *sfep); + void (*sf_put_ftype)(struct xfs_dir2_sf_entry *sfep, + __uint8_t ftype); + xfs_ino_t (*sf_get_ino)(struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep); + void (*sf_put_ino)(struct xfs_dir2_sf_hdr *hdr, + struct xfs_dir2_sf_entry *sfep, + xfs_ino_t ino); + xfs_ino_t (*sf_get_parent_ino)(struct xfs_dir2_sf_hdr *hdr); + void (*sf_put_parent_ino)(struct xfs_dir2_sf_hdr *hdr, + xfs_ino_t ino); }; extern const struct xfs_dir_ops xfs_dir2_ops; @@ -79,15 +90,6 @@ extern int xfs_dir2_sf_to_block(struct xfs_da_args *args); /* * Interface routines used by userspace utilities */ -extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp); -extern void xfs_dir2_sf_put_parent_ino(struct xfs_dir2_sf_hdr *sfp, - xfs_ino_t ino); -extern xfs_ino_t xfs_dir3_sfe_get_ino(struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *sfp, struct xfs_dir2_sf_entry *sfep); -extern void xfs_dir3_sfe_put_ino(struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep, - xfs_ino_t ino); - extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp, int *r); extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r); extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 9d86b6f9e80f..960f3ab526f6 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -1173,7 +1173,7 @@ xfs_dir2_sf_to_block( * Create entry for .. */ dep = xfs_dir3_data_dotdot_entry_p(mp, hdr); - dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp)); + dep->inumber = cpu_to_be64(dp->d_ops->sf_get_parent_ino(sfp)); dep->namelen = 2; dep->name[0] = dep->name[1] = '.'; xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR); @@ -1222,10 +1222,10 @@ xfs_dir2_sf_to_block( * Copy a real entry. */ dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset); - dep->inumber = cpu_to_be64(xfs_dir3_sfe_get_ino(mp, sfp, sfep)); + dep->inumber = cpu_to_be64(dp->d_ops->sf_get_ino(sfp, sfep)); dep->namelen = sfep->namelen; xfs_dir3_dirent_put_ftype(mp, dep, - xfs_dir3_sfe_get_ftype(mp, sfp, sfep)); + dp->d_ops->sf_get_ftype(sfep)); memcpy(dep->name, sfep->name, dep->namelen); tagp = xfs_dir3_data_entry_tag_p(mp, dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 80333055df34..2d2c8fb05541 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -136,7 +136,7 @@ xfs_dir2_sf_getdents( * Put .. entry unless we're starting past it. */ if (ctx->pos <= dotdot_offset) { - ino = xfs_dir2_sf_get_parent_ino(sfp); + ino = dp->d_ops->sf_get_parent_ino(sfp); ctx->pos = dotdot_offset & 0x7fffffff; if (!dir_emit(ctx, "..", 2, ino, DT_DIR)) return 0; @@ -157,8 +157,8 @@ xfs_dir2_sf_getdents( continue; } - ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep); - filetype = xfs_dir3_sfe_get_ftype(mp, sfp, sfep); + ino = dp->d_ops->sf_get_ino(sfp, sfep); + filetype = dp->d_ops->sf_get_ftype(sfep); ctx->pos = off & 0x7fffffff; if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino, xfs_dir3_get_dtype(mp, filetype))) diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 73881c9f40d6..ec0d39b5fa12 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -56,89 +56,6 @@ static void xfs_dir2_sf_toino4(xfs_da_args_t *args); static void xfs_dir2_sf_toino8(xfs_da_args_t *args); #endif /* XFS_BIG_INUMS */ -/* - * Inode numbers in short-form directories can come in two versions, - * either 4 bytes or 8 bytes wide. These helpers deal with the - * two forms transparently by looking at the headers i8count field. - * - * For 64-bit inode number the most significant byte must be zero. - */ -static xfs_ino_t -xfs_dir2_sf_get_ino( - struct xfs_dir2_sf_hdr *hdr, - xfs_dir2_inou_t *from) -{ - if (hdr->i8count) - return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL; - else - return get_unaligned_be32(&from->i4.i); -} - -static void -xfs_dir2_sf_put_ino( - struct xfs_dir2_sf_hdr *hdr, - xfs_dir2_inou_t *to, - xfs_ino_t ino) -{ - ASSERT((ino & 0xff00000000000000ULL) == 0); - - if (hdr->i8count) - put_unaligned_be64(ino, &to->i8.i); - else - put_unaligned_be32(ino, &to->i4.i); -} - -xfs_ino_t -xfs_dir2_sf_get_parent_ino( - struct xfs_dir2_sf_hdr *hdr) -{ - return xfs_dir2_sf_get_ino(hdr, &hdr->parent); -} - -void -xfs_dir2_sf_put_parent_ino( - struct xfs_dir2_sf_hdr *hdr, - xfs_ino_t ino) -{ - xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino); -} - -/* - * In short-form directory entries the inode numbers are stored at variable - * offset behind the entry name. If the entry stores a filetype value, then it - * sits between the name and the inode number. Hence the inode numbers may only - * be accessed through the helpers below. - */ -static xfs_dir2_inou_t * -xfs_dir3_sfe_inop( - struct xfs_mount *mp, - struct xfs_dir2_sf_entry *sfep) -{ - __uint8_t *ptr = &sfep->name[sfep->namelen]; - if (xfs_sb_version_hasftype(&mp->m_sb)) - ptr++; - return (xfs_dir2_inou_t *)ptr; -} - -xfs_ino_t -xfs_dir3_sfe_get_ino( - struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, - struct xfs_dir2_sf_entry *sfep) -{ - return xfs_dir2_sf_get_ino(hdr, xfs_dir3_sfe_inop(mp, sfep)); -} - -void -xfs_dir3_sfe_put_ino( - struct xfs_mount *mp, - struct xfs_dir2_sf_hdr *hdr, - struct xfs_dir2_sf_entry *sfep, - xfs_ino_t ino) -{ - xfs_dir2_sf_put_ino(hdr, xfs_dir3_sfe_inop(mp, sfep), ino); -} - /* * Given a block directory (dp/block), calculate its size as a shortform (sf) * directory and a header for the sf directory, if it will fit it the @@ -226,7 +143,7 @@ xfs_dir2_block_sfsize( */ sfhp->count = count; sfhp->i8count = i8count; - xfs_dir2_sf_put_parent_ino(sfhp, parent); + dp->d_ops->sf_put_parent_ino(sfhp, parent); return size; } @@ -321,7 +238,7 @@ xfs_dir2_block_to_sf( else if (dep->namelen == 2 && dep->name[0] == '.' && dep->name[1] == '.') ASSERT(be64_to_cpu(dep->inumber) == - xfs_dir2_sf_get_parent_ino(sfp)); + dp->d_ops->sf_get_parent_ino(sfp)); /* * Normal entry, copy it into shortform. */ @@ -331,9 +248,9 @@ xfs_dir2_block_to_sf( (xfs_dir2_data_aoff_t) ((char *)dep - (char *)hdr)); memcpy(sfep->name, dep->name, dep->namelen); - xfs_dir3_sfe_put_ino(mp, sfp, sfep, - be64_to_cpu(dep->inumber)); - xfs_dir3_sfe_put_ftype(mp, sfp, sfep, + dp->d_ops->sf_put_ino(sfp, sfep, + be64_to_cpu(dep->inumber)); + dp->d_ops->sf_put_ftype(sfep, xfs_dir3_dirent_get_ftype(mp, dep)); sfep = dp->d_ops->sf_nextentry(sfp, sfep); @@ -496,8 +413,8 @@ xfs_dir2_sf_addname_easy( sfep->namelen = args->namelen; xfs_dir2_sf_put_offset(sfep, offset); memcpy(sfep->name, args->name, sfep->namelen); - xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, args->inumber); - xfs_dir3_sfe_put_ftype(dp->i_mount, sfp, sfep, args->filetype); + dp->d_ops->sf_put_ino(sfp, sfep, args->inumber); + dp->d_ops->sf_put_ftype(sfep, args->filetype); /* * Update the header and inode. @@ -591,8 +508,8 @@ xfs_dir2_sf_addname_hard( sfep->namelen = args->namelen; xfs_dir2_sf_put_offset(sfep, offset); memcpy(sfep->name, args->name, sfep->namelen); - xfs_dir3_sfe_put_ino(mp, sfp, sfep, args->inumber); - xfs_dir3_sfe_put_ftype(mp, sfp, sfep, args->filetype); + dp->d_ops->sf_put_ino(sfp, sfep, args->inumber); + dp->d_ops->sf_put_ftype(sfep, args->filetype); sfp->count++; #if XFS_BIG_INUMS if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange) @@ -713,20 +630,19 @@ xfs_dir2_sf_check( sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; offset = xfs_dir3_data_first_offset(mp); - ino = xfs_dir2_sf_get_parent_ino(sfp); + ino = dp->d_ops->sf_get_parent_ino(sfp); i8count = ino > XFS_DIR2_MAX_SHORT_INUM; for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset); - ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep); + ino = dp->d_ops->sf_get_ino(sfp, sfep); i8count += ino > XFS_DIR2_MAX_SHORT_INUM; offset = xfs_dir2_sf_get_offset(sfep) + xfs_dir3_data_entsize(mp, sfep->namelen); - ASSERT(xfs_dir3_sfe_get_ftype(mp, sfp, sfep) < - XFS_DIR3_FT_MAX); + ASSERT(dp->d_ops->sf_get_ftype(sfep) < XFS_DIR3_FT_MAX); } ASSERT(i8count == sfp->i8count); ASSERT(XFS_BIG_INUMS || i8count == 0); @@ -782,7 +698,7 @@ xfs_dir2_sf_create( /* * Now can put in the inode number, since i8count is set. */ - xfs_dir2_sf_put_parent_ino(sfp, pino); + dp->d_ops->sf_put_parent_ino(sfp, pino); sfp->count = 0; dp->i_d.di_size = size; xfs_dir2_sf_check(args); @@ -837,7 +753,7 @@ xfs_dir2_sf_lookup( */ if (args->namelen == 2 && args->name[0] == '.' && args->name[1] == '.') { - args->inumber = xfs_dir2_sf_get_parent_ino(sfp); + args->inumber = dp->d_ops->sf_get_parent_ino(sfp); args->cmpresult = XFS_CMP_EXACT; args->filetype = XFS_DIR3_FT_DIR; return XFS_ERROR(EEXIST); @@ -857,10 +773,8 @@ xfs_dir2_sf_lookup( sfep->namelen); if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { args->cmpresult = cmp; - args->inumber = xfs_dir3_sfe_get_ino(dp->i_mount, - sfp, sfep); - args->filetype = xfs_dir3_sfe_get_ftype(dp->i_mount, - sfp, sfep); + args->inumber = dp->d_ops->sf_get_ino(sfp, sfep); + args->filetype = dp->d_ops->sf_get_ftype(sfep); if (cmp == XFS_CMP_EXACT) return XFS_ERROR(EEXIST); ci_sfep = sfep; @@ -919,7 +833,7 @@ xfs_dir2_sf_removename( i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { if (xfs_da_compname(args, sfep->name, sfep->namelen) == XFS_CMP_EXACT) { - ASSERT(xfs_dir3_sfe_get_ino(dp->i_mount, sfp, sfep) == + ASSERT(dp->d_ops->sf_get_ino(sfp, sfep) == args->inumber); break; } @@ -1040,10 +954,10 @@ xfs_dir2_sf_replace( if (args->namelen == 2 && args->name[0] == '.' && args->name[1] == '.') { #if XFS_BIG_INUMS || defined(DEBUG) - ino = xfs_dir2_sf_get_parent_ino(sfp); + ino = dp->d_ops->sf_get_parent_ino(sfp); ASSERT(args->inumber != ino); #endif - xfs_dir2_sf_put_parent_ino(sfp, args->inumber); + dp->d_ops->sf_put_parent_ino(sfp, args->inumber); } /* * Normal entry, look for the name. @@ -1054,14 +968,11 @@ xfs_dir2_sf_replace( if (xfs_da_compname(args, sfep->name, sfep->namelen) == XFS_CMP_EXACT) { #if XFS_BIG_INUMS || defined(DEBUG) - ino = xfs_dir3_sfe_get_ino(dp->i_mount, - sfp, sfep); + ino = dp->d_ops->sf_get_ino(sfp, sfep); ASSERT(args->inumber != ino); #endif - xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, - args->inumber); - xfs_dir3_sfe_put_ftype(dp->i_mount, sfp, sfep, - args->filetype); + dp->d_ops->sf_put_ino(sfp, sfep, args->inumber); + dp->d_ops->sf_put_ftype(sfep, args->filetype); break; } } @@ -1164,7 +1075,7 @@ xfs_dir2_sf_toino4( */ sfp->count = oldsfp->count; sfp->i8count = 0; - xfs_dir2_sf_put_parent_ino(sfp, xfs_dir2_sf_get_parent_ino(oldsfp)); + dp->d_ops->sf_put_parent_ino(sfp, dp->d_ops->sf_get_parent_ino(oldsfp)); /* * Copy the entries field by field. */ @@ -1176,10 +1087,9 @@ xfs_dir2_sf_toino4( sfep->namelen = oldsfep->namelen; sfep->offset = oldsfep->offset; memcpy(sfep->name, oldsfep->name, sfep->namelen); - xfs_dir3_sfe_put_ino(mp, sfp, sfep, - xfs_dir3_sfe_get_ino(mp, oldsfp, oldsfep)); - xfs_dir3_sfe_put_ftype(mp, sfp, sfep, - xfs_dir3_sfe_get_ftype(mp, oldsfp, oldsfep)); + dp->d_ops->sf_put_ino(sfp, sfep, + dp->d_ops->sf_get_ino(oldsfp, oldsfep)); + dp->d_ops->sf_put_ftype(sfep, dp->d_ops->sf_get_ftype(oldsfep)); } /* * Clean up the inode. @@ -1243,7 +1153,7 @@ xfs_dir2_sf_toino8( */ sfp->count = oldsfp->count; sfp->i8count = 1; - xfs_dir2_sf_put_parent_ino(sfp, xfs_dir2_sf_get_parent_ino(oldsfp)); + dp->d_ops->sf_put_parent_ino(sfp, dp->d_ops->sf_get_parent_ino(oldsfp)); /* * Copy the entries field by field. */ @@ -1255,10 +1165,9 @@ xfs_dir2_sf_toino8( sfep->namelen = oldsfep->namelen; sfep->offset = oldsfep->offset; memcpy(sfep->name, oldsfep->name, sfep->namelen); - xfs_dir3_sfe_put_ino(mp, sfp, sfep, - xfs_dir3_sfe_get_ino(mp, oldsfp, oldsfep)); - xfs_dir3_sfe_put_ftype(mp, sfp, sfep, - xfs_dir3_sfe_get_ftype(mp, oldsfp, oldsfep)); + dp->d_ops->sf_put_ino(sfp, sfep, + dp->d_ops->sf_get_ino(oldsfp, oldsfep)); + dp->d_ops->sf_put_ftype(sfep, dp->d_ops->sf_get_ftype(oldsfep)); } /* * Clean up the inode. -- cgit v1.2.3 From 9d23fc8575de7012b8853bd6fefe10534665de2f Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:48 +1100 Subject: xfs: vectorise directory data operations Following from the initial patches to vectorise the shortform directory encode/decode operations, convert half the data block operations to use the vector. The rest will be done in a second patch. This further reduces the size of the built binary: text data bss dec hex filename 794490 96802 1096 892388 d9de4 fs/xfs/xfs.o.orig 792986 96802 1096 890884 d9804 fs/xfs/xfs.o.p1 792350 96802 1096 890248 d9588 fs/xfs/xfs.o.p2 789293 96802 1096 887191 d8997 fs/xfs/xfs.o.p3 Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_da_format.c | 218 +++++++++++++++++++++++++++++++++++++++++++++- fs/xfs/xfs_da_format.h | 123 -------------------------- fs/xfs/xfs_dir2.h | 22 ++++- fs/xfs/xfs_dir2_block.c | 54 ++++++------ fs/xfs/xfs_dir2_data.c | 38 +++++--- fs/xfs/xfs_dir2_leaf.c | 22 ++--- fs/xfs/xfs_dir2_node.c | 23 ++--- fs/xfs/xfs_dir2_readdir.c | 14 +-- fs/xfs/xfs_dir2_sf.c | 20 ++--- 9 files changed, 329 insertions(+), 205 deletions(-) diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index 62f55a0186ae..d0285fdfb6e7 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c @@ -28,7 +28,9 @@ #include "xfs_inode.h" #include "xfs_dir2.h" - +/* + * Shortform directory ops + */ static int xfs_dir2_sf_entsize( struct xfs_dir2_sf_hdr *hdr, @@ -203,6 +205,184 @@ xfs_dir3_sfe_put_ino( (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1], ino); } + +/* + * Directory data block operations + */ +static int +__xfs_dir3_data_entsize( + bool ftype, + int n) +{ + int size = offsetof(struct xfs_dir2_data_entry, name[0]); + + size += n; + size += sizeof(xfs_dir2_data_off_t); + if (ftype) + size += sizeof(__uint8_t); + return roundup(size, XFS_DIR2_DATA_ALIGN); +} + +static int +xfs_dir2_data_entsize( + int n) +{ + return __xfs_dir3_data_entsize(false, n); +} +static int +xfs_dir3_data_entsize( + int n) +{ + return __xfs_dir3_data_entsize(true, n); +} + +static __uint8_t +xfs_dir2_data_get_ftype( + struct xfs_dir2_data_entry *dep) +{ + return XFS_DIR3_FT_UNKNOWN; +} + +static void +xfs_dir2_data_put_ftype( + struct xfs_dir2_data_entry *dep, + __uint8_t ftype) +{ + ASSERT(ftype < XFS_DIR3_FT_MAX); +} + +static __uint8_t +xfs_dir3_data_get_ftype( + struct xfs_dir2_data_entry *dep) +{ + __uint8_t ftype = dep->name[dep->namelen]; + + ASSERT(ftype < XFS_DIR3_FT_MAX); + if (ftype >= XFS_DIR3_FT_MAX) + return XFS_DIR3_FT_UNKNOWN; + return ftype; +} + +static void +xfs_dir3_data_put_ftype( + struct xfs_dir2_data_entry *dep, + __uint8_t type) +{ + ASSERT(type < XFS_DIR3_FT_MAX); + ASSERT(dep->namelen != 0); + + dep->name[dep->namelen] = type; +} + +/* + * Pointer to an entry's tag word. + */ +static __be16 * +xfs_dir2_data_entry_tag_p( + struct xfs_dir2_data_entry *dep) +{ + return (__be16 *)((char *)dep + + xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16)); +} + +static __be16 * +xfs_dir3_data_entry_tag_p( + struct xfs_dir2_data_entry *dep) +{ + return (__be16 *)((char *)dep + + xfs_dir3_data_entsize(dep->namelen) - sizeof(__be16)); +} + +/* + * Offsets of . and .. in data space (always block 0) + */ +static xfs_dir2_data_aoff_t +xfs_dir2_data_dot_offset(void) +{ + return sizeof(struct xfs_dir2_data_hdr); +} + +static xfs_dir2_data_aoff_t +xfs_dir2_data_dotdot_offset(void) +{ + return xfs_dir2_data_dot_offset() + xfs_dir2_data_entsize(1); +} + +static xfs_dir2_data_aoff_t +xfs_dir2_data_first_offset(void) +{ + return xfs_dir2_data_dotdot_offset() + xfs_dir2_data_entsize(2); +} + +static xfs_dir2_data_aoff_t +xfs_dir3_data_dot_offset(void) +{ + return sizeof(struct xfs_dir3_data_hdr); +} + +static xfs_dir2_data_aoff_t +xfs_dir3_data_dotdot_offset(void) +{ + return xfs_dir3_data_dot_offset() + xfs_dir3_data_entsize(1); +} + +static xfs_dir2_data_aoff_t +xfs_dir3_data_first_offset(void) +{ + return xfs_dir3_data_dotdot_offset() + xfs_dir3_data_entsize(2); +} + +/* + * location of . and .. in data space (always block 0) + */ +static struct xfs_dir2_data_entry * +xfs_dir2_data_dot_entry_p( + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir2_data_dot_offset()); +} + +static struct xfs_dir2_data_entry * +xfs_dir2_data_dotdot_entry_p( + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir2_data_dotdot_offset()); +} + +static struct xfs_dir2_data_entry * +xfs_dir2_data_first_entry_p( + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir2_data_first_offset()); +} + +static struct xfs_dir2_data_entry * +xfs_dir3_data_dot_entry_p( + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir3_data_dot_offset()); +} + +static struct xfs_dir2_data_entry * +xfs_dir3_data_dotdot_entry_p( + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir3_data_dotdot_offset()); +} + +static struct xfs_dir2_data_entry * +xfs_dir3_data_first_entry_p( + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir3_data_first_offset()); +} + const struct xfs_dir_ops xfs_dir2_ops = { .sf_entsize = xfs_dir2_sf_entsize, .sf_nextentry = xfs_dir2_sf_nextentry, @@ -212,6 +392,18 @@ const struct xfs_dir_ops xfs_dir2_ops = { .sf_put_ino = xfs_dir2_sfe_put_ino, .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, + + .data_entsize = xfs_dir2_data_entsize, + .data_get_ftype = xfs_dir2_data_get_ftype, + .data_put_ftype = xfs_dir2_data_put_ftype, + .data_entry_tag_p = xfs_dir2_data_entry_tag_p, + + .data_dot_offset = xfs_dir2_data_dot_offset, + .data_dotdot_offset = xfs_dir2_data_dotdot_offset, + .data_first_offset = xfs_dir2_data_first_offset, + .data_dot_entry_p = xfs_dir2_data_dot_entry_p, + .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p, + .data_first_entry_p = xfs_dir2_data_first_entry_p, }; const struct xfs_dir_ops xfs_dir2_ftype_ops = { @@ -223,6 +415,18 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = { .sf_put_ino = xfs_dir3_sfe_put_ino, .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, + + .data_entsize = xfs_dir3_data_entsize, + .data_get_ftype = xfs_dir3_data_get_ftype, + .data_put_ftype = xfs_dir3_data_put_ftype, + .data_entry_tag_p = xfs_dir3_data_entry_tag_p, + + .data_dot_offset = xfs_dir2_data_dot_offset, + .data_dotdot_offset = xfs_dir2_data_dotdot_offset, + .data_first_offset = xfs_dir2_data_first_offset, + .data_dot_entry_p = xfs_dir2_data_dot_entry_p, + .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p, + .data_first_entry_p = xfs_dir2_data_first_entry_p, }; const struct xfs_dir_ops xfs_dir3_ops = { @@ -234,4 +438,16 @@ const struct xfs_dir_ops xfs_dir3_ops = { .sf_put_ino = xfs_dir3_sfe_put_ino, .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, + + .data_entsize = xfs_dir3_data_entsize, + .data_get_ftype = xfs_dir3_data_get_ftype, + .data_put_ftype = xfs_dir3_data_put_ftype, + .data_entry_tag_p = xfs_dir3_data_entry_tag_p, + + .data_dot_offset = xfs_dir3_data_dot_offset, + .data_dotdot_offset = xfs_dir3_data_dotdot_offset, + .data_first_offset = xfs_dir3_data_first_offset, + .data_dot_entry_p = xfs_dir3_data_dot_entry_p, + .data_dotdot_entry_p = xfs_dir3_data_dotdot_entry_p, + .data_first_entry_p = xfs_dir3_data_first_entry_p, }; diff --git a/fs/xfs/xfs_da_format.h b/fs/xfs/xfs_da_format.h index 68c2ad5ba54f..5b72dd2f8a69 100644 --- a/fs/xfs/xfs_da_format.h +++ b/fs/xfs/xfs_da_format.h @@ -455,72 +455,6 @@ typedef struct xfs_dir2_data_unused { __be16 tag; /* starting offset of us */ } xfs_dir2_data_unused_t; -/* - * Size of a data entry. - */ -static inline int -__xfs_dir3_data_entsize( - bool ftype, - int n) -{ - int size = offsetof(struct xfs_dir2_data_entry, name[0]); - - size += n; - size += sizeof(xfs_dir2_data_off_t); - if (ftype) - size += sizeof(__uint8_t); - return roundup(size, XFS_DIR2_DATA_ALIGN); -} -static inline int -xfs_dir3_data_entsize( - struct xfs_mount *mp, - int n) -{ - bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false; - return __xfs_dir3_data_entsize(ftype, n); -} - -static inline __uint8_t -xfs_dir3_dirent_get_ftype( - struct xfs_mount *mp, - struct xfs_dir2_data_entry *dep) -{ - if (xfs_sb_version_hasftype(&mp->m_sb)) { - __uint8_t type = dep->name[dep->namelen]; - - ASSERT(type < XFS_DIR3_FT_MAX); - if (type < XFS_DIR3_FT_MAX) - return type; - - } - return XFS_DIR3_FT_UNKNOWN; -} - -static inline void -xfs_dir3_dirent_put_ftype( - struct xfs_mount *mp, - struct xfs_dir2_data_entry *dep, - __uint8_t type) -{ - ASSERT(type < XFS_DIR3_FT_MAX); - ASSERT(dep->namelen != 0); - - if (xfs_sb_version_hasftype(&mp->m_sb)) - dep->name[dep->namelen] = type; -} - -/* - * Pointer to an entry's tag word. - */ -static inline __be16 * -xfs_dir3_data_entry_tag_p( - struct xfs_mount *mp, - struct xfs_dir2_data_entry *dep) -{ - return (__be16 *)((char *)dep + - xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16)); -} - /* * Pointer to a freespace's tag word. */ @@ -561,63 +495,6 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) ((char *)hdr + xfs_dir3_data_entry_offset(hdr)); } -/* - * Offsets of . and .. in data space (always block 0) - * - * XXX: there is scope for significant optimisation of the logic here. Right - * now we are checking for "dir3 format" over and over again. Ideally we should - * only do it once for each operation. - */ -static inline xfs_dir2_data_aoff_t -xfs_dir3_data_dot_offset(struct xfs_mount *mp) -{ - return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)); -} - -static inline xfs_dir2_data_aoff_t -xfs_dir3_data_dotdot_offset(struct xfs_mount *mp) -{ - return xfs_dir3_data_dot_offset(mp) + - xfs_dir3_data_entsize(mp, 1); -} - -static inline xfs_dir2_data_aoff_t -xfs_dir3_data_first_offset(struct xfs_mount *mp) -{ - return xfs_dir3_data_dotdot_offset(mp) + - xfs_dir3_data_entsize(mp, 2); -} - -/* - * location of . and .. in data space (always block 0) - */ -static inline struct xfs_dir2_data_entry * -xfs_dir3_data_dot_entry_p( - struct xfs_mount *mp, - struct xfs_dir2_data_hdr *hdr) -{ - return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_dot_offset(mp)); -} - -static inline struct xfs_dir2_data_entry * -xfs_dir3_data_dotdot_entry_p( - struct xfs_mount *mp, - struct xfs_dir2_data_hdr *hdr) -{ - return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_dotdot_offset(mp)); -} - -static inline struct xfs_dir2_data_entry * -xfs_dir3_data_first_entry_p( - struct xfs_mount *mp, - struct xfs_dir2_data_hdr *hdr) -{ - return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_first_offset(mp)); -} - /* * Leaf block structures. * diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 0e94b3e662af..c0a45923cce0 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -50,6 +50,22 @@ struct xfs_dir_ops { xfs_ino_t (*sf_get_parent_ino)(struct xfs_dir2_sf_hdr *hdr); void (*sf_put_parent_ino)(struct xfs_dir2_sf_hdr *hdr, xfs_ino_t ino); + + int (*data_entsize)(int len); + __uint8_t (*data_get_ftype)(struct xfs_dir2_data_entry *dep); + void (*data_put_ftype)(struct xfs_dir2_data_entry *dep, + __uint8_t ftype); + __be16 * (*data_entry_tag_p)(struct xfs_dir2_data_entry *dep); + + xfs_dir2_data_aoff_t (*data_dot_offset)(void); + xfs_dir2_data_aoff_t (*data_dotdot_offset)(void); + xfs_dir2_data_aoff_t (*data_first_offset)(void); + struct xfs_dir2_data_entry * + (*data_dot_entry_p)(struct xfs_dir2_data_hdr *hdr); + struct xfs_dir2_data_entry * + (*data_dotdot_entry_p)(struct xfs_dir2_data_hdr *hdr); + struct xfs_dir2_data_entry * + (*data_first_entry_p)(struct xfs_dir2_data_hdr *hdr); }; extern const struct xfs_dir_ops xfs_dir2_ops; @@ -95,10 +111,10 @@ extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r); extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, struct xfs_buf *bp); -extern void xfs_dir2_data_freescan(struct xfs_mount *mp, +extern void xfs_dir2_data_freescan(struct xfs_inode *dp, struct xfs_dir2_data_hdr *hdr, int *loghead); -extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_buf *bp, - struct xfs_dir2_data_entry *dep); +extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_inode *dp, + struct xfs_buf *bp, struct xfs_dir2_data_entry *dep); extern void xfs_dir2_data_log_header(struct xfs_trans *tp, struct xfs_buf *bp); extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_buf *bp, diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 960f3ab526f6..507ef6a7d1f9 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -280,6 +280,7 @@ out: static void xfs_dir2_block_compact( struct xfs_trans *tp, + struct xfs_inode *dp, struct xfs_buf *bp, struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_block_tail *btp, @@ -323,7 +324,7 @@ xfs_dir2_block_compact( * This needs to happen before the next call to use_free. */ if (needscan) - xfs_dir2_data_freescan(tp->t_mountp, hdr, needlog); + xfs_dir2_data_freescan(dp, hdr, needlog); } /* @@ -369,7 +370,7 @@ xfs_dir2_block_addname( if (error) return error; - len = xfs_dir3_data_entsize(mp, args->namelen); + len = dp->d_ops->data_entsize(args->namelen); /* * Set up pointers to parts of the block. @@ -418,7 +419,7 @@ xfs_dir2_block_addname( * If need to compact the leaf entries, do it now. */ if (compact) { - xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog, + xfs_dir2_block_compact(tp, dp, bp, hdr, btp, blp, &needlog, &lfloghigh, &lfloglow); /* recalculate blp post-compaction */ blp = xfs_dir2_block_leaf_p(btp); @@ -468,7 +469,7 @@ xfs_dir2_block_addname( * This needs to happen before the next call to use_free. */ if (needscan) { - xfs_dir2_data_freescan(mp, hdr, &needlog); + xfs_dir2_data_freescan(dp, hdr, &needlog); needscan = 0; } /* @@ -549,18 +550,18 @@ xfs_dir2_block_addname( dep->inumber = cpu_to_be64(args->inumber); dep->namelen = args->namelen; memcpy(dep->name, args->name, args->namelen); - xfs_dir3_dirent_put_ftype(mp, dep, args->filetype); - tagp = xfs_dir3_data_entry_tag_p(mp, dep); + dp->d_ops->data_put_ftype(dep, args->filetype); + tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); /* * Clean up the bestfree array and log the header, tail, and entry. */ if (needscan) - xfs_dir2_data_freescan(mp, hdr, &needlog); + xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(tp, bp); xfs_dir2_block_log_tail(tp, bp); - xfs_dir2_data_log_entry(tp, bp, dep); + xfs_dir2_data_log_entry(tp, dp, bp, dep); xfs_dir3_data_check(dp, bp); return 0; } @@ -642,7 +643,7 @@ xfs_dir2_block_lookup( * Fill in inode number, CI name if appropriate, release the block. */ args->inumber = be64_to_cpu(dep->inumber); - args->filetype = xfs_dir3_dirent_get_ftype(mp, dep); + args->filetype = dp->d_ops->data_get_ftype(dep); error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); xfs_trans_brelse(args->trans, bp); return XFS_ERROR(error); @@ -801,7 +802,7 @@ xfs_dir2_block_removename( needlog = needscan = 0; xfs_dir2_data_make_free(tp, bp, (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), - xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan); + dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); /* * Fix up the block tail. */ @@ -816,7 +817,7 @@ xfs_dir2_block_removename( * Fix up bestfree, log the header if necessary. */ if (needscan) - xfs_dir2_data_freescan(mp, hdr, &needlog); + xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(tp, bp); xfs_dir3_data_check(dp, bp); @@ -875,8 +876,8 @@ xfs_dir2_block_replace( * Change the inode number to the new value. */ dep->inumber = cpu_to_be64(args->inumber); - xfs_dir3_dirent_put_ftype(mp, dep, args->filetype); - xfs_dir2_data_log_entry(args->trans, bp, dep); + dp->d_ops->data_put_ftype(dep, args->filetype); + xfs_dir2_data_log_entry(args->trans, dp, bp, dep); xfs_dir3_data_check(dp, bp); return 0; } @@ -1023,7 +1024,7 @@ xfs_dir2_leaf_to_block( * Scan the bestfree if we need it and log the data block header. */ if (needscan) - xfs_dir2_data_freescan(mp, hdr, &needlog); + xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(tp, dbp); /* @@ -1158,32 +1159,32 @@ xfs_dir2_sf_to_block( /* * Create entry for . */ - dep = xfs_dir3_data_dot_entry_p(mp, hdr); + dep = dp->d_ops->data_dot_entry_p(hdr); dep->inumber = cpu_to_be64(dp->i_ino); dep->namelen = 1; dep->name[0] = '.'; - xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR); - tagp = xfs_dir3_data_entry_tag_p(mp, dep); + dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR); + tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); - xfs_dir2_data_log_entry(tp, bp, dep); + xfs_dir2_data_log_entry(tp, dp, bp, dep); blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot); blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, (char *)dep - (char *)hdr)); /* * Create entry for .. */ - dep = xfs_dir3_data_dotdot_entry_p(mp, hdr); + dep = dp->d_ops->data_dotdot_entry_p(hdr); dep->inumber = cpu_to_be64(dp->d_ops->sf_get_parent_ino(sfp)); dep->namelen = 2; dep->name[0] = dep->name[1] = '.'; - xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR); - tagp = xfs_dir3_data_entry_tag_p(mp, dep); + dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR); + tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); - xfs_dir2_data_log_entry(tp, bp, dep); + xfs_dir2_data_log_entry(tp, dp, bp, dep); blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, (char *)dep - (char *)hdr)); - offset = xfs_dir3_data_first_offset(mp); + offset = dp->d_ops->data_first_offset(); /* * Loop over existing entries, stuff them in. */ @@ -1224,12 +1225,11 @@ xfs_dir2_sf_to_block( dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset); dep->inumber = cpu_to_be64(dp->d_ops->sf_get_ino(sfp, sfep)); dep->namelen = sfep->namelen; - xfs_dir3_dirent_put_ftype(mp, dep, - dp->d_ops->sf_get_ftype(sfep)); + dp->d_ops->data_put_ftype(dep, dp->d_ops->sf_get_ftype(sfep)); memcpy(dep->name, sfep->name, dep->namelen); - tagp = xfs_dir3_data_entry_tag_p(mp, dep); + tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); - xfs_dir2_data_log_entry(tp, bp, dep); + xfs_dir2_data_log_entry(tp, dp, bp, dep); name.name = sfep->name; name.len = sfep->namelen; blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops-> diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index ccfeb4d8376a..00006b3db054 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -62,12 +62,26 @@ __xfs_dir3_data_check( char *p; /* current data position */ int stale; /* count of stale leaves */ struct xfs_name name; + const struct xfs_dir_ops *ops; mp = bp->b_target->bt_mount; hdr = bp->b_addr; bf = xfs_dir3_data_bestfree_p(hdr); p = (char *)xfs_dir3_data_entry_p(hdr); + /* + * We can be passed a null dp here from a verifier, so manually + * configure the ops here in that case. + */ + if (dp) + ops = dp->d_ops; + else if (xfs_sb_version_hascrc(&mp->m_sb)) + ops = &xfs_dir3_ops; + else if (xfs_sb_version_hasftype(&mp->m_sb)) + ops = &xfs_dir2_ftype_ops; + else + ops = &xfs_dir2_ops; + switch (hdr->magic) { case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): @@ -146,10 +160,10 @@ __xfs_dir3_data_check( XFS_WANT_CORRUPTED_RETURN( !xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber))); XFS_WANT_CORRUPTED_RETURN( - be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)) == + be16_to_cpu(*ops->data_entry_tag_p(dep)) == (char *)dep - (char *)hdr); XFS_WANT_CORRUPTED_RETURN( - xfs_dir3_dirent_get_ftype(mp, dep) < XFS_DIR3_FT_MAX); + ops->data_get_ftype(dep) < XFS_DIR3_FT_MAX); count++; lastfree = 0; if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || @@ -167,7 +181,7 @@ __xfs_dir3_data_check( } XFS_WANT_CORRUPTED_RETURN(i < be32_to_cpu(btp->count)); } - p += xfs_dir3_data_entsize(mp, dep->namelen); + p += ops->data_entsize(dep->namelen); } /* * Need to have seen all the entries and all the bestfree slots. @@ -485,9 +499,9 @@ xfs_dir2_data_freeremove( */ void xfs_dir2_data_freescan( - xfs_mount_t *mp, /* filesystem mount point */ - xfs_dir2_data_hdr_t *hdr, /* data block header */ - int *loghead) /* out: log data header */ + struct xfs_inode *dp, + struct xfs_dir2_data_hdr *hdr, + int *loghead) { xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* active data entry */ @@ -513,10 +527,10 @@ xfs_dir2_data_freescan( p = (char *)xfs_dir3_data_entry_p(hdr); if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { - btp = xfs_dir2_block_tail_p(mp, hdr); + btp = xfs_dir2_block_tail_p(dp->i_mount, hdr); endp = (char *)xfs_dir2_block_leaf_p(btp); } else - endp = (char *)hdr + mp->m_dirblksize; + endp = (char *)hdr + dp->i_mount->m_dirblksize; /* * Loop over the block's entries. */ @@ -537,8 +551,8 @@ xfs_dir2_data_freescan( else { dep = (xfs_dir2_data_entry_t *)p; ASSERT((char *)dep - (char *)hdr == - be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep))); - p += xfs_dir3_data_entsize(mp, dep->namelen); + be16_to_cpu(*dp->d_ops->data_entry_tag_p(dep))); + p += dp->d_ops->data_entsize(dep->namelen); } } } @@ -625,11 +639,11 @@ xfs_dir3_data_init( void xfs_dir2_data_log_entry( struct xfs_trans *tp, + struct xfs_inode *dp, struct xfs_buf *bp, xfs_dir2_data_entry_t *dep) /* data entry pointer */ { struct xfs_dir2_data_hdr *hdr = bp->b_addr; - struct xfs_mount *mp = tp->t_mountp; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || @@ -637,7 +651,7 @@ xfs_dir2_data_log_entry( hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr), - (uint)((char *)(xfs_dir3_data_entry_tag_p(mp, dep) + 1) - + (uint)((char *)(dp->d_ops->data_entry_tag_p(dep) + 1) - (char *)hdr - 1)); } diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 51fdc11a1e2c..dd195363ccf2 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -500,7 +500,7 @@ xfs_dir2_block_to_leaf( hdr->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC); if (needscan) - xfs_dir2_data_freescan(mp, hdr, &needlog); + xfs_dir2_data_freescan(dp, hdr, &needlog); /* * Set up leaf tail and bests table. */ @@ -700,7 +700,7 @@ xfs_dir2_leaf_addname( ents = xfs_dir3_leaf_ents_p(leaf); xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); bestsp = xfs_dir2_leaf_bests_p(ltp); - length = xfs_dir3_data_entsize(mp, args->namelen); + length = dp->d_ops->data_entsize(args->namelen); /* * See if there are any entries with the same hash value @@ -901,20 +901,20 @@ xfs_dir2_leaf_addname( dep->inumber = cpu_to_be64(args->inumber); dep->namelen = args->namelen; memcpy(dep->name, args->name, dep->namelen); - xfs_dir3_dirent_put_ftype(mp, dep, args->filetype); - tagp = xfs_dir3_data_entry_tag_p(mp, dep); + dp->d_ops->data_put_ftype(dep, args->filetype); + tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); /* * Need to scan fix up the bestfree table. */ if (needscan) - xfs_dir2_data_freescan(mp, hdr, &needlog); + xfs_dir2_data_freescan(dp, hdr, &needlog); /* * Need to log the data block's header. */ if (needlog) xfs_dir2_data_log_header(tp, dbp); - xfs_dir2_data_log_entry(tp, dbp, dep); + xfs_dir2_data_log_entry(tp, dp, dbp, dep); /* * If the bests table needs to be changed, do it. * Log the change unless we've already done that. @@ -1230,7 +1230,7 @@ xfs_dir2_leaf_lookup( * Return the found inode number & CI name if appropriate */ args->inumber = be64_to_cpu(dep->inumber); - args->filetype = xfs_dir3_dirent_get_ftype(dp->i_mount, dep); + args->filetype = dp->d_ops->data_get_ftype(dep); error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); xfs_trans_brelse(tp, dbp); xfs_trans_brelse(tp, lbp); @@ -1433,7 +1433,7 @@ xfs_dir2_leaf_removename( */ xfs_dir2_data_make_free(tp, dbp, (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), - xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan); + dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); /* * We just mark the leaf entry stale by putting a null in it. */ @@ -1449,7 +1449,7 @@ xfs_dir2_leaf_removename( * log the data block header if necessary. */ if (needscan) - xfs_dir2_data_freescan(mp, hdr, &needlog); + xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(tp, dbp); /* @@ -1561,9 +1561,9 @@ xfs_dir2_leaf_replace( * Put the new inode number in, log it. */ dep->inumber = cpu_to_be64(args->inumber); - xfs_dir3_dirent_put_ftype(dp->i_mount, dep, args->filetype); + dp->d_ops->data_put_ftype(dep, args->filetype); tp = args->trans; - xfs_dir2_data_log_entry(tp, dbp, dep); + xfs_dir2_data_log_entry(tp, dp, dbp, dep); xfs_dir3_leaf_check(dp->i_mount, lbp); xfs_trans_brelse(tp, lbp); return 0; diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index b8381646b8af..a1d133981c14 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -604,7 +604,7 @@ xfs_dir2_leafn_lookup_for_addname( ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); } - length = xfs_dir3_data_entsize(mp, args->namelen); + length = dp->d_ops->data_entsize(args->namelen); /* * Loop over leaf entries with the right hash value. */ @@ -815,7 +815,7 @@ xfs_dir2_leafn_lookup_for_entry( xfs_trans_brelse(tp, state->extrablk.bp); args->cmpresult = cmp; args->inumber = be64_to_cpu(dep->inumber); - args->filetype = xfs_dir3_dirent_get_ftype(mp, dep); + args->filetype = dp->d_ops->data_get_ftype(dep); *indexp = index; state->extravalid = 1; state->extrablk.bp = curbp; @@ -1259,13 +1259,13 @@ xfs_dir2_leafn_remove( longest = be16_to_cpu(bf[0].length); needlog = needscan = 0; xfs_dir2_data_make_free(tp, dbp, off, - xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan); + dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); /* * Rescan the data block freespaces for bestfree. * Log the data block header if needed. */ if (needscan) - xfs_dir2_data_freescan(mp, hdr, &needlog); + xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) xfs_dir2_data_log_header(tp, dbp); xfs_dir3_data_check(dp, dbp); @@ -1711,7 +1711,7 @@ xfs_dir2_node_addname_int( dp = args->dp; mp = dp->i_mount; tp = args->trans; - length = xfs_dir3_data_entsize(mp, args->namelen); + length = dp->d_ops->data_entsize(args->namelen); /* * If we came in with a freespace block that means that lookup * found an entry with our hash value. This is the freespace @@ -2007,15 +2007,15 @@ xfs_dir2_node_addname_int( dep->inumber = cpu_to_be64(args->inumber); dep->namelen = args->namelen; memcpy(dep->name, args->name, dep->namelen); - xfs_dir3_dirent_put_ftype(mp, dep, args->filetype); - tagp = xfs_dir3_data_entry_tag_p(mp, dep); + dp->d_ops->data_put_ftype(dep, args->filetype); + tagp = dp->d_ops->data_entry_tag_p(dep); *tagp = cpu_to_be16((char *)dep - (char *)hdr); - xfs_dir2_data_log_entry(tp, dbp, dep); + xfs_dir2_data_log_entry(tp, dp, dbp, dep); /* * Rescan the block for bestfree if needed. */ if (needscan) - xfs_dir2_data_freescan(mp, hdr, &needlog); + xfs_dir2_data_freescan(dp, hdr, &needlog); /* * Log the data block header if needed. */ @@ -2228,8 +2228,9 @@ xfs_dir2_node_replace( * Fill in the new inode number and log the entry. */ dep->inumber = cpu_to_be64(inum); - xfs_dir3_dirent_put_ftype(state->mp, dep, args->filetype); - xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep); + args->dp->d_ops->data_put_ftype(dep, args->filetype); + xfs_dir2_data_log_entry(args->trans, args->dp, + state->extrablk.bp, dep); rval = 0; } /* diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 2d2c8fb05541..b99aa7d48e90 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -119,9 +119,9 @@ xfs_dir2_sf_getdents( * mp->m_dirdatablk. */ dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, - xfs_dir3_data_dot_offset(mp)); + dp->d_ops->data_dot_offset()); dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, - xfs_dir3_data_dotdot_offset(mp)); + dp->d_ops->data_dotdot_offset()); /* * Put . entry unless we're starting past it. @@ -237,7 +237,7 @@ xfs_dir2_block_getdents( /* * Bump pointer for the next iteration. */ - ptr += xfs_dir3_data_entsize(mp, dep->namelen); + ptr += dp->d_ops->data_entsize(dep->namelen); /* * The entry is before the desired starting point, skip it. */ @@ -248,7 +248,7 @@ xfs_dir2_block_getdents( (char *)dep - (char *)hdr); ctx->pos = cook & 0x7fffffff; - filetype = xfs_dir3_dirent_get_ftype(mp, dep); + filetype = dp->d_ops->data_get_ftype(dep); /* * If it didn't fit, set the final offset to here & return. */ @@ -601,7 +601,7 @@ xfs_dir2_leaf_getdents( } dep = (xfs_dir2_data_entry_t *)ptr; length = - xfs_dir3_data_entsize(mp, dep->namelen); + dp->d_ops->data_entsize(dep->namelen); ptr += length; } /* @@ -632,8 +632,8 @@ xfs_dir2_leaf_getdents( } dep = (xfs_dir2_data_entry_t *)ptr; - length = xfs_dir3_data_entsize(mp, dep->namelen); - filetype = xfs_dir3_dirent_get_ftype(mp, dep); + length = dp->d_ops->data_entsize(dep->namelen); + filetype = dp->d_ops->data_get_ftype(dep); ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; if (!dir_emit(ctx, (char *)dep->name, dep->namelen, diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index ec0d39b5fa12..953e19479151 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -251,11 +251,11 @@ xfs_dir2_block_to_sf( dp->d_ops->sf_put_ino(sfp, sfep, be64_to_cpu(dep->inumber)); dp->d_ops->sf_put_ftype(sfep, - xfs_dir3_dirent_get_ftype(mp, dep)); + dp->d_ops->data_get_ftype(dep)); sfep = dp->d_ops->sf_nextentry(sfp, sfep); } - ptr += xfs_dir3_data_entsize(mp, dep->namelen); + ptr += dp->d_ops->data_entsize(dep->namelen); } ASSERT((char *)sfep - (char *)sfp == size); xfs_dir2_sf_check(args); @@ -473,12 +473,12 @@ xfs_dir2_sf_addname_hard( * to insert the new entry. * If it's going to end up at the end then oldsfep will point there. */ - for (offset = xfs_dir3_data_first_offset(mp), + for (offset = dp->d_ops->data_first_offset(), oldsfep = xfs_dir2_sf_firstentry(oldsfp), - add_datasize = xfs_dir3_data_entsize(mp, args->namelen), + add_datasize = dp->d_ops->data_entsize(args->namelen), eof = (char *)oldsfep == &buf[old_isize]; !eof; - offset = new_offset + xfs_dir3_data_entsize(mp, oldsfep->namelen), + offset = new_offset + dp->d_ops->data_entsize(oldsfep->namelen), oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep), eof = (char *)oldsfep == &buf[old_isize]) { new_offset = xfs_dir2_sf_get_offset(oldsfep); @@ -555,8 +555,8 @@ xfs_dir2_sf_addname_pick( mp = dp->i_mount; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; - size = xfs_dir3_data_entsize(mp, args->namelen); - offset = xfs_dir3_data_first_offset(mp); + size = dp->d_ops->data_entsize(args->namelen); + offset = dp->d_ops->data_first_offset(); sfep = xfs_dir2_sf_firstentry(sfp); holefit = 0; /* @@ -568,7 +568,7 @@ xfs_dir2_sf_addname_pick( if (!holefit) holefit = offset + size <= xfs_dir2_sf_get_offset(sfep); offset = xfs_dir2_sf_get_offset(sfep) + - xfs_dir3_data_entsize(mp, sfep->namelen); + dp->d_ops->data_entsize(sfep->namelen); sfep = dp->d_ops->sf_nextentry(sfp, sfep); } /* @@ -629,7 +629,7 @@ xfs_dir2_sf_check( mp = dp->i_mount; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; - offset = xfs_dir3_data_first_offset(mp); + offset = dp->d_ops->data_first_offset(); ino = dp->d_ops->sf_get_parent_ino(sfp); i8count = ino > XFS_DIR2_MAX_SHORT_INUM; @@ -641,7 +641,7 @@ xfs_dir2_sf_check( i8count += ino > XFS_DIR2_MAX_SHORT_INUM; offset = xfs_dir2_sf_get_offset(sfep) + - xfs_dir3_data_entsize(mp, sfep->namelen); + dp->d_ops->data_entsize(sfep->namelen); ASSERT(dp->d_ops->sf_get_ftype(sfep) < XFS_DIR3_FT_MAX); } ASSERT(i8count == sfp->i8count); -- cgit v1.2.3 From 2ca9877410594dd321621efc9e1cbcd1ca24d0f3 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:49 +1100 Subject: xfs: vectorise directory data operations part 2 Convert the rest of the directory data block encode/decode operations to vector format. This further reduces the size of the built binary: text data bss dec hex filename 794490 96802 1096 892388 d9de4 fs/xfs/xfs.o.orig 792986 96802 1096 890884 d9804 fs/xfs/xfs.o.p1 792350 96802 1096 890248 d9588 fs/xfs/xfs.o.p2 789293 96802 1096 887191 d8997 fs/xfs/xfs.o.p3 789005 96802 1096 886903 d8997 fs/xfs/xfs.o.p4 Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_da_format.c | 68 +++++++++++++++++++++++++++++ fs/xfs/xfs_da_format.h | 41 ------------------ fs/xfs/xfs_dir2.h | 22 +++++++--- fs/xfs/xfs_dir2_block.c | 33 ++++++++------- fs/xfs/xfs_dir2_data.c | 106 +++++++++++++++++++++++++--------------------- fs/xfs/xfs_dir2_leaf.c | 26 ++++++------ fs/xfs/xfs_dir2_node.c | 16 +++---- fs/xfs/xfs_dir2_priv.h | 3 +- fs/xfs/xfs_dir2_readdir.c | 6 +-- fs/xfs/xfs_dir2_sf.c | 2 +- 10 files changed, 186 insertions(+), 137 deletions(-) diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index d0285fdfb6e7..1e92a241fd52 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c @@ -383,6 +383,58 @@ xfs_dir3_data_first_entry_p( ((char *)hdr + xfs_dir3_data_first_offset()); } +static struct xfs_dir2_data_free * +xfs_dir2_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) +{ + return hdr->bestfree; +} + +static struct xfs_dir2_data_free * +xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) +{ + return ((struct xfs_dir3_data_hdr *)hdr)->best_free; +} + +static size_t +xfs_dir2_data_entry_offset(void) +{ + return sizeof(struct xfs_dir2_data_hdr); +} + +static struct xfs_dir2_data_entry * +xfs_dir2_data_entry_p(struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir2_data_entry_offset()); +} + +static struct xfs_dir2_data_unused * +xfs_dir2_data_unused_p(struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_unused *) + ((char *)hdr + xfs_dir2_data_entry_offset()); +} + +static size_t +xfs_dir3_data_entry_offset(void) +{ + return sizeof(struct xfs_dir3_data_hdr); +} + +static struct xfs_dir2_data_entry * +xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + xfs_dir3_data_entry_offset()); +} + +static struct xfs_dir2_data_unused * +xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_unused *) + ((char *)hdr + xfs_dir3_data_entry_offset()); +} + const struct xfs_dir_ops xfs_dir2_ops = { .sf_entsize = xfs_dir2_sf_entsize, .sf_nextentry = xfs_dir2_sf_nextentry, @@ -397,13 +449,19 @@ const struct xfs_dir_ops xfs_dir2_ops = { .data_get_ftype = xfs_dir2_data_get_ftype, .data_put_ftype = xfs_dir2_data_put_ftype, .data_entry_tag_p = xfs_dir2_data_entry_tag_p, + .data_bestfree_p = xfs_dir2_data_bestfree_p, .data_dot_offset = xfs_dir2_data_dot_offset, .data_dotdot_offset = xfs_dir2_data_dotdot_offset, .data_first_offset = xfs_dir2_data_first_offset, + .data_entry_offset = xfs_dir2_data_entry_offset, + .data_dot_entry_p = xfs_dir2_data_dot_entry_p, .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p, .data_first_entry_p = xfs_dir2_data_first_entry_p, + .data_entry_p = xfs_dir2_data_entry_p, + .data_unused_p = xfs_dir2_data_unused_p, + }; const struct xfs_dir_ops xfs_dir2_ftype_ops = { @@ -420,13 +478,18 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = { .data_get_ftype = xfs_dir3_data_get_ftype, .data_put_ftype = xfs_dir3_data_put_ftype, .data_entry_tag_p = xfs_dir3_data_entry_tag_p, + .data_bestfree_p = xfs_dir2_data_bestfree_p, .data_dot_offset = xfs_dir2_data_dot_offset, .data_dotdot_offset = xfs_dir2_data_dotdot_offset, .data_first_offset = xfs_dir2_data_first_offset, + .data_entry_offset = xfs_dir2_data_entry_offset, + .data_dot_entry_p = xfs_dir2_data_dot_entry_p, .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p, .data_first_entry_p = xfs_dir2_data_first_entry_p, + .data_entry_p = xfs_dir2_data_entry_p, + .data_unused_p = xfs_dir2_data_unused_p, }; const struct xfs_dir_ops xfs_dir3_ops = { @@ -443,11 +506,16 @@ const struct xfs_dir_ops xfs_dir3_ops = { .data_get_ftype = xfs_dir3_data_get_ftype, .data_put_ftype = xfs_dir3_data_put_ftype, .data_entry_tag_p = xfs_dir3_data_entry_tag_p, + .data_bestfree_p = xfs_dir3_data_bestfree_p, .data_dot_offset = xfs_dir3_data_dot_offset, .data_dotdot_offset = xfs_dir3_data_dotdot_offset, .data_first_offset = xfs_dir3_data_first_offset, + .data_entry_offset = xfs_dir3_data_entry_offset, + .data_dot_entry_p = xfs_dir3_data_dot_entry_p, .data_dotdot_entry_p = xfs_dir3_data_dotdot_entry_p, .data_first_entry_p = xfs_dir3_data_first_entry_p, + .data_entry_p = xfs_dir3_data_entry_p, + .data_unused_p = xfs_dir3_data_unused_p, }; diff --git a/fs/xfs/xfs_da_format.h b/fs/xfs/xfs_da_format.h index 5b72dd2f8a69..aeca0038a013 100644 --- a/fs/xfs/xfs_da_format.h +++ b/fs/xfs/xfs_da_format.h @@ -412,17 +412,6 @@ struct xfs_dir3_data_hdr { #define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc) -static inline struct xfs_dir2_data_free * -xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) -{ - if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || - hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { - struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr; - return hdr3->best_free; - } - return hdr->bestfree; -} - /* * Active entry in a data block. * @@ -465,36 +454,6 @@ xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) be16_to_cpu(dup->length) - sizeof(__be16)); } -static inline size_t -xfs_dir3_data_hdr_size(bool dir3) -{ - if (dir3) - return sizeof(struct xfs_dir3_data_hdr); - return sizeof(struct xfs_dir2_data_hdr); -} - -static inline size_t -xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr) -{ - bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || - hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); - return xfs_dir3_data_hdr_size(dir3); -} - -static inline struct xfs_dir2_data_entry * -xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) -{ - return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_entry_offset(hdr)); -} - -static inline struct xfs_dir2_data_unused * -xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) -{ - return (struct xfs_dir2_data_unused *) - ((char *)hdr + xfs_dir3_data_entry_offset(hdr)); -} - /* * Leaf block structures. * diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index c0a45923cce0..076010a1376a 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -56,16 +56,24 @@ struct xfs_dir_ops { void (*data_put_ftype)(struct xfs_dir2_data_entry *dep, __uint8_t ftype); __be16 * (*data_entry_tag_p)(struct xfs_dir2_data_entry *dep); + struct xfs_dir2_data_free * + (*data_bestfree_p)(struct xfs_dir2_data_hdr *hdr); xfs_dir2_data_aoff_t (*data_dot_offset)(void); xfs_dir2_data_aoff_t (*data_dotdot_offset)(void); xfs_dir2_data_aoff_t (*data_first_offset)(void); + size_t (*data_entry_offset)(void); + struct xfs_dir2_data_entry * (*data_dot_entry_p)(struct xfs_dir2_data_hdr *hdr); struct xfs_dir2_data_entry * (*data_dotdot_entry_p)(struct xfs_dir2_data_hdr *hdr); struct xfs_dir2_data_entry * (*data_first_entry_p)(struct xfs_dir2_data_hdr *hdr); + struct xfs_dir2_data_entry * + (*data_entry_p)(struct xfs_dir2_data_hdr *hdr); + struct xfs_dir2_data_unused * + (*data_unused_p)(struct xfs_dir2_data_hdr *hdr); }; extern const struct xfs_dir_ops xfs_dir2_ops; @@ -115,19 +123,21 @@ extern void xfs_dir2_data_freescan(struct xfs_inode *dp, struct xfs_dir2_data_hdr *hdr, int *loghead); extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_buf *bp, struct xfs_dir2_data_entry *dep); -extern void xfs_dir2_data_log_header(struct xfs_trans *tp, +extern void xfs_dir2_data_log_header(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_buf *bp); extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_buf *bp, struct xfs_dir2_data_unused *dup); -extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_buf *bp, +extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_inode *dp, + struct xfs_buf *bp, xfs_dir2_data_aoff_t offset, + xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); +extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_inode *dp, + struct xfs_buf *bp, struct xfs_dir2_data_unused *dup, xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); -extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp, - struct xfs_dir2_data_unused *dup, xfs_dir2_data_aoff_t offset, - xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); extern struct xfs_dir2_data_free *xfs_dir2_data_freefind( - struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_unused *dup); + struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf, + struct xfs_dir2_data_unused *dup); extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 507ef6a7d1f9..f92ca5699342 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -168,6 +168,7 @@ xfs_dir3_block_init( static void xfs_dir2_block_need_space( + struct xfs_inode *dp, struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_block_tail *btp, struct xfs_dir2_leaf_entry *blp, @@ -183,7 +184,7 @@ xfs_dir2_block_need_space( struct xfs_dir2_data_unused *enddup = NULL; *compact = 0; - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); /* * If there are stale entries we'll use one for the leaf. @@ -313,7 +314,7 @@ xfs_dir2_block_compact( *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1); *lfloghigh -= be32_to_cpu(btp->stale) - 1; be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1)); - xfs_dir2_data_make_free(tp, bp, + xfs_dir2_data_make_free(tp, dp, bp, (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)), needlog, &needscan); @@ -383,7 +384,7 @@ xfs_dir2_block_addname( * Find out if we can reuse stale entries or whether we need extra * space for entry and new leaf. */ - xfs_dir2_block_need_space(hdr, btp, blp, &tagp, &dup, + xfs_dir2_block_need_space(dp, hdr, btp, blp, &tagp, &dup, &enddup, &compact, len); /* @@ -454,7 +455,7 @@ xfs_dir2_block_addname( /* * Mark the space needed for the new leaf entry, now in use. */ - xfs_dir2_data_use_free(tp, bp, enddup, + xfs_dir2_data_use_free(tp, dp, bp, enddup, (xfs_dir2_data_aoff_t) ((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) - sizeof(*blp)), @@ -541,7 +542,7 @@ xfs_dir2_block_addname( /* * Mark space for the data entry used. */ - xfs_dir2_data_use_free(tp, bp, dup, + xfs_dir2_data_use_free(tp, dp, bp, dup, (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), (xfs_dir2_data_aoff_t)len, &needlog, &needscan); /* @@ -559,7 +560,7 @@ xfs_dir2_block_addname( if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) - xfs_dir2_data_log_header(tp, bp); + xfs_dir2_data_log_header(tp, dp, bp); xfs_dir2_block_log_tail(tp, bp); xfs_dir2_data_log_entry(tp, dp, bp, dep); xfs_dir3_data_check(dp, bp); @@ -800,7 +801,7 @@ xfs_dir2_block_removename( * Mark the data entry's space free. */ needlog = needscan = 0; - xfs_dir2_data_make_free(tp, bp, + xfs_dir2_data_make_free(tp, dp, bp, (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); /* @@ -819,7 +820,7 @@ xfs_dir2_block_removename( if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) - xfs_dir2_data_log_header(tp, bp); + xfs_dir2_data_log_header(tp, dp, bp); xfs_dir3_data_check(dp, bp); /* * See if the size as a shortform is good enough. @@ -950,7 +951,7 @@ xfs_dir2_leaf_to_block( while (dp->i_d.di_size > mp->m_dirblksize) { int hdrsz; - hdrsz = xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)); + hdrsz = dp->d_ops->data_entry_offset(); bestsp = xfs_dir2_leaf_bests_p(ltp); if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) == mp->m_dirblksize - hdrsz) { @@ -1000,7 +1001,7 @@ xfs_dir2_leaf_to_block( /* * Use up the space at the end of the block (blp/btp). */ - xfs_dir2_data_use_free(tp, dbp, dup, mp->m_dirblksize - size, size, + xfs_dir2_data_use_free(tp, dp, dbp, dup, mp->m_dirblksize - size, size, &needlog, &needscan); /* * Initialize the block tail. @@ -1026,7 +1027,7 @@ xfs_dir2_leaf_to_block( if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) - xfs_dir2_data_log_header(tp, dbp); + xfs_dir2_data_log_header(tp, dp, dbp); /* * Pitch the old leaf block. */ @@ -1137,9 +1138,9 @@ xfs_dir2_sf_to_block( * The whole thing is initialized to free by the init routine. * Say we're using the leaf and tail area. */ - dup = xfs_dir3_data_unused_p(hdr); + dup = dp->d_ops->data_unused_p(hdr); needlog = needscan = 0; - xfs_dir2_data_use_free(tp, bp, dup, mp->m_dirblksize - i, i, &needlog, + xfs_dir2_data_use_free(tp, dp, bp, dup, mp->m_dirblksize - i, i, &needlog, &needscan); ASSERT(needscan == 0); /* @@ -1153,7 +1154,7 @@ xfs_dir2_sf_to_block( /* * Remove the freespace, we'll manage it. */ - xfs_dir2_data_use_free(tp, bp, dup, + xfs_dir2_data_use_free(tp, dp, bp, dup, (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), be16_to_cpu(dup->length), &needlog, &needscan); /* @@ -1215,7 +1216,9 @@ xfs_dir2_sf_to_block( *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16( ((char *)dup - (char *)hdr)); xfs_dir2_data_log_unused(tp, bp, dup); - xfs_dir2_data_freeinsert(hdr, dup, &dummy); + xfs_dir2_data_freeinsert(hdr, + dp->d_ops->data_bestfree_p(hdr), + dup, &dummy); offset += be16_to_cpu(dup->length); continue; } diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 00006b3db054..13fa0d6b4ff7 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -66,8 +66,6 @@ __xfs_dir3_data_check( mp = bp->b_target->bt_mount; hdr = bp->b_addr; - bf = xfs_dir3_data_bestfree_p(hdr); - p = (char *)xfs_dir3_data_entry_p(hdr); /* * We can be passed a null dp here from a verifier, so manually @@ -97,6 +95,8 @@ __xfs_dir3_data_check( XFS_ERROR_REPORT("Bad Magic", XFS_ERRLEVEL_LOW, mp); return EFSCORRUPTED; } + bf = ops->data_bestfree_p(hdr); + p = (char *)ops->data_entry_p(hdr); count = lastfree = freeseen = 0; /* @@ -134,7 +134,7 @@ __xfs_dir3_data_check( XFS_WANT_CORRUPTED_RETURN( be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) == (char *)dup - (char *)hdr); - dfp = xfs_dir2_data_freefind(hdr, dup); + dfp = xfs_dir2_data_freefind(hdr, bf, dup); if (dfp) { i = (int)(dfp - bf); XFS_WANT_CORRUPTED_RETURN( @@ -340,19 +340,18 @@ xfs_dir3_data_readahead( */ xfs_dir2_data_free_t * xfs_dir2_data_freefind( - xfs_dir2_data_hdr_t *hdr, /* data block */ - xfs_dir2_data_unused_t *dup) /* data unused entry */ + struct xfs_dir2_data_hdr *hdr, /* data block header */ + struct xfs_dir2_data_free *bf, /* bestfree table pointer */ + struct xfs_dir2_data_unused *dup) /* unused space */ { xfs_dir2_data_free_t *dfp; /* bestfree entry */ xfs_dir2_data_aoff_t off; /* offset value needed */ - struct xfs_dir2_data_free *bf; #ifdef DEBUG int matched; /* matched the value */ int seenzero; /* saw a 0 bestfree entry */ #endif off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr); - bf = xfs_dir3_data_bestfree_p(hdr); #ifdef DEBUG /* @@ -412,11 +411,11 @@ xfs_dir2_data_freefind( */ xfs_dir2_data_free_t * /* entry inserted */ xfs_dir2_data_freeinsert( - xfs_dir2_data_hdr_t *hdr, /* data block pointer */ - xfs_dir2_data_unused_t *dup, /* unused space */ + struct xfs_dir2_data_hdr *hdr, /* data block pointer */ + struct xfs_dir2_data_free *dfp, /* bestfree table pointer */ + struct xfs_dir2_data_unused *dup, /* unused space */ int *loghead) /* log the data header (out) */ { - xfs_dir2_data_free_t *dfp; /* bestfree table pointer */ xfs_dir2_data_free_t new; /* new bestfree entry */ ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || @@ -424,7 +423,6 @@ xfs_dir2_data_freeinsert( hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); - dfp = xfs_dir3_data_bestfree_p(hdr); new.length = dup->length; new.offset = cpu_to_be16((char *)dup - (char *)hdr); @@ -457,11 +455,11 @@ xfs_dir2_data_freeinsert( */ STATIC void xfs_dir2_data_freeremove( - xfs_dir2_data_hdr_t *hdr, /* data block header */ - xfs_dir2_data_free_t *dfp, /* bestfree entry pointer */ + struct xfs_dir2_data_hdr *hdr, /* data block header */ + struct xfs_dir2_data_free *bf, /* bestfree table pointer */ + struct xfs_dir2_data_free *dfp, /* bestfree entry pointer */ int *loghead) /* out: log data header */ { - struct xfs_dir2_data_free *bf; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || @@ -471,7 +469,6 @@ xfs_dir2_data_freeremove( /* * It's the first entry, slide the next 2 up. */ - bf = xfs_dir3_data_bestfree_p(hdr); if (dfp == &bf[0]) { bf[0] = bf[1]; bf[1] = bf[2]; @@ -518,13 +515,13 @@ xfs_dir2_data_freescan( /* * Start by clearing the table. */ - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT); *loghead = 1; /* * Set up pointers. */ - p = (char *)xfs_dir3_data_entry_p(hdr); + p = (char *)dp->d_ops->data_entry_p(hdr); if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { btp = xfs_dir2_block_tail_p(dp->i_mount, hdr); @@ -542,7 +539,7 @@ xfs_dir2_data_freescan( if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { ASSERT((char *)dup - (char *)hdr == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup))); - xfs_dir2_data_freeinsert(hdr, dup, loghead); + xfs_dir2_data_freeinsert(hdr, bf, dup, loghead); p += be16_to_cpu(dup->length); } /* @@ -607,8 +604,8 @@ xfs_dir3_data_init( } else hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); - bf = xfs_dir3_data_bestfree_p(hdr); - bf[0].offset = cpu_to_be16(xfs_dir3_data_entry_offset(hdr)); + bf = dp->d_ops->data_bestfree_p(hdr); + bf[0].offset = cpu_to_be16(dp->d_ops->data_entry_offset()); for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) { bf[i].length = 0; bf[i].offset = 0; @@ -617,17 +614,17 @@ xfs_dir3_data_init( /* * Set up an unused entry for the block's body. */ - dup = xfs_dir3_data_unused_p(hdr); + dup = dp->d_ops->data_unused_p(hdr); dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); - t = mp->m_dirblksize - (uint)xfs_dir3_data_entry_offset(hdr); + t = mp->m_dirblksize - (uint)dp->d_ops->data_entry_offset(); bf[0].length = cpu_to_be16(t); dup->length = cpu_to_be16(t); *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr); /* * Log it and return it. */ - xfs_dir2_data_log_header(tp, bp); + xfs_dir2_data_log_header(tp, dp, bp); xfs_dir2_data_log_unused(tp, bp, dup); *bpp = bp; return 0; @@ -661,16 +658,19 @@ xfs_dir2_data_log_entry( void xfs_dir2_data_log_header( struct xfs_trans *tp, + struct xfs_inode *dp, struct xfs_buf *bp) { - xfs_dir2_data_hdr_t *hdr = bp->b_addr; +#ifdef DEBUG + struct xfs_dir2_data_hdr *hdr = bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); +#endif - xfs_trans_log_buf(tp, bp, 0, xfs_dir3_data_entry_offset(hdr) - 1); + xfs_trans_log_buf(tp, bp, 0, dp->d_ops->data_entry_offset() - 1); } /* @@ -711,6 +711,7 @@ xfs_dir2_data_log_unused( void xfs_dir2_data_make_free( struct xfs_trans *tp, + struct xfs_inode *dp, struct xfs_buf *bp, xfs_dir2_data_aoff_t offset, /* starting byte offset */ xfs_dir2_data_aoff_t len, /* length in bytes */ @@ -748,7 +749,7 @@ xfs_dir2_data_make_free( * If this isn't the start of the block, then back up to * the previous entry and see if it's free. */ - if (offset > xfs_dir3_data_entry_offset(hdr)) { + if (offset > dp->d_ops->data_entry_offset()) { __be16 *tagp; /* tag just before us */ tagp = (__be16 *)((char *)hdr + offset) - 1; @@ -774,15 +775,15 @@ xfs_dir2_data_make_free( * Previous and following entries are both free, * merge everything into a single free entry. */ - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); if (prevdup && postdup) { xfs_dir2_data_free_t *dfp2; /* another bestfree pointer */ /* * See if prevdup and/or postdup are in bestfree table. */ - dfp = xfs_dir2_data_freefind(hdr, prevdup); - dfp2 = xfs_dir2_data_freefind(hdr, postdup); + dfp = xfs_dir2_data_freefind(hdr, bf, prevdup); + dfp2 = xfs_dir2_data_freefind(hdr, bf, postdup); /* * We need a rescan unless there are exactly 2 free entries * namely our two. Then we know what's happening, otherwise @@ -810,12 +811,13 @@ xfs_dir2_data_make_free( ASSERT(dfp2 == dfp); dfp2 = &bf[1]; } - xfs_dir2_data_freeremove(hdr, dfp2, needlogp); - xfs_dir2_data_freeremove(hdr, dfp, needlogp); + xfs_dir2_data_freeremove(hdr, bf, dfp2, needlogp); + xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); /* * Now insert the new entry. */ - dfp = xfs_dir2_data_freeinsert(hdr, prevdup, needlogp); + dfp = xfs_dir2_data_freeinsert(hdr, bf, prevdup, + needlogp); ASSERT(dfp == &bf[0]); ASSERT(dfp->length == prevdup->length); ASSERT(!dfp[1].length); @@ -826,7 +828,7 @@ xfs_dir2_data_make_free( * The entry before us is free, merge with it. */ else if (prevdup) { - dfp = xfs_dir2_data_freefind(hdr, prevdup); + dfp = xfs_dir2_data_freefind(hdr, bf, prevdup); be16_add_cpu(&prevdup->length, len); *xfs_dir2_data_unused_tag_p(prevdup) = cpu_to_be16((char *)prevdup - (char *)hdr); @@ -837,8 +839,8 @@ xfs_dir2_data_make_free( * the old one and add the new one. */ if (dfp) { - xfs_dir2_data_freeremove(hdr, dfp, needlogp); - xfs_dir2_data_freeinsert(hdr, prevdup, needlogp); + xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); + xfs_dir2_data_freeinsert(hdr, bf, prevdup, needlogp); } /* * Otherwise we need a scan if the new entry is big enough. @@ -852,7 +854,7 @@ xfs_dir2_data_make_free( * The following entry is free, merge with it. */ else if (postdup) { - dfp = xfs_dir2_data_freefind(hdr, postdup); + dfp = xfs_dir2_data_freefind(hdr, bf, postdup); newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset); newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length)); @@ -865,8 +867,8 @@ xfs_dir2_data_make_free( * the old one and add the new one. */ if (dfp) { - xfs_dir2_data_freeremove(hdr, dfp, needlogp); - xfs_dir2_data_freeinsert(hdr, newdup, needlogp); + xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); + xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); } /* * Otherwise we need a scan if the new entry is big enough. @@ -886,7 +888,7 @@ xfs_dir2_data_make_free( *xfs_dir2_data_unused_tag_p(newdup) = cpu_to_be16((char *)newdup - (char *)hdr); xfs_dir2_data_log_unused(tp, bp, newdup); - xfs_dir2_data_freeinsert(hdr, newdup, needlogp); + xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); } *needscanp = needscan; } @@ -897,6 +899,7 @@ xfs_dir2_data_make_free( void xfs_dir2_data_use_free( struct xfs_trans *tp, + struct xfs_inode *dp, struct xfs_buf *bp, xfs_dir2_data_unused_t *dup, /* unused entry */ xfs_dir2_data_aoff_t offset, /* starting offset to use */ @@ -926,9 +929,9 @@ xfs_dir2_data_use_free( /* * Look up the entry in the bestfree table. */ - dfp = xfs_dir2_data_freefind(hdr, dup); oldlen = be16_to_cpu(dup->length); - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); + dfp = xfs_dir2_data_freefind(hdr, bf, dup); ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length)); /* * Check for alignment with front and back of the entry. @@ -945,7 +948,8 @@ xfs_dir2_data_use_free( if (dfp) { needscan = (bf[2].offset != 0); if (!needscan) - xfs_dir2_data_freeremove(hdr, dfp, needlogp); + xfs_dir2_data_freeremove(hdr, bf, dfp, + needlogp); } } /* @@ -963,8 +967,9 @@ xfs_dir2_data_use_free( * If it was in the table, remove it and add the new one. */ if (dfp) { - xfs_dir2_data_freeremove(hdr, dfp, needlogp); - dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp); + xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); + dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup, + needlogp); ASSERT(dfp != NULL); ASSERT(dfp->length == newdup->length); ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr); @@ -990,8 +995,9 @@ xfs_dir2_data_use_free( * If it was in the table, remove it and add the new one. */ if (dfp) { - xfs_dir2_data_freeremove(hdr, dfp, needlogp); - dfp = xfs_dir2_data_freeinsert(hdr, newdup, needlogp); + xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); + dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup, + needlogp); ASSERT(dfp != NULL); ASSERT(dfp->length == newdup->length); ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)hdr); @@ -1030,9 +1036,11 @@ xfs_dir2_data_use_free( if (dfp) { needscan = (bf[2].length != 0); if (!needscan) { - xfs_dir2_data_freeremove(hdr, dfp, needlogp); - xfs_dir2_data_freeinsert(hdr, newdup, needlogp); - xfs_dir2_data_freeinsert(hdr, newdup2, + xfs_dir2_data_freeremove(hdr, bf, dfp, + needlogp); + xfs_dir2_data_freeinsert(hdr, bf, newdup, + needlogp); + xfs_dir2_data_freeinsert(hdr, bf, newdup2, needlogp); } } diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index dd195363ccf2..f35b3942c1a6 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -460,7 +460,7 @@ xfs_dir2_block_to_leaf( xfs_dir3_data_check(dp, dbp); btp = xfs_dir2_block_tail_p(mp, hdr); blp = xfs_dir2_block_leaf_p(btp); - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); ents = xfs_dir3_leaf_ents_p(leaf); /* @@ -484,7 +484,7 @@ xfs_dir2_block_to_leaf( * Make the space formerly occupied by the leaf entries and block * tail be free. */ - xfs_dir2_data_make_free(tp, dbp, + xfs_dir2_data_make_free(tp, dp, dbp, (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), (xfs_dir2_data_aoff_t)((char *)hdr + mp->m_dirblksize - (char *)blp), @@ -512,7 +512,7 @@ xfs_dir2_block_to_leaf( * Log the data header and leaf bests table. */ if (needlog) - xfs_dir2_data_log_header(tp, dbp); + xfs_dir2_data_log_header(tp, dp, dbp); xfs_dir3_leaf_check(mp, lbp); xfs_dir3_data_check(dp, dbp); xfs_dir3_leaf_log_bests(tp, lbp, 0, 0); @@ -862,7 +862,7 @@ xfs_dir2_leaf_addname( else xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block); hdr = dbp->b_addr; - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); bestsp[use_block] = bf[0].length; grown = 1; } else { @@ -878,7 +878,7 @@ xfs_dir2_leaf_addname( return error; } hdr = dbp->b_addr; - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); grown = 0; } /* @@ -891,7 +891,7 @@ xfs_dir2_leaf_addname( /* * Mark the initial part of our freespace in use for the new entry. */ - xfs_dir2_data_use_free(tp, dbp, dup, + xfs_dir2_data_use_free(tp, dp, dbp, dup, (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length, &needlog, &needscan); /* @@ -913,7 +913,7 @@ xfs_dir2_leaf_addname( * Need to log the data block's header. */ if (needlog) - xfs_dir2_data_log_header(tp, dbp); + xfs_dir2_data_log_header(tp, dp, dbp); xfs_dir2_data_log_entry(tp, dp, dbp, dep); /* * If the bests table needs to be changed, do it. @@ -1413,7 +1413,7 @@ xfs_dir2_leaf_removename( leaf = lbp->b_addr; hdr = dbp->b_addr; xfs_dir3_data_check(dp, dbp); - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); ents = xfs_dir3_leaf_ents_p(leaf); /* @@ -1431,7 +1431,7 @@ xfs_dir2_leaf_removename( /* * Mark the former data entry unused. */ - xfs_dir2_data_make_free(tp, dbp, + xfs_dir2_data_make_free(tp, dp, dbp, (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); /* @@ -1451,7 +1451,7 @@ xfs_dir2_leaf_removename( if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) - xfs_dir2_data_log_header(tp, dbp); + xfs_dir2_data_log_header(tp, dp, dbp); /* * If the longest freespace in the data block has changed, * put the new value in the bests table and log that. @@ -1465,7 +1465,7 @@ xfs_dir2_leaf_removename( * If the data block is now empty then get rid of the data block. */ if (be16_to_cpu(bf[0].length) == - mp->m_dirblksize - xfs_dir3_data_entry_offset(hdr)) { + mp->m_dirblksize - dp->d_ops->data_entry_offset()) { ASSERT(db != mp->m_dirdatablk); if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { /* @@ -1659,12 +1659,12 @@ xfs_dir2_leaf_trim_data( #ifdef DEBUG { struct xfs_dir2_data_hdr *hdr = dbp->b_addr; - struct xfs_dir2_data_free *bf = xfs_dir3_data_bestfree_p(hdr); + struct xfs_dir2_data_free *bf = dp->d_ops->data_bestfree_p(hdr); ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); ASSERT(be16_to_cpu(bf[0].length) == - mp->m_dirblksize - xfs_dir3_data_entry_offset(hdr)); + mp->m_dirblksize - dp->d_ops->data_entry_offset()); ASSERT(db == be32_to_cpu(ltp->bestcount) - 1); } #endif diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index a1d133981c14..9cfc00323b19 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -1255,10 +1255,10 @@ xfs_dir2_leafn_remove( dbp = dblk->bp; hdr = dbp->b_addr; dep = (xfs_dir2_data_entry_t *)((char *)hdr + off); - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); longest = be16_to_cpu(bf[0].length); needlog = needscan = 0; - xfs_dir2_data_make_free(tp, dbp, off, + xfs_dir2_data_make_free(tp, dp, dbp, off, dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); /* * Rescan the data block freespaces for bestfree. @@ -1267,7 +1267,7 @@ xfs_dir2_leafn_remove( if (needscan) xfs_dir2_data_freescan(dp, hdr, &needlog); if (needlog) - xfs_dir2_data_log_header(tp, dbp); + xfs_dir2_data_log_header(tp, dp, dbp); xfs_dir3_data_check(dp, dbp); /* * If the longest data block freespace changes, need to update @@ -1308,7 +1308,7 @@ xfs_dir2_leafn_remove( * (usually). */ if (longest == mp->m_dirblksize - - xfs_dir3_data_entry_offset(hdr)) { + dp->d_ops->data_entry_offset()) { /* * Try to punch out the data block. */ @@ -1962,7 +1962,7 @@ xfs_dir2_node_addname_int( * change again. */ hdr = dbp->b_addr; - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); bests[findex] = bf[0].length; logfree = 1; } @@ -1984,7 +1984,7 @@ xfs_dir2_node_addname_int( if (error) return error; hdr = dbp->b_addr; - bf = xfs_dir3_data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); logfree = 0; } ASSERT(be16_to_cpu(bf[0].length) >= length); @@ -1997,7 +1997,7 @@ xfs_dir2_node_addname_int( /* * Mark the first part of the unused space, inuse for us. */ - xfs_dir2_data_use_free(tp, dbp, dup, + xfs_dir2_data_use_free(tp, dp, dbp, dup, (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), length, &needlog, &needscan); /* @@ -2020,7 +2020,7 @@ xfs_dir2_node_addname_int( * Log the data block header if needed. */ if (needlog) - xfs_dir2_data_log_header(tp, dbp); + xfs_dir2_data_log_header(tp, dp, dbp); /* * If the freespace entry is now wrong, update it. */ diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h index 1bad84c40829..9a69f206daf9 100644 --- a/fs/xfs/xfs_dir2_priv.h +++ b/fs/xfs/xfs_dir2_priv.h @@ -59,7 +59,8 @@ extern int xfs_dir3_data_readahead(struct xfs_trans *tp, struct xfs_inode *dp, extern struct xfs_dir2_data_free * xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr, - struct xfs_dir2_data_unused *dup, int *loghead); + struct xfs_dir2_data_free *bf, struct xfs_dir2_data_unused *dup, + int *loghead); extern int xfs_dir3_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno, struct xfs_buf **bpp); diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index b99aa7d48e90..f45ecac821ec 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -213,7 +213,7 @@ xfs_dir2_block_getdents( * Set up values for the loop. */ btp = xfs_dir2_block_tail_p(mp, hdr); - ptr = (char *)xfs_dir3_data_entry_p(hdr); + ptr = (char *)dp->d_ops->data_entry_p(hdr); endptr = (char *)xfs_dir2_block_leaf_p(btp); /* @@ -578,13 +578,13 @@ xfs_dir2_leaf_getdents( /* * Find our position in the block. */ - ptr = (char *)xfs_dir3_data_entry_p(hdr); + ptr = (char *)dp->d_ops->data_entry_p(hdr); byteoff = xfs_dir2_byte_to_off(mp, curoff); /* * Skip past the header. */ if (byteoff == 0) - curoff += xfs_dir3_data_entry_offset(hdr); + curoff += dp->d_ops->data_entry_offset(); /* * Skip past entries until we reach our offset. */ diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 953e19479151..42bbcff15cc5 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -210,7 +210,7 @@ xfs_dir2_block_to_sf( * Set up to loop over the block's entries. */ btp = xfs_dir2_block_tail_p(mp, hdr); - ptr = (char *)xfs_dir3_data_entry_p(hdr); + ptr = (char *)dp->d_ops->data_entry_p(hdr); endptr = (char *)xfs_dir2_block_leaf_p(btp); sfep = xfs_dir2_sf_firstentry(sfp); /* -- cgit v1.2.3 From 4141956ae05e0685b14b30f92fdc8fb11b4a0cb2 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:50 +1100 Subject: xfs: vectorise directory leaf operations Next step in the vectorisation process is the leaf block encode/decode operations. Most of the operations on leaves are handled by the data block vectors, so there are relatively few of them here. Because of all the shuffling of code and having to pass more state to some functions, this patch doesn't directly reduce the size of the binary. It does open up many more opportunities for factoring and optimisation, however. text data bss dec hex filename 794490 96802 1096 892388 d9de4 fs/xfs/xfs.o.orig 792986 96802 1096 890884 d9804 fs/xfs/xfs.o.p1 792350 96802 1096 890248 d9588 fs/xfs/xfs.o.p2 789293 96802 1096 887191 d8997 fs/xfs/xfs.o.p3 789005 96802 1096 886903 d8997 fs/xfs/xfs.o.p4 789061 96802 1096 886959 d88af fs/xfs/xfs.o.p5 Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_da_btree.c | 19 ++++---- fs/xfs/xfs_da_format.c | 75 +++++++++++++++++++++++++++++++ fs/xfs/xfs_da_format.h | 30 ------------- fs/xfs/xfs_dir2.c | 7 +-- fs/xfs/xfs_dir2.h | 10 +++-- fs/xfs/xfs_dir2_block.c | 2 +- fs/xfs/xfs_dir2_data.c | 13 ++---- fs/xfs/xfs_dir2_leaf.c | 91 ++++++++++++++++++++----------------- fs/xfs/xfs_dir2_node.c | 117 ++++++++++++++++++++++++++---------------------- fs/xfs/xfs_dir2_priv.h | 13 +++--- 10 files changed, 218 insertions(+), 159 deletions(-) diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index eb65c546ffd8..df3759c51470 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -605,7 +605,7 @@ xfs_da3_root_split( leaf = (xfs_dir2_leaf_t *)oldroot; xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); @@ -1319,7 +1319,8 @@ xfs_da3_fixhashpath( return; break; case XFS_DIR2_LEAFN_MAGIC: - lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count); + lasthash = xfs_dir2_leafn_lasthash(state->args->dp, + blk->bp, &count); if (count == 0) return; break; @@ -1536,7 +1537,8 @@ xfs_da3_node_lookup_int( if (blk->magic == XFS_DIR2_LEAFN_MAGIC || blk->magic == XFS_DIR3_LEAFN_MAGIC) { blk->magic = XFS_DIR2_LEAFN_MAGIC; - blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); + blk->hashval = xfs_dir2_leafn_lasthash(args->dp, + blk->bp, NULL); break; } @@ -1702,7 +1704,7 @@ xfs_da3_blk_link( before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp); break; case XFS_DIR2_LEAFN_MAGIC: - before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp); + before = xfs_dir2_leafn_order(args->dp, old_blk->bp, new_blk->bp); break; case XFS_DA_NODE_MAGIC: before = xfs_da3_node_order(old_blk->bp, new_blk->bp); @@ -1947,16 +1949,15 @@ xfs_da3_path_shift( blk->magic = XFS_ATTR_LEAF_MAGIC; ASSERT(level == path->active-1); blk->index = 0; - blk->hashval = xfs_attr_leaf_lasthash(blk->bp, - NULL); + blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); break; case XFS_DIR2_LEAFN_MAGIC: case XFS_DIR3_LEAFN_MAGIC: blk->magic = XFS_DIR2_LEAFN_MAGIC; ASSERT(level == path->active-1); blk->index = 0; - blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, - NULL); + blk->hashval = xfs_dir2_leafn_lasthash(args->dp, + blk->bp, NULL); break; default: ASSERT(0); @@ -2223,7 +2224,7 @@ xfs_da3_swap_lastblock( dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; xfs_dir3_leaf_hdr_from_disk(&leafhdr, dead_leaf2); - ents = xfs_dir3_leaf_ents_p(dead_leaf2); + ents = ip->d_ops->leaf_ents_p(dead_leaf2); dead_level = 0; dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval); } else { diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index 1e92a241fd52..ff8b50368c94 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c @@ -435,6 +435,48 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) ((char *)hdr + xfs_dir3_data_entry_offset()); } + +/* + * Directory Leaf block operations + */ +static int +xfs_dir2_leaf_hdr_size(void) +{ + return sizeof(struct xfs_dir2_leaf_hdr); +} + +static int +xfs_dir2_max_leaf_ents(struct xfs_mount *mp) +{ + return (mp->m_dirblksize - xfs_dir2_leaf_hdr_size()) / + (uint)sizeof(struct xfs_dir2_leaf_entry); +} + +static struct xfs_dir2_leaf_entry * +xfs_dir2_leaf_ents_p(struct xfs_dir2_leaf *lp) +{ + return lp->__ents; +} + +static int +xfs_dir3_leaf_hdr_size(void) +{ + return sizeof(struct xfs_dir3_leaf_hdr); +} + +static inline int +xfs_dir3_max_leaf_ents(struct xfs_mount *mp) +{ + return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size()) / + (uint)sizeof(struct xfs_dir2_leaf_entry); +} + +static inline struct xfs_dir2_leaf_entry * +xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp) +{ + return ((struct xfs_dir3_leaf *)lp)->__ents; +} + const struct xfs_dir_ops xfs_dir2_ops = { .sf_entsize = xfs_dir2_sf_entsize, .sf_nextentry = xfs_dir2_sf_nextentry, @@ -462,6 +504,10 @@ const struct xfs_dir_ops xfs_dir2_ops = { .data_entry_p = xfs_dir2_data_entry_p, .data_unused_p = xfs_dir2_data_unused_p, + .leaf_hdr_size = xfs_dir2_leaf_hdr_size, + .leaf_max_ents = xfs_dir2_max_leaf_ents, + .leaf_ents_p = xfs_dir2_leaf_ents_p, + }; const struct xfs_dir_ops xfs_dir2_ftype_ops = { @@ -490,6 +536,10 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = { .data_first_entry_p = xfs_dir2_data_first_entry_p, .data_entry_p = xfs_dir2_data_entry_p, .data_unused_p = xfs_dir2_data_unused_p, + + .leaf_hdr_size = xfs_dir2_leaf_hdr_size, + .leaf_max_ents = xfs_dir2_max_leaf_ents, + .leaf_ents_p = xfs_dir2_leaf_ents_p, }; const struct xfs_dir_ops xfs_dir3_ops = { @@ -518,4 +568,29 @@ const struct xfs_dir_ops xfs_dir3_ops = { .data_first_entry_p = xfs_dir3_data_first_entry_p, .data_entry_p = xfs_dir3_data_entry_p, .data_unused_p = xfs_dir3_data_unused_p, + + .leaf_hdr_size = xfs_dir3_leaf_hdr_size, + .leaf_max_ents = xfs_dir3_max_leaf_ents, + .leaf_ents_p = xfs_dir3_leaf_ents_p, }; + +/* + * Return the ops structure according to the current config. If we are passed + * an inode, then that overrides the default config we use which is based on + * feature bits. + */ +const struct xfs_dir_ops * +xfs_dir_get_ops( + struct xfs_mount *mp, + struct xfs_inode *dp) +{ + if (dp) + return dp->d_ops; + if (mp->m_dir_inode_ops) + return mp->m_dir_inode_ops; + if (xfs_sb_version_hascrc(&mp->m_sb)) + return &xfs_dir3_ops; + if (xfs_sb_version_hasftype(&mp->m_sb)) + return &xfs_dir2_ftype_ops; + return &xfs_dir2_ops; +} diff --git a/fs/xfs/xfs_da_format.h b/fs/xfs/xfs_da_format.h index aeca0038a013..0a567e25cf59 100644 --- a/fs/xfs/xfs_da_format.h +++ b/fs/xfs/xfs_da_format.h @@ -551,36 +551,6 @@ struct xfs_dir3_leaf { extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to, struct xfs_dir2_leaf *from); -static inline int -xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp) -{ - if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || - lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) - return sizeof(struct xfs_dir3_leaf_hdr); - return sizeof(struct xfs_dir2_leaf_hdr); -} - -static inline int -xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) -{ - return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) / - (uint)sizeof(struct xfs_dir2_leaf_entry); -} - -/* - * Get address of the bestcount field in the single-leaf block. - */ -static inline struct xfs_dir2_leaf_entry * -xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp) -{ - if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || - lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { - struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp; - return lp3->__ents; - } - return lp->__ents; -} - /* * Get address of the bestcount field in the single-leaf block. */ diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 7911136453cd..2b98a33ca383 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -113,12 +113,7 @@ xfs_dir_mount( else mp->m_dirnameops = &xfs_default_nameops; - if (xfs_sb_version_hascrc(&mp->m_sb)) - mp->m_dir_inode_ops = &xfs_dir3_ops; - else if (xfs_sb_version_hasftype(&mp->m_sb)) - mp->m_dir_inode_ops = &xfs_dir2_ftype_ops; - else - mp->m_dir_inode_ops = &xfs_dir2_ops; + mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL); } /* diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 076010a1376a..9ba9db731990 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -74,11 +74,15 @@ struct xfs_dir_ops { (*data_entry_p)(struct xfs_dir2_data_hdr *hdr); struct xfs_dir2_data_unused * (*data_unused_p)(struct xfs_dir2_data_hdr *hdr); + + int (*leaf_hdr_size)(void); + int (*leaf_max_ents)(struct xfs_mount *mp); + struct xfs_dir2_leaf_entry * + (*leaf_ents_p)(struct xfs_dir2_leaf *lp); }; -extern const struct xfs_dir_ops xfs_dir2_ops; -extern const struct xfs_dir_ops xfs_dir2_ftype_ops; -extern const struct xfs_dir_ops xfs_dir3_ops; +extern const struct xfs_dir_ops * + xfs_dir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp); /* * Generic directory interface routines diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index f92ca5699342..75f815786b97 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -937,7 +937,7 @@ xfs_dir2_leaf_to_block( mp = dp->i_mount; leaf = lbp->b_addr; xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); ltp = xfs_dir2_leaf_tail_p(mp, leaf); ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC || diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 13fa0d6b4ff7..32d657fbe6a4 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -68,17 +68,10 @@ __xfs_dir3_data_check( hdr = bp->b_addr; /* - * We can be passed a null dp here from a verifier, so manually - * configure the ops here in that case. + * We can be passed a null dp here from a verifier, so we need to go the + * hard way to get them. */ - if (dp) - ops = dp->d_ops; - else if (xfs_sb_version_hascrc(&mp->m_sb)) - ops = &xfs_dir3_ops; - else if (xfs_sb_version_hasftype(&mp->m_sb)) - ops = &xfs_dir2_ftype_ops; - else - ops = &xfs_dir2_ops; + ops = xfs_dir_get_ops(mp, dp); switch (hdr->magic) { case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index f35b3942c1a6..16fdc0e627a7 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -50,15 +50,15 @@ static void xfs_dir3_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp); * Pop an assert if something is wrong. */ #ifdef DEBUG -#define xfs_dir3_leaf_check(mp, bp) \ +#define xfs_dir3_leaf_check(dp, bp) \ do { \ - if (!xfs_dir3_leaf1_check((mp), (bp))) \ + if (!xfs_dir3_leaf1_check((dp), (bp))) \ ASSERT(0); \ } while (0); STATIC bool xfs_dir3_leaf1_check( - struct xfs_mount *mp, + struct xfs_inode *dp, struct xfs_buf *bp) { struct xfs_dir2_leaf *leaf = bp->b_addr; @@ -73,10 +73,10 @@ xfs_dir3_leaf1_check( } else if (leafhdr.magic != XFS_DIR2_LEAF1_MAGIC) return false; - return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); + return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf); } #else -#define xfs_dir3_leaf_check(mp, bp) +#define xfs_dir3_leaf_check(dp, bp) #endif void @@ -138,6 +138,7 @@ xfs_dir3_leaf_hdr_to_disk( bool xfs_dir3_leaf_check_int( struct xfs_mount *mp, + struct xfs_inode *dp, struct xfs_dir3_icleaf_hdr *hdr, struct xfs_dir2_leaf *leaf) { @@ -145,8 +146,15 @@ xfs_dir3_leaf_check_int( xfs_dir2_leaf_tail_t *ltp; int stale; int i; + const struct xfs_dir_ops *ops; - ents = xfs_dir3_leaf_ents_p(leaf); + /* + * we can be passed a null dp here from a verifier, so we need to go the + * hard way to get them. + */ + ops = xfs_dir_get_ops(mp, dp); + + ents = ops->leaf_ents_p(leaf); ltp = xfs_dir2_leaf_tail_p(mp, leaf); /* @@ -154,7 +162,7 @@ xfs_dir3_leaf_check_int( * Should factor in the size of the bests table as well. * We can deduce a value for that from di_size. */ - if (hdr->count > xfs_dir3_max_leaf_ents(mp, leaf)) + if (hdr->count > ops->leaf_max_ents(mp)) return false; /* Leaves and bests don't overlap in leaf format. */ @@ -213,7 +221,7 @@ xfs_dir3_leaf_verify( } xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); - return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); + return xfs_dir3_leaf_check_int(mp, NULL, &leafhdr, leaf); } static void @@ -399,7 +407,7 @@ xfs_dir3_leaf_get_buf( return error; xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic); - xfs_dir3_leaf_log_header(tp, bp); + xfs_dir3_leaf_log_header(tp, dp, bp); if (magic == XFS_DIR2_LEAF1_MAGIC) xfs_dir3_leaf_log_tail(tp, bp); *bpp = bp; @@ -461,7 +469,7 @@ xfs_dir2_block_to_leaf( btp = xfs_dir2_block_tail_p(mp, hdr); blp = xfs_dir2_block_leaf_p(btp); bf = dp->d_ops->data_bestfree_p(hdr); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); /* * Set the counts in the leaf header. @@ -470,14 +478,14 @@ xfs_dir2_block_to_leaf( leafhdr.count = be32_to_cpu(btp->count); leafhdr.stale = be32_to_cpu(btp->stale); xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); - xfs_dir3_leaf_log_header(tp, lbp); + xfs_dir3_leaf_log_header(tp, dp, lbp); /* * Could compact these but I think we always do the conversion * after squeezing out stale entries. */ memcpy(ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t)); - xfs_dir3_leaf_log_ents(tp, lbp, 0, leafhdr.count - 1); + xfs_dir3_leaf_log_ents(tp, dp, lbp, 0, leafhdr.count - 1); needscan = 0; needlog = 1; /* @@ -513,7 +521,7 @@ xfs_dir2_block_to_leaf( */ if (needlog) xfs_dir2_data_log_header(tp, dp, dbp); - xfs_dir3_leaf_check(mp, lbp); + xfs_dir3_leaf_check(dp, lbp); xfs_dir3_data_check(dp, dbp); xfs_dir3_leaf_log_bests(tp, lbp, 0, 0); return 0; @@ -697,7 +705,7 @@ xfs_dir2_leaf_addname( index = xfs_dir2_leaf_search_hash(args, lbp); leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(mp, leaf); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); bestsp = xfs_dir2_leaf_bests_p(ltp); length = dp->d_ops->data_entsize(args->namelen); @@ -938,9 +946,9 @@ xfs_dir2_leaf_addname( * Log the leaf fields and give up the buffers. */ xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); - xfs_dir3_leaf_log_header(tp, lbp); - xfs_dir3_leaf_log_ents(tp, lbp, lfloglow, lfloghigh); - xfs_dir3_leaf_check(mp, lbp); + xfs_dir3_leaf_log_header(tp, dp, lbp); + xfs_dir3_leaf_log_ents(tp, dp, lbp, lfloglow, lfloghigh); + xfs_dir3_leaf_check(dp, lbp); xfs_dir3_data_check(dp, dbp); return 0; } @@ -968,7 +976,7 @@ xfs_dir3_leaf_compact( /* * Compress out the stale entries in place. */ - ents = xfs_dir3_leaf_ents_p(leaf); + ents = args->dp->d_ops->leaf_ents_p(leaf); for (from = to = 0, loglow = -1; from < leafhdr->count; from++) { if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) continue; @@ -990,9 +998,10 @@ xfs_dir3_leaf_compact( leafhdr->stale = 0; xfs_dir3_leaf_hdr_to_disk(leaf, leafhdr); - xfs_dir3_leaf_log_header(args->trans, bp); + xfs_dir3_leaf_log_header(args->trans, args->dp, bp); if (loglow != -1) - xfs_dir3_leaf_log_ents(args->trans, bp, loglow, to - 1); + xfs_dir3_leaf_log_ents(args->trans, args->dp, bp, + loglow, to - 1); } /* @@ -1119,10 +1128,11 @@ xfs_dir3_leaf_log_bests( */ void xfs_dir3_leaf_log_ents( - xfs_trans_t *tp, /* transaction pointer */ - struct xfs_buf *bp, /* leaf buffer */ - int first, /* first entry to log */ - int last) /* last entry to log */ + struct xfs_trans *tp, + struct xfs_inode *dp, + struct xfs_buf *bp, + int first, + int last) { xfs_dir2_leaf_entry_t *firstlep; /* pointer to first entry */ xfs_dir2_leaf_entry_t *lastlep; /* pointer to last entry */ @@ -1134,7 +1144,7 @@ xfs_dir3_leaf_log_ents( leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); firstlep = &ents[first]; lastlep = &ents[last]; xfs_trans_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf), @@ -1147,6 +1157,7 @@ xfs_dir3_leaf_log_ents( void xfs_dir3_leaf_log_header( struct xfs_trans *tp, + struct xfs_inode *dp, struct xfs_buf *bp) { struct xfs_dir2_leaf *leaf = bp->b_addr; @@ -1157,7 +1168,7 @@ xfs_dir3_leaf_log_header( leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), - xfs_dir3_leaf_hdr_size(leaf) - 1); + dp->d_ops->leaf_hdr_size() - 1); } /* @@ -1212,9 +1223,9 @@ xfs_dir2_leaf_lookup( } tp = args->trans; dp = args->dp; - xfs_dir3_leaf_check(dp->i_mount, lbp); + xfs_dir3_leaf_check(dp, lbp); leaf = lbp->b_addr; - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); /* * Get to the leaf entry and contained data entry address. */ @@ -1277,8 +1288,8 @@ xfs_dir2_leaf_lookup_int( *lbpp = lbp; leaf = lbp->b_addr; - xfs_dir3_leaf_check(mp, lbp); - ents = xfs_dir3_leaf_ents_p(leaf); + xfs_dir3_leaf_check(dp, lbp); + ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); /* @@ -1415,7 +1426,7 @@ xfs_dir2_leaf_removename( xfs_dir3_data_check(dp, dbp); bf = dp->d_ops->data_bestfree_p(hdr); xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); /* * Point to the leaf entry, use that to point to the data entry. */ @@ -1439,10 +1450,10 @@ xfs_dir2_leaf_removename( */ leafhdr.stale++; xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); - xfs_dir3_leaf_log_header(tp, lbp); + xfs_dir3_leaf_log_header(tp, dp, lbp); lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); - xfs_dir3_leaf_log_ents(tp, lbp, index, index); + xfs_dir3_leaf_log_ents(tp, dp, lbp, index, index); /* * Scan the freespace in the data block again if necessary, @@ -1476,7 +1487,7 @@ xfs_dir2_leaf_removename( */ if (error == ENOSPC && args->total == 0) error = 0; - xfs_dir3_leaf_check(mp, lbp); + xfs_dir3_leaf_check(dp, lbp); return error; } dbp = NULL; @@ -1510,7 +1521,7 @@ xfs_dir2_leaf_removename( else if (db != mp->m_dirdatablk) dbp = NULL; - xfs_dir3_leaf_check(mp, lbp); + xfs_dir3_leaf_check(dp, lbp); /* * See if we can convert to block form. */ @@ -1545,7 +1556,7 @@ xfs_dir2_leaf_replace( } dp = args->dp; leaf = lbp->b_addr; - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); /* * Point to the leaf entry, get data address from it. */ @@ -1564,7 +1575,7 @@ xfs_dir2_leaf_replace( dp->d_ops->data_put_ftype(dep, args->filetype); tp = args->trans; xfs_dir2_data_log_entry(tp, dp, dbp, dep); - xfs_dir3_leaf_check(dp->i_mount, lbp); + xfs_dir3_leaf_check(dp, lbp); xfs_trans_brelse(tp, lbp); return 0; } @@ -1590,7 +1601,7 @@ xfs_dir2_leaf_search_hash( struct xfs_dir3_icleaf_hdr leafhdr; leaf = lbp->b_addr; - ents = xfs_dir3_leaf_ents_p(leaf); + ents = args->dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); /* @@ -1830,10 +1841,10 @@ xfs_dir2_node_to_leaf( freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); - xfs_dir3_leaf_log_header(tp, lbp); + xfs_dir3_leaf_log_header(tp, dp, lbp); xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); xfs_dir3_leaf_log_tail(tp, lbp); - xfs_dir3_leaf_check(mp, lbp); + xfs_dir3_leaf_check(dp, lbp); /* * Get rid of the freespace block. diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 9cfc00323b19..3a426ed9b16e 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -54,15 +54,15 @@ static int xfs_dir2_node_addname_int(xfs_da_args_t *args, * Check internal consistency of a leafn block. */ #ifdef DEBUG -#define xfs_dir3_leaf_check(mp, bp) \ +#define xfs_dir3_leaf_check(dp, bp) \ do { \ - if (!xfs_dir3_leafn_check((mp), (bp))) \ + if (!xfs_dir3_leafn_check((dp), (bp))) \ ASSERT(0); \ } while (0); static bool xfs_dir3_leafn_check( - struct xfs_mount *mp, + struct xfs_inode *dp, struct xfs_buf *bp) { struct xfs_dir2_leaf *leaf = bp->b_addr; @@ -77,10 +77,10 @@ xfs_dir3_leafn_check( } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC) return false; - return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); + return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf); } #else -#define xfs_dir3_leaf_check(mp, bp) +#define xfs_dir3_leaf_check(dp, bp) #endif static bool @@ -408,8 +408,8 @@ xfs_dir2_leaf_to_node( leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); lbp->b_ops = &xfs_dir3_leafn_buf_ops; xfs_trans_buf_set_type(tp, lbp, XFS_BLFT_DIR_LEAFN_BUF); - xfs_dir3_leaf_log_header(tp, lbp); - xfs_dir3_leaf_check(mp, lbp); + xfs_dir3_leaf_log_header(tp, dp, lbp); + xfs_dir3_leaf_check(dp, lbp); return 0; } @@ -443,7 +443,7 @@ xfs_dir2_leafn_add( tp = args->trans; leaf = bp->b_addr; xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); /* * Quick check just to make sure we are not going to index @@ -459,7 +459,7 @@ xfs_dir2_leafn_add( * a compact. */ - if (leafhdr.count == xfs_dir3_max_leaf_ents(mp, leaf)) { + if (leafhdr.count == dp->d_ops->leaf_max_ents(mp)) { if (!leafhdr.stale) return XFS_ERROR(ENOSPC); compact = leafhdr.stale > 1; @@ -498,9 +498,9 @@ xfs_dir2_leafn_add( args->blkno, args->index)); xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); - xfs_dir3_leaf_log_header(tp, bp); - xfs_dir3_leaf_log_ents(tp, bp, lfloglow, lfloghigh); - xfs_dir3_leaf_check(mp, bp); + xfs_dir3_leaf_log_header(tp, dp, bp); + xfs_dir3_leaf_log_ents(tp, dp, bp, lfloglow, lfloghigh); + xfs_dir3_leaf_check(dp, bp); return 0; } @@ -529,6 +529,7 @@ xfs_dir2_free_hdr_check( */ xfs_dahash_t /* hash value */ xfs_dir2_leafn_lasthash( + struct xfs_inode *dp, struct xfs_buf *bp, /* leaf buffer */ int *count) /* count of entries in leaf */ { @@ -546,7 +547,7 @@ xfs_dir2_leafn_lasthash( if (!leafhdr.count) return 0; - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); return be32_to_cpu(ents[leafhdr.count - 1].hashval); } @@ -584,9 +585,9 @@ xfs_dir2_leafn_lookup_for_addname( mp = dp->i_mount; leaf = bp->b_addr; xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); - xfs_dir3_leaf_check(mp, bp); + xfs_dir3_leaf_check(dp, bp); ASSERT(leafhdr.count > 0); /* @@ -734,9 +735,9 @@ xfs_dir2_leafn_lookup_for_entry( mp = dp->i_mount; leaf = bp->b_addr; xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); - xfs_dir3_leaf_check(mp, bp); + xfs_dir3_leaf_check(dp, bp); ASSERT(leafhdr.count > 0); /* @@ -906,7 +907,7 @@ xfs_dir3_leafn_moveents( if (start_d < dhdr->count) { memmove(&dents[start_d + count], &dents[start_d], (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t)); - xfs_dir3_leaf_log_ents(tp, bp_d, start_d + count, + xfs_dir3_leaf_log_ents(tp, args->dp, bp_d, start_d + count, count + dhdr->count - 1); } /* @@ -928,7 +929,8 @@ xfs_dir3_leafn_moveents( */ memcpy(&dents[start_d], &sents[start_s], count * sizeof(xfs_dir2_leaf_entry_t)); - xfs_dir3_leaf_log_ents(tp, bp_d, start_d, start_d + count - 1); + xfs_dir3_leaf_log_ents(tp, args->dp, bp_d, + start_d, start_d + count - 1); /* * If there are source entries after the ones we copied, @@ -937,7 +939,8 @@ xfs_dir3_leafn_moveents( if (start_s + count < shdr->count) { memmove(&sents[start_s], &sents[start_s + count], count * sizeof(xfs_dir2_leaf_entry_t)); - xfs_dir3_leaf_log_ents(tp, bp_s, start_s, start_s + count - 1); + xfs_dir3_leaf_log_ents(tp, args->dp, bp_s, + start_s, start_s + count - 1); } /* @@ -955,6 +958,7 @@ xfs_dir3_leafn_moveents( */ int /* sort order */ xfs_dir2_leafn_order( + struct xfs_inode *dp, struct xfs_buf *leaf1_bp, /* leaf1 buffer */ struct xfs_buf *leaf2_bp) /* leaf2 buffer */ { @@ -967,8 +971,8 @@ xfs_dir2_leafn_order( xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1); xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2); - ents1 = xfs_dir3_leaf_ents_p(leaf1); - ents2 = xfs_dir3_leaf_ents_p(leaf2); + ents1 = dp->d_ops->leaf_ents_p(leaf1); + ents2 = dp->d_ops->leaf_ents_p(leaf2); if (hdr1.count > 0 && hdr2.count > 0 && (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) || @@ -1006,12 +1010,13 @@ xfs_dir2_leafn_rebalance( struct xfs_dir2_leaf_entry *ents2; struct xfs_dir3_icleaf_hdr hdr1; struct xfs_dir3_icleaf_hdr hdr2; + struct xfs_inode *dp = state->args->dp; args = state->args; /* * If the block order is wrong, swap the arguments. */ - if ((swap = xfs_dir2_leafn_order(blk1->bp, blk2->bp))) { + if ((swap = xfs_dir2_leafn_order(dp, blk1->bp, blk2->bp))) { xfs_da_state_blk_t *tmp; /* temp for block swap */ tmp = blk1; @@ -1022,8 +1027,8 @@ xfs_dir2_leafn_rebalance( leaf2 = blk2->bp->b_addr; xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1); xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2); - ents1 = xfs_dir3_leaf_ents_p(leaf1); - ents2 = xfs_dir3_leaf_ents_p(leaf2); + ents1 = dp->d_ops->leaf_ents_p(leaf1); + ents2 = dp->d_ops->leaf_ents_p(leaf2); oldsum = hdr1.count + hdr2.count; #if defined(DEBUG) || defined(XFS_WARN) @@ -1071,11 +1076,11 @@ xfs_dir2_leafn_rebalance( /* log the changes made when moving the entries */ xfs_dir3_leaf_hdr_to_disk(leaf1, &hdr1); xfs_dir3_leaf_hdr_to_disk(leaf2, &hdr2); - xfs_dir3_leaf_log_header(args->trans, blk1->bp); - xfs_dir3_leaf_log_header(args->trans, blk2->bp); + xfs_dir3_leaf_log_header(args->trans, dp, blk1->bp); + xfs_dir3_leaf_log_header(args->trans, dp, blk2->bp); - xfs_dir3_leaf_check(args->dp->i_mount, blk1->bp); - xfs_dir3_leaf_check(args->dp->i_mount, blk2->bp); + xfs_dir3_leaf_check(dp, blk1->bp); + xfs_dir3_leaf_check(dp, blk2->bp); /* * Mark whether we're inserting into the old or new leaf. @@ -1096,10 +1101,10 @@ xfs_dir2_leafn_rebalance( * Finally sanity check just to make sure we are not returning a * negative index */ - if(blk2->index < 0) { + if (blk2->index < 0) { state->inleaf = 1; blk2->index = 0; - xfs_alert(args->dp->i_mount, + xfs_alert(dp->i_mount, "%s: picked the wrong leaf? reverting original leaf: blk1->index %d", __func__, blk1->index); } @@ -1222,7 +1227,7 @@ xfs_dir2_leafn_remove( mp = dp->i_mount; leaf = bp->b_addr; xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); /* * Point to the entry we're removing. @@ -1243,10 +1248,10 @@ xfs_dir2_leafn_remove( */ leafhdr.stale++; xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); - xfs_dir3_leaf_log_header(tp, bp); + xfs_dir3_leaf_log_header(tp, dp, bp); lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); - xfs_dir3_leaf_log_ents(tp, bp, index, index); + xfs_dir3_leaf_log_ents(tp, dp, bp, index, index); /* * Make the data entry free. Keep track of the longest freespace @@ -1335,12 +1340,12 @@ xfs_dir2_leafn_remove( return error; } - xfs_dir3_leaf_check(mp, bp); + xfs_dir3_leaf_check(dp, bp); /* * Return indication of whether this leaf block is empty enough * to justify trying to join it with a neighbor. */ - *rval = (xfs_dir3_leaf_hdr_size(leaf) + + *rval = (dp->d_ops->leaf_hdr_size() + (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) < mp->m_dir_magicpct; return 0; @@ -1359,12 +1364,14 @@ xfs_dir2_leafn_split( xfs_dablk_t blkno; /* new leaf block number */ int error; /* error return value */ xfs_mount_t *mp; /* filesystem mount point */ + struct xfs_inode *dp; /* * Allocate space for a new leaf node. */ args = state->args; - mp = args->dp->i_mount; + dp = args->dp; + mp = dp->i_mount; ASSERT(args != NULL); ASSERT(oldblk->magic == XFS_DIR2_LEAFN_MAGIC); error = xfs_da_grow_inode(args, &blkno); @@ -1400,10 +1407,10 @@ xfs_dir2_leafn_split( /* * Update last hashval in each block since we added the name. */ - oldblk->hashval = xfs_dir2_leafn_lasthash(oldblk->bp, NULL); - newblk->hashval = xfs_dir2_leafn_lasthash(newblk->bp, NULL); - xfs_dir3_leaf_check(mp, oldblk->bp); - xfs_dir3_leaf_check(mp, newblk->bp); + oldblk->hashval = xfs_dir2_leafn_lasthash(dp, oldblk->bp, NULL); + newblk->hashval = xfs_dir2_leafn_lasthash(dp, newblk->bp, NULL); + xfs_dir3_leaf_check(dp, oldblk->bp); + xfs_dir3_leaf_check(dp, newblk->bp); return error; } @@ -1433,6 +1440,7 @@ xfs_dir2_leafn_toosmall( int rval; /* result from path_shift */ struct xfs_dir3_icleaf_hdr leafhdr; struct xfs_dir2_leaf_entry *ents; + struct xfs_inode *dp = state->args->dp; /* * Check for the degenerate case of the block being over 50% full. @@ -1442,11 +1450,11 @@ xfs_dir2_leafn_toosmall( blk = &state->path.blk[state->path.active - 1]; leaf = blk->bp->b_addr; xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); - ents = xfs_dir3_leaf_ents_p(leaf); - xfs_dir3_leaf_check(state->args->dp->i_mount, blk->bp); + ents = dp->d_ops->leaf_ents_p(leaf); + xfs_dir3_leaf_check(dp, blk->bp); count = leafhdr.count - leafhdr.stale; - bytes = xfs_dir3_leaf_hdr_size(leaf) + count * sizeof(ents[0]); + bytes = dp->d_ops->leaf_hdr_size() + count * sizeof(ents[0]); if (bytes > (state->blocksize >> 1)) { /* * Blk over 50%, don't try to join. @@ -1491,7 +1499,7 @@ xfs_dir2_leafn_toosmall( /* * Read the sibling leaf block. */ - error = xfs_dir3_leafn_read(state->args->trans, state->args->dp, + error = xfs_dir3_leafn_read(state->args->trans, dp, blkno, -1, &bp); if (error) return error; @@ -1504,7 +1512,7 @@ xfs_dir2_leafn_toosmall( leaf = bp->b_addr; xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf); - ents = xfs_dir3_leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); count += hdr2.count - hdr2.stale; bytes -= count * sizeof(ents[0]); @@ -1558,6 +1566,7 @@ xfs_dir2_leafn_unbalance( struct xfs_dir3_icleaf_hdr drophdr; struct xfs_dir2_leaf_entry *sents; struct xfs_dir2_leaf_entry *dents; + struct xfs_inode *dp = state->args->dp; args = state->args; ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); @@ -1567,8 +1576,8 @@ xfs_dir2_leafn_unbalance( xfs_dir3_leaf_hdr_from_disk(&savehdr, save_leaf); xfs_dir3_leaf_hdr_from_disk(&drophdr, drop_leaf); - sents = xfs_dir3_leaf_ents_p(save_leaf); - dents = xfs_dir3_leaf_ents_p(drop_leaf); + sents = args->dp->d_ops->leaf_ents_p(save_leaf); + dents = args->dp->d_ops->leaf_ents_p(drop_leaf); /* * If there are any stale leaf entries, take this opportunity @@ -1583,7 +1592,7 @@ xfs_dir2_leafn_unbalance( * Move the entries from drop to the appropriate end of save. */ drop_blk->hashval = be32_to_cpu(dents[drophdr.count - 1].hashval); - if (xfs_dir2_leafn_order(save_blk->bp, drop_blk->bp)) + if (xfs_dir2_leafn_order(dp, save_blk->bp, drop_blk->bp)) xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0, save_blk->bp, &savehdr, sents, 0, drophdr.count); @@ -1596,11 +1605,11 @@ xfs_dir2_leafn_unbalance( /* log the changes made when moving the entries */ xfs_dir3_leaf_hdr_to_disk(save_leaf, &savehdr); xfs_dir3_leaf_hdr_to_disk(drop_leaf, &drophdr); - xfs_dir3_leaf_log_header(args->trans, save_blk->bp); - xfs_dir3_leaf_log_header(args->trans, drop_blk->bp); + xfs_dir3_leaf_log_header(args->trans, dp, save_blk->bp); + xfs_dir3_leaf_log_header(args->trans, dp, drop_blk->bp); - xfs_dir3_leaf_check(args->dp->i_mount, save_blk->bp); - xfs_dir3_leaf_check(args->dp->i_mount, drop_blk->bp); + xfs_dir3_leaf_check(dp, save_blk->bp); + xfs_dir3_leaf_check(dp, drop_blk->bp); } /* @@ -2211,7 +2220,7 @@ xfs_dir2_node_replace( blk = &state->path.blk[state->path.active - 1]; ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); leaf = blk->bp->b_addr; - ents = xfs_dir3_leaf_ents_p(leaf); + ents = args->dp->d_ops->leaf_ents_p(leaf); lep = &ents[blk->index]; ASSERT(state->extravalid); /* diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h index 9a69f206daf9..3e4b5ba7b41f 100644 --- a/fs/xfs/xfs_dir2_priv.h +++ b/fs/xfs/xfs_dir2_priv.h @@ -77,9 +77,9 @@ extern void xfs_dir3_leaf_compact_x1(struct xfs_dir3_icleaf_hdr *leafhdr, int *lowstalep, int *highstalep, int *lowlogp, int *highlogp); extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno, struct xfs_buf **bpp, __uint16_t magic); -extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp, - int first, int last); -extern void xfs_dir3_leaf_log_header(struct xfs_trans *tp, +extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_inode *dp, + struct xfs_buf *bp, int first, int last); +extern void xfs_dir3_leaf_log_header(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_buf *bp); extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args); extern int xfs_dir2_leaf_removename(struct xfs_da_args *args); @@ -98,17 +98,18 @@ extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to, struct xfs_dir2_leaf *from); extern void xfs_dir3_leaf_hdr_to_disk(struct xfs_dir2_leaf *to, struct xfs_dir3_icleaf_hdr *from); -extern bool xfs_dir3_leaf_check_int(struct xfs_mount *mp, +extern bool xfs_dir3_leaf_check_int(struct xfs_mount *mp, struct xfs_inode *dp, struct xfs_dir3_icleaf_hdr *hdr, struct xfs_dir2_leaf *leaf); /* xfs_dir2_node.c */ extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args, struct xfs_buf *lbp); -extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_buf *bp, int *count); +extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_inode *dp, + struct xfs_buf *bp, int *count); extern int xfs_dir2_leafn_lookup_int(struct xfs_buf *bp, struct xfs_da_args *args, int *indexp, struct xfs_da_state *state); -extern int xfs_dir2_leafn_order(struct xfs_buf *leaf1_bp, +extern int xfs_dir2_leafn_order(struct xfs_inode *dp, struct xfs_buf *leaf1_bp, struct xfs_buf *leaf2_bp); extern int xfs_dir2_leafn_split(struct xfs_da_state *state, struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk); -- cgit v1.2.3 From 4bceb18f1551c8c047eeb54d48cda9f5453dc12f Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:51 +1100 Subject: xfs: vectorise DA btree operations The remaining non-vectorised code for the directory structure is the node format blocks. This is shared with the attribute tree, and so is slightly more complex to vectorise. Introduce a "non-directory" directory ops structure that is attached to all non-directory inodes so that attribute operations can be vectorised for all inodes. Once we do this, we can vectorise all the da btree operations. Because this patch adds more infrastructure than it removes the binary size does not decrease: text data bss dec hex filename 794490 96802 1096 892388 d9de4 fs/xfs/xfs.o.orig 792986 96802 1096 890884 d9804 fs/xfs/xfs.o.p1 792350 96802 1096 890248 d9588 fs/xfs/xfs.o.p2 789293 96802 1096 887191 d8997 fs/xfs/xfs.o.p3 789005 96802 1096 886903 d8997 fs/xfs/xfs.o.p4 789061 96802 1096 886959 d88af fs/xfs/xfs.o.p5 789733 96802 1096 887631 d8b4f fs/xfs/xfs.o.p6 Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_attr_inactive.c | 3 +- fs/xfs/xfs_attr_leaf.c | 3 +- fs/xfs/xfs_attr_list.c | 11 ++--- fs/xfs/xfs_da_btree.c | 104 +++++++++++++++++++++++++-------------------- fs/xfs/xfs_da_format.c | 59 +++++++++++++++++++++++++ fs/xfs/xfs_da_format.h | 25 ----------- fs/xfs/xfs_dir2.c | 7 ++- fs/xfs/xfs_dir2.h | 6 +++ fs/xfs/xfs_iops.c | 1 + fs/xfs/xfs_mount.h | 1 + 10 files changed, 139 insertions(+), 81 deletions(-) diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index f33fb62b7f17..4855085f8c6b 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c @@ -40,6 +40,7 @@ #include "xfs_quota.h" #include "xfs_trace.h" #include "xfs_dinode.h" +#include "xfs_dir2.h" /* * Look at all the extents for this logical region, @@ -236,7 +237,7 @@ xfs_attr3_node_inactive( xfs_trans_brelse(*trans, bp); return 0; } - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); child_fsb = be32_to_cpu(btree[0].before); xfs_trans_brelse(*trans, bp); /* no locks for later trans */ diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index a0f90193a247..82f1354c77b6 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -41,6 +41,7 @@ #include "xfs_buf_item.h" #include "xfs_cksum.h" #include "xfs_dinode.h" +#include "xfs_dir2.h" /* @@ -916,7 +917,7 @@ xfs_attr3_leaf_to_node( goto out; node = bp1->b_addr; xfs_da3_node_hdr_from_disk(&icnodehdr, node); - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); leaf = bp2->b_addr; xfs_attr3_leaf_hdr_from_disk(&icleafhdr, leaf); diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index 46c4ce148a43..ea1c4c46c24f 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -40,6 +40,7 @@ #include "xfs_buf_item.h" #include "xfs_cksum.h" #include "xfs_dinode.h" +#include "xfs_dir2.h" STATIC int xfs_attr_shortform_compare(const void *a, const void *b) @@ -226,6 +227,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) struct xfs_da_node_entry *btree; int error, i; struct xfs_buf *bp; + struct xfs_inode *dp = context->dp; trace_xfs_attr_node_list(context); @@ -239,7 +241,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) */ bp = NULL; if (cursor->blkno > 0) { - error = xfs_da3_node_read(NULL, context->dp, cursor->blkno, -1, + error = xfs_da3_node_read(NULL, dp, cursor->blkno, -1, &bp, XFS_ATTR_FORK); if ((error != 0) && (error != EFSCORRUPTED)) return(error); @@ -289,7 +291,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) for (;;) { __uint16_t magic; - error = xfs_da3_node_read(NULL, context->dp, + error = xfs_da3_node_read(NULL, dp, cursor->blkno, -1, &bp, XFS_ATTR_FORK); if (error) @@ -310,7 +312,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) } xfs_da3_node_hdr_from_disk(&nodehdr, node); - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); for (i = 0; i < nodehdr.count; btree++, i++) { if (cursor->hashval <= be32_to_cpu(btree->hashval)) { @@ -346,8 +348,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) break; cursor->blkno = leafhdr.forw; xfs_trans_brelse(NULL, bp); - error = xfs_attr3_leaf_read(NULL, context->dp, cursor->blkno, -1, - &bp); + error = xfs_attr3_leaf_read(NULL, dp, cursor->blkno, -1, &bp); if (error) return error; } diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index df3759c51470..26dfc42a28f9 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -379,7 +379,8 @@ xfs_da3_node_create( xfs_da3_node_hdr_to_disk(node, &ichdr); xfs_trans_log_buf(tp, bp, - XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node))); + XFS_DA_LOGRANGE(node, &node->hdr, + args->dp->d_ops->node_hdr_size())); *bpp = bp; return(0); @@ -590,7 +591,7 @@ xfs_da3_root_split( struct xfs_da3_icnode_hdr nodehdr; xfs_da3_node_hdr_from_disk(&nodehdr, oldroot); - btree = xfs_da3_node_tree_p(oldroot); + btree = dp->d_ops->node_tree_p(oldroot); size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot); level = nodehdr.level; @@ -650,7 +651,7 @@ xfs_da3_root_split( node = bp->b_addr; xfs_da3_node_hdr_from_disk(&nodehdr, node); - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); btree[0].hashval = cpu_to_be32(blk1->hashval); btree[0].before = cpu_to_be32(blk1->blkno); btree[1].hashval = cpu_to_be32(blk2->hashval); @@ -793,6 +794,7 @@ xfs_da3_node_rebalance( int count; int tmp; int swap = 0; + struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_rebalance(state->args); @@ -800,8 +802,8 @@ xfs_da3_node_rebalance( node2 = blk2->bp->b_addr; xfs_da3_node_hdr_from_disk(&nodehdr1, node1); xfs_da3_node_hdr_from_disk(&nodehdr2, node2); - btree1 = xfs_da3_node_tree_p(node1); - btree2 = xfs_da3_node_tree_p(node2); + btree1 = dp->d_ops->node_tree_p(node1); + btree2 = dp->d_ops->node_tree_p(node2); /* * Figure out how many entries need to move, and in which direction. @@ -816,8 +818,8 @@ xfs_da3_node_rebalance( node2 = tmpnode; xfs_da3_node_hdr_from_disk(&nodehdr1, node1); xfs_da3_node_hdr_from_disk(&nodehdr2, node2); - btree1 = xfs_da3_node_tree_p(node1); - btree2 = xfs_da3_node_tree_p(node2); + btree1 = dp->d_ops->node_tree_p(node1); + btree2 = dp->d_ops->node_tree_p(node2); swap = 1; } @@ -882,12 +884,12 @@ xfs_da3_node_rebalance( xfs_da3_node_hdr_to_disk(node1, &nodehdr1); xfs_trans_log_buf(tp, blk1->bp, XFS_DA_LOGRANGE(node1, &node1->hdr, - xfs_da3_node_hdr_size(node1))); + dp->d_ops->node_hdr_size())); xfs_da3_node_hdr_to_disk(node2, &nodehdr2); xfs_trans_log_buf(tp, blk2->bp, XFS_DA_LOGRANGE(node2, &node2->hdr, - xfs_da3_node_hdr_size(node2) + + dp->d_ops->node_hdr_size() + (sizeof(btree2[0]) * nodehdr2.count))); /* @@ -899,8 +901,8 @@ xfs_da3_node_rebalance( node2 = blk2->bp->b_addr; xfs_da3_node_hdr_from_disk(&nodehdr1, node1); xfs_da3_node_hdr_from_disk(&nodehdr2, node2); - btree1 = xfs_da3_node_tree_p(node1); - btree2 = xfs_da3_node_tree_p(node2); + btree1 = dp->d_ops->node_tree_p(node1); + btree2 = dp->d_ops->node_tree_p(node2); } blk1->hashval = be32_to_cpu(btree1[nodehdr1.count - 1].hashval); blk2->hashval = be32_to_cpu(btree2[nodehdr2.count - 1].hashval); @@ -927,12 +929,13 @@ xfs_da3_node_add( struct xfs_da3_icnode_hdr nodehdr; struct xfs_da_node_entry *btree; int tmp; + struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_add(state->args); node = oldblk->bp->b_addr; xfs_da3_node_hdr_from_disk(&nodehdr, node); - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); ASSERT(oldblk->index >= 0 && oldblk->index <= nodehdr.count); ASSERT(newblk->blkno != 0); @@ -957,7 +960,7 @@ xfs_da3_node_add( nodehdr.count += 1; xfs_da3_node_hdr_to_disk(node, &nodehdr); xfs_trans_log_buf(state->args->trans, oldblk->bp, - XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node))); + XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size())); /* * Copy the last hash value from the oldblk to propagate upwards. @@ -1115,7 +1118,7 @@ xfs_da3_root_join( * Read in the (only) child block, then copy those bytes into * the root block's buffer and free the original child block. */ - btree = xfs_da3_node_tree_p(oldroot); + btree = args->dp->d_ops->node_tree_p(oldroot); child = be32_to_cpu(btree[0].before); ASSERT(child != 0); error = xfs_da3_node_read(args->trans, args->dp, child, -1, &bp, @@ -1275,6 +1278,7 @@ xfs_da3_node_toosmall( */ STATIC uint xfs_da3_node_lasthash( + struct xfs_inode *dp, struct xfs_buf *bp, int *count) { @@ -1288,7 +1292,7 @@ xfs_da3_node_lasthash( *count = nodehdr.count; if (!nodehdr.count) return 0; - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); return be32_to_cpu(btree[nodehdr.count - 1].hashval); } @@ -1307,6 +1311,7 @@ xfs_da3_fixhashpath( xfs_dahash_t lasthash=0; int level; int count; + struct xfs_inode *dp = state->args->dp; trace_xfs_da_fixhashpath(state->args); @@ -1319,13 +1324,12 @@ xfs_da3_fixhashpath( return; break; case XFS_DIR2_LEAFN_MAGIC: - lasthash = xfs_dir2_leafn_lasthash(state->args->dp, - blk->bp, &count); + lasthash = xfs_dir2_leafn_lasthash(dp, blk->bp, &count); if (count == 0) return; break; case XFS_DA_NODE_MAGIC: - lasthash = xfs_da3_node_lasthash(blk->bp, &count); + lasthash = xfs_da3_node_lasthash(dp, blk->bp, &count); if (count == 0) return; break; @@ -1335,7 +1339,7 @@ xfs_da3_fixhashpath( node = blk->bp->b_addr; xfs_da3_node_hdr_from_disk(&nodehdr, node); - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); if (be32_to_cpu(btree->hashval) == lasthash) break; blk->hashval = lasthash; @@ -1361,6 +1365,7 @@ xfs_da3_node_remove( struct xfs_da_node_entry *btree; int index; int tmp; + struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_remove(state->args); @@ -1373,7 +1378,7 @@ xfs_da3_node_remove( * Copy over the offending entry, or just zero it out. */ index = drop_blk->index; - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); if (index < nodehdr.count - 1) { tmp = nodehdr.count - index - 1; tmp *= (uint)sizeof(xfs_da_node_entry_t); @@ -1388,7 +1393,7 @@ xfs_da3_node_remove( nodehdr.count -= 1; xfs_da3_node_hdr_to_disk(node, &nodehdr); xfs_trans_log_buf(state->args->trans, drop_blk->bp, - XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node))); + XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size())); /* * Copy the last hash value from the block to propagate upwards. @@ -1415,6 +1420,7 @@ xfs_da3_node_unbalance( struct xfs_trans *tp; int sindex; int tmp; + struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_unbalance(state->args); @@ -1422,8 +1428,8 @@ xfs_da3_node_unbalance( save_node = save_blk->bp->b_addr; xfs_da3_node_hdr_from_disk(&drop_hdr, drop_node); xfs_da3_node_hdr_from_disk(&save_hdr, save_node); - drop_btree = xfs_da3_node_tree_p(drop_node); - save_btree = xfs_da3_node_tree_p(save_node); + drop_btree = dp->d_ops->node_tree_p(drop_node); + save_btree = dp->d_ops->node_tree_p(save_node); tp = state->args->trans; /* @@ -1460,7 +1466,7 @@ xfs_da3_node_unbalance( xfs_da3_node_hdr_to_disk(save_node, &save_hdr); xfs_trans_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, &save_node->hdr, - xfs_da3_node_hdr_size(save_node))); + dp->d_ops->node_hdr_size())); /* * Save the last hashval in the remaining block for upward propagation. @@ -1502,6 +1508,7 @@ xfs_da3_node_lookup_int( int max; int error; int retval; + struct xfs_inode *dp = state->args->dp; args = state->args; @@ -1550,7 +1557,7 @@ xfs_da3_node_lookup_int( */ node = blk->bp->b_addr; xfs_da3_node_hdr_from_disk(&nodehdr, node); - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); max = nodehdr.count; blk->hashval = be32_to_cpu(btree[max - 1].hashval); @@ -1645,6 +1652,7 @@ xfs_da3_node_lookup_int( */ STATIC int xfs_da3_node_order( + struct xfs_inode *dp, struct xfs_buf *node1_bp, struct xfs_buf *node2_bp) { @@ -1659,8 +1667,8 @@ xfs_da3_node_order( node2 = node2_bp->b_addr; xfs_da3_node_hdr_from_disk(&node1hdr, node1); xfs_da3_node_hdr_from_disk(&node2hdr, node2); - btree1 = xfs_da3_node_tree_p(node1); - btree2 = xfs_da3_node_tree_p(node2); + btree1 = dp->d_ops->node_tree_p(node1); + btree2 = dp->d_ops->node_tree_p(node2); if (node1hdr.count > 0 && node2hdr.count > 0 && ((be32_to_cpu(btree2[0].hashval) < be32_to_cpu(btree1[0].hashval)) || @@ -1687,6 +1695,7 @@ xfs_da3_blk_link( struct xfs_buf *bp; int before = 0; int error; + struct xfs_inode *dp = state->args->dp; /* * Set up environment. @@ -1704,10 +1713,10 @@ xfs_da3_blk_link( before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp); break; case XFS_DIR2_LEAFN_MAGIC: - before = xfs_dir2_leafn_order(args->dp, old_blk->bp, new_blk->bp); + before = xfs_dir2_leafn_order(dp, old_blk->bp, new_blk->bp); break; case XFS_DA_NODE_MAGIC: - before = xfs_da3_node_order(old_blk->bp, new_blk->bp); + before = xfs_da3_node_order(dp, old_blk->bp, new_blk->bp); break; } @@ -1722,7 +1731,7 @@ xfs_da3_blk_link( new_info->forw = cpu_to_be32(old_blk->blkno); new_info->back = old_info->back; if (old_info->back) { - error = xfs_da3_node_read(args->trans, args->dp, + error = xfs_da3_node_read(args->trans, dp, be32_to_cpu(old_info->back), -1, &bp, args->whichfork); if (error) @@ -1743,7 +1752,7 @@ xfs_da3_blk_link( new_info->forw = old_info->forw; new_info->back = cpu_to_be32(old_blk->blkno); if (old_info->forw) { - error = xfs_da3_node_read(args->trans, args->dp, + error = xfs_da3_node_read(args->trans, dp, be32_to_cpu(old_info->forw), -1, &bp, args->whichfork); if (error) @@ -1863,6 +1872,7 @@ xfs_da3_path_shift( xfs_dablk_t blkno = 0; int level; int error; + struct xfs_inode *dp = state->args->dp; trace_xfs_da_path_shift(state->args); @@ -1879,7 +1889,7 @@ xfs_da3_path_shift( for (blk = &path->blk[level]; level >= 0; blk--, level--) { node = blk->bp->b_addr; xfs_da3_node_hdr_from_disk(&nodehdr, node); - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); if (forward && (blk->index < nodehdr.count - 1)) { blk->index++; @@ -1913,7 +1923,7 @@ xfs_da3_path_shift( * Read the next child block. */ blk->blkno = blkno; - error = xfs_da3_node_read(args->trans, args->dp, blkno, -1, + error = xfs_da3_node_read(args->trans, dp, blkno, -1, &blk->bp, args->whichfork); if (error) return(error); @@ -1936,7 +1946,7 @@ xfs_da3_path_shift( blk->magic = XFS_DA_NODE_MAGIC; node = (xfs_da_intnode_t *)info; xfs_da3_node_hdr_from_disk(&nodehdr, node); - btree = xfs_da3_node_tree_p(node); + btree = dp->d_ops->node_tree_p(node); blk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval); if (forward) blk->index = 0; @@ -2164,7 +2174,7 @@ xfs_da3_swap_lastblock( struct xfs_dir2_leaf *dead_leaf2; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr par_hdr; - struct xfs_inode *ip; + struct xfs_inode *dp; struct xfs_trans *tp; struct xfs_mount *mp; struct xfs_buf *dead_buf; @@ -2188,12 +2198,12 @@ xfs_da3_swap_lastblock( dead_buf = *dead_bufp; dead_blkno = *dead_blknop; tp = args->trans; - ip = args->dp; + dp = args->dp; w = args->whichfork; ASSERT(w == XFS_DATA_FORK); - mp = ip->i_mount; + mp = dp->i_mount; lastoff = mp->m_dirfreeblk; - error = xfs_bmap_last_before(tp, ip, &lastoff, w); + error = xfs_bmap_last_before(tp, dp, &lastoff, w); if (error) return error; if (unlikely(lastoff == 0)) { @@ -2205,7 +2215,7 @@ xfs_da3_swap_lastblock( * Read the last block in the btree space. */ last_blkno = (xfs_dablk_t)lastoff - mp->m_dirblkfsbs; - error = xfs_da3_node_read(tp, ip, last_blkno, -1, &last_buf, w); + error = xfs_da3_node_read(tp, dp, last_blkno, -1, &last_buf, w); if (error) return error; /* @@ -2224,7 +2234,7 @@ xfs_da3_swap_lastblock( dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; xfs_dir3_leaf_hdr_from_disk(&leafhdr, dead_leaf2); - ents = ip->d_ops->leaf_ents_p(dead_leaf2); + ents = dp->d_ops->leaf_ents_p(dead_leaf2); dead_level = 0; dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval); } else { @@ -2232,7 +2242,7 @@ xfs_da3_swap_lastblock( dead_node = (xfs_da_intnode_t *)dead_info; xfs_da3_node_hdr_from_disk(&deadhdr, dead_node); - btree = xfs_da3_node_tree_p(dead_node); + btree = dp->d_ops->node_tree_p(dead_node); dead_level = deadhdr.level; dead_hash = be32_to_cpu(btree[deadhdr.count - 1].hashval); } @@ -2241,7 +2251,7 @@ xfs_da3_swap_lastblock( * If the moved block has a left sibling, fix up the pointers. */ if ((sib_blkno = be32_to_cpu(dead_info->back))) { - error = xfs_da3_node_read(tp, ip, sib_blkno, -1, &sib_buf, w); + error = xfs_da3_node_read(tp, dp, sib_blkno, -1, &sib_buf, w); if (error) goto done; sib_info = sib_buf->b_addr; @@ -2263,7 +2273,7 @@ xfs_da3_swap_lastblock( * If the moved block has a right sibling, fix up the pointers. */ if ((sib_blkno = be32_to_cpu(dead_info->forw))) { - error = xfs_da3_node_read(tp, ip, sib_blkno, -1, &sib_buf, w); + error = xfs_da3_node_read(tp, dp, sib_blkno, -1, &sib_buf, w); if (error) goto done; sib_info = sib_buf->b_addr; @@ -2287,7 +2297,7 @@ xfs_da3_swap_lastblock( * Walk down the tree looking for the parent of the moved block. */ for (;;) { - error = xfs_da3_node_read(tp, ip, par_blkno, -1, &par_buf, w); + error = xfs_da3_node_read(tp, dp, par_blkno, -1, &par_buf, w); if (error) goto done; par_node = par_buf->b_addr; @@ -2299,7 +2309,7 @@ xfs_da3_swap_lastblock( goto done; } level = par_hdr.level; - btree = xfs_da3_node_tree_p(par_node); + btree = dp->d_ops->node_tree_p(par_node); for (entno = 0; entno < par_hdr.count && be32_to_cpu(btree[entno].hashval) < dead_hash; @@ -2338,7 +2348,7 @@ xfs_da3_swap_lastblock( error = XFS_ERROR(EFSCORRUPTED); goto done; } - error = xfs_da3_node_read(tp, ip, par_blkno, -1, &par_buf, w); + error = xfs_da3_node_read(tp, dp, par_blkno, -1, &par_buf, w); if (error) goto done; par_node = par_buf->b_addr; @@ -2349,7 +2359,7 @@ xfs_da3_swap_lastblock( error = XFS_ERROR(EFSCORRUPTED); goto done; } - btree = xfs_da3_node_tree_p(par_node); + btree = dp->d_ops->node_tree_p(par_node); entno = 0; } /* diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index ff8b50368c94..72b48b5ec69a 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c @@ -477,6 +477,33 @@ xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp) return ((struct xfs_dir3_leaf *)lp)->__ents; } +/* + * Directory/Attribute Node block operations + */ +static inline int +xfs_da2_node_hdr_size(void) +{ + return sizeof(struct xfs_da_node_hdr); +} + +static struct xfs_da_node_entry * +xfs_da2_node_tree_p(struct xfs_da_intnode *dap) +{ + return dap->__btree; +} + +static inline int +xfs_da3_node_hdr_size(void) +{ + return sizeof(struct xfs_da3_node_hdr); +} + +static inline struct xfs_da_node_entry * +xfs_da3_node_tree_p(struct xfs_da_intnode *dap) +{ + return ((struct xfs_da3_intnode *)dap)->__btree; +} + const struct xfs_dir_ops xfs_dir2_ops = { .sf_entsize = xfs_dir2_sf_entsize, .sf_nextentry = xfs_dir2_sf_nextentry, @@ -508,6 +535,8 @@ const struct xfs_dir_ops xfs_dir2_ops = { .leaf_max_ents = xfs_dir2_max_leaf_ents, .leaf_ents_p = xfs_dir2_leaf_ents_p, + .node_hdr_size = xfs_da2_node_hdr_size, + .node_tree_p = xfs_da2_node_tree_p, }; const struct xfs_dir_ops xfs_dir2_ftype_ops = { @@ -540,6 +569,9 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = { .leaf_hdr_size = xfs_dir2_leaf_hdr_size, .leaf_max_ents = xfs_dir2_max_leaf_ents, .leaf_ents_p = xfs_dir2_leaf_ents_p, + + .node_hdr_size = xfs_da2_node_hdr_size, + .node_tree_p = xfs_da2_node_tree_p, }; const struct xfs_dir_ops xfs_dir3_ops = { @@ -572,6 +604,19 @@ const struct xfs_dir_ops xfs_dir3_ops = { .leaf_hdr_size = xfs_dir3_leaf_hdr_size, .leaf_max_ents = xfs_dir3_max_leaf_ents, .leaf_ents_p = xfs_dir3_leaf_ents_p, + + .node_hdr_size = xfs_da3_node_hdr_size, + .node_tree_p = xfs_da3_node_tree_p, +}; + +const struct xfs_dir_ops xfs_dir2_nondir_ops = { + .node_hdr_size = xfs_da2_node_hdr_size, + .node_tree_p = xfs_da2_node_tree_p, +}; + +const struct xfs_dir_ops xfs_dir3_nondir_ops = { + .node_hdr_size = xfs_da3_node_hdr_size, + .node_tree_p = xfs_da3_node_tree_p, }; /* @@ -594,3 +639,17 @@ xfs_dir_get_ops( return &xfs_dir2_ftype_ops; return &xfs_dir2_ops; } + +const struct xfs_dir_ops * +xfs_nondir_get_ops( + struct xfs_mount *mp, + struct xfs_inode *dp) +{ + if (dp) + return dp->d_ops; + if (mp->m_nondir_inode_ops) + return mp->m_nondir_inode_ops; + if (xfs_sb_version_hascrc(&mp->m_sb)) + return &xfs_dir3_nondir_ops; + return &xfs_dir2_nondir_ops; +} diff --git a/fs/xfs/xfs_da_format.h b/fs/xfs/xfs_da_format.h index 0a567e25cf59..69b4c6e1c52e 100644 --- a/fs/xfs/xfs_da_format.h +++ b/fs/xfs/xfs_da_format.h @@ -127,31 +127,6 @@ extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to, extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from); -static inline int -__xfs_da3_node_hdr_size(bool v3) -{ - if (v3) - return sizeof(struct xfs_da3_node_hdr); - return sizeof(struct xfs_da_node_hdr); -} -static inline int -xfs_da3_node_hdr_size(struct xfs_da_intnode *dap) -{ - bool v3 = dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC); - - return __xfs_da3_node_hdr_size(v3); -} - -static inline struct xfs_da_node_entry * -xfs_da3_node_tree_p(struct xfs_da_intnode *dap) -{ - if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) { - struct xfs_da3_intnode *dap3 = (struct xfs_da3_intnode *)dap; - return dap3->__btree; - } - return dap->__btree; -} - extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to, struct xfs_da_intnode *from); extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to, diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 2b98a33ca383..1b44e83924b7 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -95,13 +95,17 @@ xfs_dir_mount( ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb)); ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= XFS_MAX_BLOCKSIZE); + + mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL); + mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL); + mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog; mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp)); mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp)); mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp)); - nodehdr_size = __xfs_da3_node_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)); + nodehdr_size = mp->m_dir_inode_ops->node_hdr_size(); mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_size) / (uint)sizeof(xfs_da_node_entry_t); mp->m_dir_node_ents = (mp->m_dirblksize - nodehdr_size) / @@ -113,7 +117,6 @@ xfs_dir_mount( else mp->m_dirnameops = &xfs_default_nameops; - mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL); } /* diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 9ba9db731990..c5cad9d9239d 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -79,10 +79,16 @@ struct xfs_dir_ops { int (*leaf_max_ents)(struct xfs_mount *mp); struct xfs_dir2_leaf_entry * (*leaf_ents_p)(struct xfs_dir2_leaf *lp); + + int (*node_hdr_size)(void); + struct xfs_da_node_entry * + (*node_tree_p)(struct xfs_da_intnode *dap); }; extern const struct xfs_dir_ops * xfs_dir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp); +extern const struct xfs_dir_ops * + xfs_nondir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp); /* * Generic directory interface routines diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 0493587ea6bc..c4cd6d47f523 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1203,6 +1203,7 @@ xfs_setup_inode( inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec; xfs_diflags_to_iflags(inode, ip); + ip->d_ops = ip->i_mount->m_nondir_inode_ops; switch (inode->i_mode & S_IFMT) { case S_IFREG: inode->i_op = &xfs_inode_operations; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 973397f66c6b..1d8101a10d8e 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -150,6 +150,7 @@ typedef struct xfs_mount { __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ const struct xfs_nameops *m_dirnameops; /* vector of dir name ops */ const struct xfs_dir_ops *m_dir_inode_ops; /* vector of dir inode ops */ + const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */ int m_dirblksize; /* directory block sz--bytes */ int m_dirblkfsbs; /* directory block sz--fsbs */ xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ -- cgit v1.2.3 From 01ba43b873d9e91ba2e0341fe8cb7e89eaa41661 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:52 +1100 Subject: xfs: vectorise encoding/decoding directory headers Conversion from on-disk structures to in-core header structures currently relies on magic number checks. If the magic number is wrong, but one of the supported values, we do the wrong thing with the encode/decode operation. Split these functions so that there are discrete operations for the specific directory format we are handling. In doing this, move all the header encode/decode functions to xfs_da_format.c as they are directly manipulating the on-disk format. It should be noted that all the growth in binary size is from xfs_da_format.c - the rest of the code actaully shrinks. text data bss dec hex filename 794490 96802 1096 892388 d9de4 fs/xfs/xfs.o.orig 792986 96802 1096 890884 d9804 fs/xfs/xfs.o.p1 792350 96802 1096 890248 d9588 fs/xfs/xfs.o.p2 789293 96802 1096 887191 d8997 fs/xfs/xfs.o.p3 789005 96802 1096 886903 d8997 fs/xfs/xfs.o.p4 789061 96802 1096 886959 d88af fs/xfs/xfs.o.p5 789733 96802 1096 887631 d8b4f fs/xfs/xfs.o.p6 791421 96802 1096 889319 d91e7 fs/xfs/xfs.o.p7 Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_attr_inactive.c | 2 +- fs/xfs/xfs_attr_leaf.c | 4 +- fs/xfs/xfs_attr_list.c | 2 +- fs/xfs/xfs_da_btree.c | 141 +++++++++++------------------- fs/xfs/xfs_da_format.c | 209 ++++++++++++++++++++++++++++++++++++++++++++- fs/xfs/xfs_da_format.h | 16 ---- fs/xfs/xfs_dir2.h | 13 +++ fs/xfs/xfs_dir2_block.c | 2 +- fs/xfs/xfs_dir2_leaf.c | 100 ++++++---------------- fs/xfs/xfs_dir2_node.c | 126 +++++++++------------------ fs/xfs/xfs_dir2_priv.h | 4 - 11 files changed, 338 insertions(+), 281 deletions(-) diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index 4855085f8c6b..09480c57f069 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c @@ -231,7 +231,7 @@ xfs_attr3_node_inactive( } node = bp->b_addr; - xfs_da3_node_hdr_from_disk(&ichdr, node); + dp->d_ops->node_hdr_from_disk(&ichdr, node); parent_blkno = bp->b_bn; if (!ichdr.count) { xfs_trans_brelse(*trans, bp); diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 82f1354c77b6..fdf9992dcbbc 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -916,7 +916,7 @@ xfs_attr3_leaf_to_node( if (error) goto out; node = bp1->b_addr; - xfs_da3_node_hdr_from_disk(&icnodehdr, node); + dp->d_ops->node_hdr_from_disk(&icnodehdr, node); btree = dp->d_ops->node_tree_p(node); leaf = bp2->b_addr; @@ -927,7 +927,7 @@ xfs_attr3_leaf_to_node( btree[0].hashval = entries[icleafhdr.count - 1].hashval; btree[0].before = cpu_to_be32(blkno); icnodehdr.count = 1; - xfs_da3_node_hdr_to_disk(node, &icnodehdr); + dp->d_ops->node_hdr_to_disk(node, &icnodehdr); xfs_trans_log_buf(args->trans, bp1, 0, XFS_LBSIZE(mp) - 1); error = 0; out: diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index ea1c4c46c24f..2d174b128153 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -311,7 +311,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) return XFS_ERROR(EFSCORRUPTED); } - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); for (i = 0; i < nodehdr.count; btree++, i++) { if (cursor->hashval diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 26dfc42a28f9..a51762dae543 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -129,56 +129,6 @@ xfs_da_state_free(xfs_da_state_t *state) kmem_zone_free(xfs_da_state_zone, state); } -void -xfs_da3_node_hdr_from_disk( - struct xfs_da3_icnode_hdr *to, - struct xfs_da_intnode *from) -{ - ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC) || - from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)); - - if (from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) { - struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)from; - - to->forw = be32_to_cpu(hdr3->info.hdr.forw); - to->back = be32_to_cpu(hdr3->info.hdr.back); - to->magic = be16_to_cpu(hdr3->info.hdr.magic); - to->count = be16_to_cpu(hdr3->__count); - to->level = be16_to_cpu(hdr3->__level); - return; - } - to->forw = be32_to_cpu(from->hdr.info.forw); - to->back = be32_to_cpu(from->hdr.info.back); - to->magic = be16_to_cpu(from->hdr.info.magic); - to->count = be16_to_cpu(from->hdr.__count); - to->level = be16_to_cpu(from->hdr.__level); -} - -void -xfs_da3_node_hdr_to_disk( - struct xfs_da_intnode *to, - struct xfs_da3_icnode_hdr *from) -{ - ASSERT(from->magic == XFS_DA_NODE_MAGIC || - from->magic == XFS_DA3_NODE_MAGIC); - - if (from->magic == XFS_DA3_NODE_MAGIC) { - struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)to; - - hdr3->info.hdr.forw = cpu_to_be32(from->forw); - hdr3->info.hdr.back = cpu_to_be32(from->back); - hdr3->info.hdr.magic = cpu_to_be16(from->magic); - hdr3->__count = cpu_to_be16(from->count); - hdr3->__level = cpu_to_be16(from->level); - return; - } - to->hdr.info.forw = cpu_to_be32(from->forw); - to->hdr.info.back = cpu_to_be32(from->back); - to->hdr.info.magic = cpu_to_be16(from->magic); - to->hdr.__count = cpu_to_be16(from->count); - to->hdr.__level = cpu_to_be16(from->level); -} - static bool xfs_da3_node_verify( struct xfs_buf *bp) @@ -186,8 +136,11 @@ xfs_da3_node_verify( struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_da_intnode *hdr = bp->b_addr; struct xfs_da3_icnode_hdr ichdr; + const struct xfs_dir_ops *ops; + + ops = xfs_dir_get_ops(mp, NULL); - xfs_da3_node_hdr_from_disk(&ichdr, hdr); + ops->node_hdr_from_disk(&ichdr, hdr); if (xfs_sb_version_hascrc(&mp->m_sb)) { struct xfs_da3_node_hdr *hdr3 = bp->b_addr; @@ -354,11 +307,12 @@ xfs_da3_node_create( struct xfs_da3_icnode_hdr ichdr = {0}; struct xfs_buf *bp; int error; + struct xfs_inode *dp = args->dp; trace_xfs_da_node_create(args); ASSERT(level <= XFS_DA_NODE_MAXDEPTH); - error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork); + error = xfs_da_get_buf(tp, dp, blkno, -1, &bp, whichfork); if (error) return(error); bp->b_ops = &xfs_da3_node_buf_ops; @@ -377,10 +331,10 @@ xfs_da3_node_create( } ichdr.level = level; - xfs_da3_node_hdr_to_disk(node, &ichdr); + dp->d_ops->node_hdr_to_disk(node, &ichdr); xfs_trans_log_buf(tp, bp, XFS_DA_LOGRANGE(node, &node->hdr, - args->dp->d_ops->node_hdr_size())); + dp->d_ops->node_hdr_size())); *bpp = bp; return(0); @@ -590,7 +544,7 @@ xfs_da3_root_split( oldroot->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) { struct xfs_da3_icnode_hdr nodehdr; - xfs_da3_node_hdr_from_disk(&nodehdr, oldroot); + dp->d_ops->node_hdr_from_disk(&nodehdr, oldroot); btree = dp->d_ops->node_tree_p(oldroot); size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot); level = nodehdr.level; @@ -605,7 +559,7 @@ xfs_da3_root_split( struct xfs_dir2_leaf_entry *ents; leaf = (xfs_dir2_leaf_t *)oldroot; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || @@ -650,14 +604,14 @@ xfs_da3_root_split( return error; node = bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); btree[0].hashval = cpu_to_be32(blk1->hashval); btree[0].before = cpu_to_be32(blk1->blkno); btree[1].hashval = cpu_to_be32(blk2->hashval); btree[1].before = cpu_to_be32(blk2->blkno); nodehdr.count = 2; - xfs_da3_node_hdr_to_disk(node, &nodehdr); + dp->d_ops->node_hdr_to_disk(node, &nodehdr); #ifdef DEBUG if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || @@ -694,11 +648,12 @@ xfs_da3_node_split( int newcount; int error; int useextra; + struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_split(state->args); node = oldblk->bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); /* * With V2 dirs the extra block is data or freespace. @@ -745,7 +700,7 @@ xfs_da3_node_split( * If we had double-split op below us, then add the extra block too. */ node = oldblk->bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); if (oldblk->index <= nodehdr.count) { oldblk->index++; xfs_da3_node_add(state, oldblk, addblk); @@ -800,8 +755,8 @@ xfs_da3_node_rebalance( node1 = blk1->bp->b_addr; node2 = blk2->bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr1, node1); - xfs_da3_node_hdr_from_disk(&nodehdr2, node2); + dp->d_ops->node_hdr_from_disk(&nodehdr1, node1); + dp->d_ops->node_hdr_from_disk(&nodehdr2, node2); btree1 = dp->d_ops->node_tree_p(node1); btree2 = dp->d_ops->node_tree_p(node2); @@ -816,8 +771,8 @@ xfs_da3_node_rebalance( tmpnode = node1; node1 = node2; node2 = tmpnode; - xfs_da3_node_hdr_from_disk(&nodehdr1, node1); - xfs_da3_node_hdr_from_disk(&nodehdr2, node2); + dp->d_ops->node_hdr_from_disk(&nodehdr1, node1); + dp->d_ops->node_hdr_from_disk(&nodehdr2, node2); btree1 = dp->d_ops->node_tree_p(node1); btree2 = dp->d_ops->node_tree_p(node2); swap = 1; @@ -881,12 +836,12 @@ xfs_da3_node_rebalance( /* * Log header of node 1 and all current bits of node 2. */ - xfs_da3_node_hdr_to_disk(node1, &nodehdr1); + dp->d_ops->node_hdr_to_disk(node1, &nodehdr1); xfs_trans_log_buf(tp, blk1->bp, XFS_DA_LOGRANGE(node1, &node1->hdr, dp->d_ops->node_hdr_size())); - xfs_da3_node_hdr_to_disk(node2, &nodehdr2); + dp->d_ops->node_hdr_to_disk(node2, &nodehdr2); xfs_trans_log_buf(tp, blk2->bp, XFS_DA_LOGRANGE(node2, &node2->hdr, dp->d_ops->node_hdr_size() + @@ -899,8 +854,8 @@ xfs_da3_node_rebalance( if (swap) { node1 = blk1->bp->b_addr; node2 = blk2->bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr1, node1); - xfs_da3_node_hdr_from_disk(&nodehdr2, node2); + dp->d_ops->node_hdr_from_disk(&nodehdr1, node1); + dp->d_ops->node_hdr_from_disk(&nodehdr2, node2); btree1 = dp->d_ops->node_tree_p(node1); btree2 = dp->d_ops->node_tree_p(node2); } @@ -934,7 +889,7 @@ xfs_da3_node_add( trace_xfs_da_node_add(state->args); node = oldblk->bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); ASSERT(oldblk->index >= 0 && oldblk->index <= nodehdr.count); @@ -958,7 +913,7 @@ xfs_da3_node_add( tmp + sizeof(*btree))); nodehdr.count += 1; - xfs_da3_node_hdr_to_disk(node, &nodehdr); + dp->d_ops->node_hdr_to_disk(node, &nodehdr); xfs_trans_log_buf(state->args->trans, oldblk->bp, XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size())); @@ -1097,6 +1052,7 @@ xfs_da3_root_join( struct xfs_da3_icnode_hdr oldroothdr; struct xfs_da_node_entry *btree; int error; + struct xfs_inode *dp = state->args->dp; trace_xfs_da_root_join(state->args); @@ -1104,7 +1060,7 @@ xfs_da3_root_join( args = state->args; oldroot = root_blk->bp->b_addr; - xfs_da3_node_hdr_from_disk(&oldroothdr, oldroot); + dp->d_ops->node_hdr_from_disk(&oldroothdr, oldroot); ASSERT(oldroothdr.forw == 0); ASSERT(oldroothdr.back == 0); @@ -1118,10 +1074,10 @@ xfs_da3_root_join( * Read in the (only) child block, then copy those bytes into * the root block's buffer and free the original child block. */ - btree = args->dp->d_ops->node_tree_p(oldroot); + btree = dp->d_ops->node_tree_p(oldroot); child = be32_to_cpu(btree[0].before); ASSERT(child != 0); - error = xfs_da3_node_read(args->trans, args->dp, child, -1, &bp, + error = xfs_da3_node_read(args->trans, dp, child, -1, &bp, args->whichfork); if (error) return error; @@ -1171,6 +1127,7 @@ xfs_da3_node_toosmall( int error; int retval; int i; + struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_toosmall(state->args); @@ -1182,7 +1139,7 @@ xfs_da3_node_toosmall( blk = &state->path.blk[ state->path.active-1 ]; info = blk->bp->b_addr; node = (xfs_da_intnode_t *)info; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); if (nodehdr.count > (state->node_ents >> 1)) { *action = 0; /* blk over 50%, don't try to join */ return(0); /* blk over 50%, don't try to join */ @@ -1234,13 +1191,13 @@ xfs_da3_node_toosmall( blkno = nodehdr.back; if (blkno == 0) continue; - error = xfs_da3_node_read(state->args->trans, state->args->dp, + error = xfs_da3_node_read(state->args->trans, dp, blkno, -1, &bp, state->args->whichfork); if (error) return(error); node = bp->b_addr; - xfs_da3_node_hdr_from_disk(&thdr, node); + dp->d_ops->node_hdr_from_disk(&thdr, node); xfs_trans_brelse(state->args->trans, bp); if (count - thdr.count >= 0) @@ -1287,7 +1244,7 @@ xfs_da3_node_lasthash( struct xfs_da3_icnode_hdr nodehdr; node = bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); if (count) *count = nodehdr.count; if (!nodehdr.count) @@ -1338,7 +1295,7 @@ xfs_da3_fixhashpath( struct xfs_da3_icnode_hdr nodehdr; node = blk->bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); if (be32_to_cpu(btree->hashval) == lasthash) break; @@ -1370,7 +1327,7 @@ xfs_da3_node_remove( trace_xfs_da_node_remove(state->args); node = drop_blk->bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); ASSERT(drop_blk->index < nodehdr.count); ASSERT(drop_blk->index >= 0); @@ -1391,7 +1348,7 @@ xfs_da3_node_remove( xfs_trans_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index]))); nodehdr.count -= 1; - xfs_da3_node_hdr_to_disk(node, &nodehdr); + dp->d_ops->node_hdr_to_disk(node, &nodehdr); xfs_trans_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size())); @@ -1426,8 +1383,8 @@ xfs_da3_node_unbalance( drop_node = drop_blk->bp->b_addr; save_node = save_blk->bp->b_addr; - xfs_da3_node_hdr_from_disk(&drop_hdr, drop_node); - xfs_da3_node_hdr_from_disk(&save_hdr, save_node); + dp->d_ops->node_hdr_from_disk(&drop_hdr, drop_node); + dp->d_ops->node_hdr_from_disk(&save_hdr, save_node); drop_btree = dp->d_ops->node_tree_p(drop_node); save_btree = dp->d_ops->node_tree_p(save_node); tp = state->args->trans; @@ -1463,7 +1420,7 @@ xfs_da3_node_unbalance( memcpy(&save_btree[sindex], &drop_btree[0], tmp); save_hdr.count += drop_hdr.count; - xfs_da3_node_hdr_to_disk(save_node, &save_hdr); + dp->d_ops->node_hdr_to_disk(save_node, &save_hdr); xfs_trans_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, &save_node->hdr, dp->d_ops->node_hdr_size())); @@ -1556,7 +1513,7 @@ xfs_da3_node_lookup_int( * Search an intermediate node for a match. */ node = blk->bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); max = nodehdr.count; @@ -1665,8 +1622,8 @@ xfs_da3_node_order( node1 = node1_bp->b_addr; node2 = node2_bp->b_addr; - xfs_da3_node_hdr_from_disk(&node1hdr, node1); - xfs_da3_node_hdr_from_disk(&node2hdr, node2); + dp->d_ops->node_hdr_from_disk(&node1hdr, node1); + dp->d_ops->node_hdr_from_disk(&node2hdr, node2); btree1 = dp->d_ops->node_tree_p(node1); btree2 = dp->d_ops->node_tree_p(node2); @@ -1888,7 +1845,7 @@ xfs_da3_path_shift( level = (path->active-1) - 1; /* skip bottom layer in path */ for (blk = &path->blk[level]; level >= 0; blk--, level--) { node = blk->bp->b_addr; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); if (forward && (blk->index < nodehdr.count - 1)) { @@ -1945,7 +1902,7 @@ xfs_da3_path_shift( case XFS_DA3_NODE_MAGIC: blk->magic = XFS_DA_NODE_MAGIC; node = (xfs_da_intnode_t *)info; - xfs_da3_node_hdr_from_disk(&nodehdr, node); + dp->d_ops->node_hdr_from_disk(&nodehdr, node); btree = dp->d_ops->node_tree_p(node); blk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval); if (forward) @@ -2233,7 +2190,7 @@ xfs_da3_swap_lastblock( struct xfs_dir2_leaf_entry *ents; dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, dead_leaf2); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, dead_leaf2); ents = dp->d_ops->leaf_ents_p(dead_leaf2); dead_level = 0; dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval); @@ -2241,7 +2198,7 @@ xfs_da3_swap_lastblock( struct xfs_da3_icnode_hdr deadhdr; dead_node = (xfs_da_intnode_t *)dead_info; - xfs_da3_node_hdr_from_disk(&deadhdr, dead_node); + dp->d_ops->node_hdr_from_disk(&deadhdr, dead_node); btree = dp->d_ops->node_tree_p(dead_node); dead_level = deadhdr.level; dead_hash = be32_to_cpu(btree[deadhdr.count - 1].hashval); @@ -2301,7 +2258,7 @@ xfs_da3_swap_lastblock( if (error) goto done; par_node = par_buf->b_addr; - xfs_da3_node_hdr_from_disk(&par_hdr, par_node); + dp->d_ops->node_hdr_from_disk(&par_hdr, par_node); if (level >= 0 && level != par_hdr.level + 1) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)", XFS_ERRLEVEL_LOW, mp); @@ -2352,7 +2309,7 @@ xfs_da3_swap_lastblock( if (error) goto done; par_node = par_buf->b_addr; - xfs_da3_node_hdr_from_disk(&par_hdr, par_node); + dp->d_ops->node_hdr_from_disk(&par_hdr, par_node); if (par_hdr.level != level) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)", XFS_ERRLEVEL_LOW, mp); diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index 72b48b5ec69a..b232c275791d 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c @@ -464,19 +464,84 @@ xfs_dir3_leaf_hdr_size(void) return sizeof(struct xfs_dir3_leaf_hdr); } -static inline int +static int xfs_dir3_max_leaf_ents(struct xfs_mount *mp) { return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size()) / (uint)sizeof(struct xfs_dir2_leaf_entry); } -static inline struct xfs_dir2_leaf_entry * +static struct xfs_dir2_leaf_entry * xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp) { return ((struct xfs_dir3_leaf *)lp)->__ents; } +static void +xfs_dir2_leaf_hdr_from_disk( + struct xfs_dir3_icleaf_hdr *to, + struct xfs_dir2_leaf *from) +{ + to->forw = be32_to_cpu(from->hdr.info.forw); + to->back = be32_to_cpu(from->hdr.info.back); + to->magic = be16_to_cpu(from->hdr.info.magic); + to->count = be16_to_cpu(from->hdr.count); + to->stale = be16_to_cpu(from->hdr.stale); + + ASSERT(to->magic == XFS_DIR2_LEAF1_MAGIC || + to->magic == XFS_DIR2_LEAFN_MAGIC); +} + +static void +xfs_dir2_leaf_hdr_to_disk( + struct xfs_dir2_leaf *to, + struct xfs_dir3_icleaf_hdr *from) +{ + ASSERT(from->magic == XFS_DIR2_LEAF1_MAGIC || + from->magic == XFS_DIR2_LEAFN_MAGIC); + + to->hdr.info.forw = cpu_to_be32(from->forw); + to->hdr.info.back = cpu_to_be32(from->back); + to->hdr.info.magic = cpu_to_be16(from->magic); + to->hdr.count = cpu_to_be16(from->count); + to->hdr.stale = cpu_to_be16(from->stale); +} + +static void +xfs_dir3_leaf_hdr_from_disk( + struct xfs_dir3_icleaf_hdr *to, + struct xfs_dir2_leaf *from) +{ + struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)from; + + to->forw = be32_to_cpu(hdr3->info.hdr.forw); + to->back = be32_to_cpu(hdr3->info.hdr.back); + to->magic = be16_to_cpu(hdr3->info.hdr.magic); + to->count = be16_to_cpu(hdr3->count); + to->stale = be16_to_cpu(hdr3->stale); + + ASSERT(to->magic == XFS_DIR3_LEAF1_MAGIC || + to->magic == XFS_DIR3_LEAFN_MAGIC); +} + +static void +xfs_dir3_leaf_hdr_to_disk( + struct xfs_dir2_leaf *to, + struct xfs_dir3_icleaf_hdr *from) +{ + struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)to; + + ASSERT(from->magic == XFS_DIR3_LEAF1_MAGIC || + from->magic == XFS_DIR3_LEAFN_MAGIC); + + hdr3->info.hdr.forw = cpu_to_be32(from->forw); + hdr3->info.hdr.back = cpu_to_be32(from->back); + hdr3->info.hdr.magic = cpu_to_be16(from->magic); + hdr3->count = cpu_to_be16(from->count); + hdr3->stale = cpu_to_be16(from->stale); +} + + /* * Directory/Attribute Node block operations */ @@ -504,6 +569,121 @@ xfs_da3_node_tree_p(struct xfs_da_intnode *dap) return ((struct xfs_da3_intnode *)dap)->__btree; } +static void +xfs_da2_node_hdr_from_disk( + struct xfs_da3_icnode_hdr *to, + struct xfs_da_intnode *from) +{ + ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); + to->forw = be32_to_cpu(from->hdr.info.forw); + to->back = be32_to_cpu(from->hdr.info.back); + to->magic = be16_to_cpu(from->hdr.info.magic); + to->count = be16_to_cpu(from->hdr.__count); + to->level = be16_to_cpu(from->hdr.__level); +} + +static void +xfs_da2_node_hdr_to_disk( + struct xfs_da_intnode *to, + struct xfs_da3_icnode_hdr *from) +{ + ASSERT(from->magic == XFS_DA_NODE_MAGIC); + to->hdr.info.forw = cpu_to_be32(from->forw); + to->hdr.info.back = cpu_to_be32(from->back); + to->hdr.info.magic = cpu_to_be16(from->magic); + to->hdr.__count = cpu_to_be16(from->count); + to->hdr.__level = cpu_to_be16(from->level); +} + +static void +xfs_da3_node_hdr_from_disk( + struct xfs_da3_icnode_hdr *to, + struct xfs_da_intnode *from) +{ + struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)from; + + ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)); + to->forw = be32_to_cpu(hdr3->info.hdr.forw); + to->back = be32_to_cpu(hdr3->info.hdr.back); + to->magic = be16_to_cpu(hdr3->info.hdr.magic); + to->count = be16_to_cpu(hdr3->__count); + to->level = be16_to_cpu(hdr3->__level); +} + +static void +xfs_da3_node_hdr_to_disk( + struct xfs_da_intnode *to, + struct xfs_da3_icnode_hdr *from) +{ + struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)to; + + ASSERT(from->magic == XFS_DA3_NODE_MAGIC); + hdr3->info.hdr.forw = cpu_to_be32(from->forw); + hdr3->info.hdr.back = cpu_to_be32(from->back); + hdr3->info.hdr.magic = cpu_to_be16(from->magic); + hdr3->__count = cpu_to_be16(from->count); + hdr3->__level = cpu_to_be16(from->level); +} + + +/* + * Directory free space block operations + */ +static void +xfs_dir2_free_hdr_from_disk( + struct xfs_dir3_icfree_hdr *to, + struct xfs_dir2_free *from) +{ + to->magic = be32_to_cpu(from->hdr.magic); + to->firstdb = be32_to_cpu(from->hdr.firstdb); + to->nvalid = be32_to_cpu(from->hdr.nvalid); + to->nused = be32_to_cpu(from->hdr.nused); + ASSERT(to->magic == XFS_DIR2_FREE_MAGIC); +} + +static void +xfs_dir2_free_hdr_to_disk( + struct xfs_dir2_free *to, + struct xfs_dir3_icfree_hdr *from) +{ + ASSERT(from->magic == XFS_DIR2_FREE_MAGIC); + + to->hdr.magic = cpu_to_be32(from->magic); + to->hdr.firstdb = cpu_to_be32(from->firstdb); + to->hdr.nvalid = cpu_to_be32(from->nvalid); + to->hdr.nused = cpu_to_be32(from->nused); +} + +static void +xfs_dir3_free_hdr_from_disk( + struct xfs_dir3_icfree_hdr *to, + struct xfs_dir2_free *from) +{ + struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)from; + + to->magic = be32_to_cpu(hdr3->hdr.magic); + to->firstdb = be32_to_cpu(hdr3->firstdb); + to->nvalid = be32_to_cpu(hdr3->nvalid); + to->nused = be32_to_cpu(hdr3->nused); + + ASSERT(to->magic == XFS_DIR3_FREE_MAGIC); +} + +static void +xfs_dir3_free_hdr_to_disk( + struct xfs_dir2_free *to, + struct xfs_dir3_icfree_hdr *from) +{ + struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)to; + + ASSERT(from->magic == XFS_DIR3_FREE_MAGIC); + + hdr3->hdr.magic = cpu_to_be32(from->magic); + hdr3->firstdb = cpu_to_be32(from->firstdb); + hdr3->nvalid = cpu_to_be32(from->nvalid); + hdr3->nused = cpu_to_be32(from->nused); +} + const struct xfs_dir_ops xfs_dir2_ops = { .sf_entsize = xfs_dir2_sf_entsize, .sf_nextentry = xfs_dir2_sf_nextentry, @@ -532,11 +712,18 @@ const struct xfs_dir_ops xfs_dir2_ops = { .data_unused_p = xfs_dir2_data_unused_p, .leaf_hdr_size = xfs_dir2_leaf_hdr_size, + .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk, + .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk, .leaf_max_ents = xfs_dir2_max_leaf_ents, .leaf_ents_p = xfs_dir2_leaf_ents_p, .node_hdr_size = xfs_da2_node_hdr_size, + .node_hdr_to_disk = xfs_da2_node_hdr_to_disk, + .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, + + .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk, + .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk, }; const struct xfs_dir_ops xfs_dir2_ftype_ops = { @@ -567,11 +754,18 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = { .data_unused_p = xfs_dir2_data_unused_p, .leaf_hdr_size = xfs_dir2_leaf_hdr_size, + .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk, + .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk, .leaf_max_ents = xfs_dir2_max_leaf_ents, .leaf_ents_p = xfs_dir2_leaf_ents_p, .node_hdr_size = xfs_da2_node_hdr_size, + .node_hdr_to_disk = xfs_da2_node_hdr_to_disk, + .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, + + .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk, + .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk, }; const struct xfs_dir_ops xfs_dir3_ops = { @@ -602,20 +796,31 @@ const struct xfs_dir_ops xfs_dir3_ops = { .data_unused_p = xfs_dir3_data_unused_p, .leaf_hdr_size = xfs_dir3_leaf_hdr_size, + .leaf_hdr_to_disk = xfs_dir3_leaf_hdr_to_disk, + .leaf_hdr_from_disk = xfs_dir3_leaf_hdr_from_disk, .leaf_max_ents = xfs_dir3_max_leaf_ents, .leaf_ents_p = xfs_dir3_leaf_ents_p, .node_hdr_size = xfs_da3_node_hdr_size, + .node_hdr_to_disk = xfs_da3_node_hdr_to_disk, + .node_hdr_from_disk = xfs_da3_node_hdr_from_disk, .node_tree_p = xfs_da3_node_tree_p, + + .free_hdr_to_disk = xfs_dir3_free_hdr_to_disk, + .free_hdr_from_disk = xfs_dir3_free_hdr_from_disk, }; const struct xfs_dir_ops xfs_dir2_nondir_ops = { .node_hdr_size = xfs_da2_node_hdr_size, + .node_hdr_to_disk = xfs_da2_node_hdr_to_disk, + .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, }; const struct xfs_dir_ops xfs_dir3_nondir_ops = { .node_hdr_size = xfs_da3_node_hdr_size, + .node_hdr_to_disk = xfs_da3_node_hdr_to_disk, + .node_hdr_from_disk = xfs_da3_node_hdr_from_disk, .node_tree_p = xfs_da3_node_tree_p, }; diff --git a/fs/xfs/xfs_da_format.h b/fs/xfs/xfs_da_format.h index 69b4c6e1c52e..1ff7b9f42097 100644 --- a/fs/xfs/xfs_da_format.h +++ b/fs/xfs/xfs_da_format.h @@ -122,16 +122,6 @@ struct xfs_da3_icnode_hdr { __uint16_t level; }; -extern void xfs_da3_node_hdr_from_disk(struct xfs_da3_icnode_hdr *to, - struct xfs_da_intnode *from); -extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to, - struct xfs_da3_icnode_hdr *from); - -extern void xfs_da3_intnode_from_disk(struct xfs_da3_icnode_hdr *to, - struct xfs_da_intnode *from); -extern void xfs_da3_intnode_to_disk(struct xfs_da_intnode *to, - struct xfs_da3_icnode_hdr *from); - #define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize /* @@ -523,9 +513,6 @@ struct xfs_dir3_leaf { #define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc) -extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to, - struct xfs_dir2_leaf *from); - /* * Get address of the bestcount field in the single-leaf block. */ @@ -717,9 +704,6 @@ struct xfs_dir3_icfree_hdr { }; -void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to, - struct xfs_dir2_free *from); - static inline int xfs_dir3_free_hdr_size(struct xfs_mount *mp) { diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index c5cad9d9239d..61195348f667 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -76,13 +76,26 @@ struct xfs_dir_ops { (*data_unused_p)(struct xfs_dir2_data_hdr *hdr); int (*leaf_hdr_size)(void); + void (*leaf_hdr_to_disk)(struct xfs_dir2_leaf *to, + struct xfs_dir3_icleaf_hdr *from); + void (*leaf_hdr_from_disk)(struct xfs_dir3_icleaf_hdr *to, + struct xfs_dir2_leaf *from); int (*leaf_max_ents)(struct xfs_mount *mp); struct xfs_dir2_leaf_entry * (*leaf_ents_p)(struct xfs_dir2_leaf *lp); int (*node_hdr_size)(void); + void (*node_hdr_to_disk)(struct xfs_da_intnode *to, + struct xfs_da3_icnode_hdr *from); + void (*node_hdr_from_disk)(struct xfs_da3_icnode_hdr *to, + struct xfs_da_intnode *from); struct xfs_da_node_entry * (*node_tree_p)(struct xfs_da_intnode *dap); + + void (*free_hdr_to_disk)(struct xfs_dir2_free *to, + struct xfs_dir3_icfree_hdr *from); + void (*free_hdr_from_disk)(struct xfs_dir3_icfree_hdr *to, + struct xfs_dir2_free *from); }; extern const struct xfs_dir_ops * diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 75f815786b97..c1ff552aa7bf 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -936,7 +936,7 @@ xfs_dir2_leaf_to_block( tp = args->trans; mp = dp->i_mount; leaf = lbp->b_addr; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); ltp = xfs_dir2_leaf_tail_p(mp, leaf); diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 16fdc0e627a7..2fb8db9fb574 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -64,7 +64,7 @@ xfs_dir3_leaf1_check( struct xfs_dir2_leaf *leaf = bp->b_addr; struct xfs_dir3_icleaf_hdr leafhdr; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) { struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; @@ -79,62 +79,6 @@ xfs_dir3_leaf1_check( #define xfs_dir3_leaf_check(dp, bp) #endif -void -xfs_dir3_leaf_hdr_from_disk( - struct xfs_dir3_icleaf_hdr *to, - struct xfs_dir2_leaf *from) -{ - if (from->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || - from->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)) { - to->forw = be32_to_cpu(from->hdr.info.forw); - to->back = be32_to_cpu(from->hdr.info.back); - to->magic = be16_to_cpu(from->hdr.info.magic); - to->count = be16_to_cpu(from->hdr.count); - to->stale = be16_to_cpu(from->hdr.stale); - } else { - struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)from; - - to->forw = be32_to_cpu(hdr3->info.hdr.forw); - to->back = be32_to_cpu(hdr3->info.hdr.back); - to->magic = be16_to_cpu(hdr3->info.hdr.magic); - to->count = be16_to_cpu(hdr3->count); - to->stale = be16_to_cpu(hdr3->stale); - } - - ASSERT(to->magic == XFS_DIR2_LEAF1_MAGIC || - to->magic == XFS_DIR3_LEAF1_MAGIC || - to->magic == XFS_DIR2_LEAFN_MAGIC || - to->magic == XFS_DIR3_LEAFN_MAGIC); -} - -void -xfs_dir3_leaf_hdr_to_disk( - struct xfs_dir2_leaf *to, - struct xfs_dir3_icleaf_hdr *from) -{ - ASSERT(from->magic == XFS_DIR2_LEAF1_MAGIC || - from->magic == XFS_DIR3_LEAF1_MAGIC || - from->magic == XFS_DIR2_LEAFN_MAGIC || - from->magic == XFS_DIR3_LEAFN_MAGIC); - - if (from->magic == XFS_DIR2_LEAF1_MAGIC || - from->magic == XFS_DIR2_LEAFN_MAGIC) { - to->hdr.info.forw = cpu_to_be32(from->forw); - to->hdr.info.back = cpu_to_be32(from->back); - to->hdr.info.magic = cpu_to_be16(from->magic); - to->hdr.count = cpu_to_be16(from->count); - to->hdr.stale = cpu_to_be16(from->stale); - } else { - struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)to; - - hdr3->info.hdr.forw = cpu_to_be32(from->forw); - hdr3->info.hdr.back = cpu_to_be32(from->back); - hdr3->info.hdr.magic = cpu_to_be16(from->magic); - hdr3->count = cpu_to_be16(from->count); - hdr3->stale = cpu_to_be16(from->stale); - } -} - bool xfs_dir3_leaf_check_int( struct xfs_mount *mp, @@ -147,6 +91,7 @@ xfs_dir3_leaf_check_int( int stale; int i; const struct xfs_dir_ops *ops; + struct xfs_dir3_icleaf_hdr leafhdr; /* * we can be passed a null dp here from a verifier, so we need to go the @@ -154,6 +99,11 @@ xfs_dir3_leaf_check_int( */ ops = xfs_dir_get_ops(mp, dp); + if (!hdr) { + ops->leaf_hdr_from_disk(&leafhdr, leaf); + hdr = &leafhdr; + } + ents = ops->leaf_ents_p(leaf); ltp = xfs_dir2_leaf_tail_p(mp, leaf); @@ -198,7 +148,6 @@ xfs_dir3_leaf_verify( { struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_dir2_leaf *leaf = bp->b_addr; - struct xfs_dir3_icleaf_hdr leafhdr; ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); @@ -220,8 +169,7 @@ xfs_dir3_leaf_verify( return false; } - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); - return xfs_dir3_leaf_check_int(mp, NULL, &leafhdr, leaf); + return xfs_dir3_leaf_check_int(mp, NULL, NULL, leaf); } static void @@ -474,10 +422,10 @@ xfs_dir2_block_to_leaf( /* * Set the counts in the leaf header. */ - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); leafhdr.count = be32_to_cpu(btp->count); leafhdr.stale = be32_to_cpu(btp->stale); - xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); + dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(tp, dp, lbp); /* @@ -706,7 +654,7 @@ xfs_dir2_leaf_addname( leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(mp, leaf); ents = dp->d_ops->leaf_ents_p(leaf); - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); bestsp = xfs_dir2_leaf_bests_p(ltp); length = dp->d_ops->data_entsize(args->namelen); @@ -945,7 +893,7 @@ xfs_dir2_leaf_addname( /* * Log the leaf fields and give up the buffers. */ - xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); + dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(tp, dp, lbp); xfs_dir3_leaf_log_ents(tp, dp, lbp, lfloglow, lfloghigh); xfs_dir3_leaf_check(dp, lbp); @@ -968,6 +916,7 @@ xfs_dir3_leaf_compact( int loglow; /* first leaf entry to log */ int to; /* target leaf index */ struct xfs_dir2_leaf_entry *ents; + struct xfs_inode *dp = args->dp; leaf = bp->b_addr; if (!leafhdr->stale) @@ -976,7 +925,7 @@ xfs_dir3_leaf_compact( /* * Compress out the stale entries in place. */ - ents = args->dp->d_ops->leaf_ents_p(leaf); + ents = dp->d_ops->leaf_ents_p(leaf); for (from = to = 0, loglow = -1; from < leafhdr->count; from++) { if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) continue; @@ -997,11 +946,10 @@ xfs_dir3_leaf_compact( leafhdr->count -= leafhdr->stale; leafhdr->stale = 0; - xfs_dir3_leaf_hdr_to_disk(leaf, leafhdr); - xfs_dir3_leaf_log_header(args->trans, args->dp, bp); + dp->d_ops->leaf_hdr_to_disk(leaf, leafhdr); + xfs_dir3_leaf_log_header(args->trans, dp, bp); if (loglow != -1) - xfs_dir3_leaf_log_ents(args->trans, args->dp, bp, - loglow, to - 1); + xfs_dir3_leaf_log_ents(args->trans, dp, bp, loglow, to - 1); } /* @@ -1290,7 +1238,7 @@ xfs_dir2_leaf_lookup_int( leaf = lbp->b_addr; xfs_dir3_leaf_check(dp, lbp); ents = dp->d_ops->leaf_ents_p(leaf); - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); /* * Look for the first leaf entry with our hash value. @@ -1425,7 +1373,7 @@ xfs_dir2_leaf_removename( hdr = dbp->b_addr; xfs_dir3_data_check(dp, dbp); bf = dp->d_ops->data_bestfree_p(hdr); - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); /* * Point to the leaf entry, use that to point to the data entry. @@ -1449,7 +1397,7 @@ xfs_dir2_leaf_removename( * We just mark the leaf entry stale by putting a null in it. */ leafhdr.stale++; - xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); + dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(tp, dp, lbp); lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); @@ -1602,7 +1550,7 @@ xfs_dir2_leaf_search_hash( leaf = lbp->b_addr; ents = args->dp->d_ops->leaf_ents_p(leaf); - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + args->dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); /* * Note, the table cannot be empty, so we have to go through the loop. @@ -1791,7 +1739,7 @@ xfs_dir2_node_to_leaf( return 0; lbp = state->path.blk[0].bp; leaf = lbp->b_addr; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); @@ -1803,7 +1751,7 @@ xfs_dir2_node_to_leaf( if (error) return error; free = fbp->b_addr; - xfs_dir3_free_hdr_from_disk(&freehdr, free); + dp->d_ops->free_hdr_from_disk(&freehdr, free); ASSERT(!freehdr.firstdb); @@ -1840,7 +1788,7 @@ xfs_dir2_node_to_leaf( memcpy(xfs_dir2_leaf_bests_p(ltp), xfs_dir3_free_bests_p(mp, free), freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); - xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); + dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(tp, dp, lbp); xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); xfs_dir3_leaf_log_tail(tp, lbp); diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 3a426ed9b16e..eaee8c36bcc4 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -68,7 +68,7 @@ xfs_dir3_leafn_check( struct xfs_dir2_leaf *leaf = bp->b_addr; struct xfs_dir3_icleaf_hdr leafhdr; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) { struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; @@ -192,53 +192,6 @@ xfs_dir2_free_try_read( return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp); } - -void -xfs_dir3_free_hdr_from_disk( - struct xfs_dir3_icfree_hdr *to, - struct xfs_dir2_free *from) -{ - if (from->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)) { - to->magic = be32_to_cpu(from->hdr.magic); - to->firstdb = be32_to_cpu(from->hdr.firstdb); - to->nvalid = be32_to_cpu(from->hdr.nvalid); - to->nused = be32_to_cpu(from->hdr.nused); - } else { - struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)from; - - to->magic = be32_to_cpu(hdr3->hdr.magic); - to->firstdb = be32_to_cpu(hdr3->firstdb); - to->nvalid = be32_to_cpu(hdr3->nvalid); - to->nused = be32_to_cpu(hdr3->nused); - } - - ASSERT(to->magic == XFS_DIR2_FREE_MAGIC || - to->magic == XFS_DIR3_FREE_MAGIC); -} - -static void -xfs_dir3_free_hdr_to_disk( - struct xfs_dir2_free *to, - struct xfs_dir3_icfree_hdr *from) -{ - ASSERT(from->magic == XFS_DIR2_FREE_MAGIC || - from->magic == XFS_DIR3_FREE_MAGIC); - - if (from->magic == XFS_DIR2_FREE_MAGIC) { - to->hdr.magic = cpu_to_be32(from->magic); - to->hdr.firstdb = cpu_to_be32(from->firstdb); - to->hdr.nvalid = cpu_to_be32(from->nvalid); - to->hdr.nused = cpu_to_be32(from->nused); - } else { - struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)to; - - hdr3->hdr.magic = cpu_to_be32(from->magic); - hdr3->firstdb = cpu_to_be32(from->firstdb); - hdr3->nvalid = cpu_to_be32(from->nvalid); - hdr3->nused = cpu_to_be32(from->nused); - } -} - static int xfs_dir3_free_get_buf( struct xfs_trans *tp, @@ -276,7 +229,7 @@ xfs_dir3_free_get_buf( uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); } else hdr.magic = XFS_DIR2_FREE_MAGIC; - xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr); + dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr); *bpp = bp; return 0; } @@ -368,7 +321,7 @@ xfs_dir2_leaf_to_node( return error; free = fbp->b_addr; - xfs_dir3_free_hdr_from_disk(&freehdr, free); + dp->d_ops->free_hdr_from_disk(&freehdr, free); leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(mp, leaf); ASSERT(be32_to_cpu(ltp->bestcount) <= @@ -392,7 +345,7 @@ xfs_dir2_leaf_to_node( freehdr.nused = n; freehdr.nvalid = be32_to_cpu(ltp->bestcount); - xfs_dir3_free_hdr_to_disk(fbp->b_addr, &freehdr); + dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); xfs_dir2_free_log_bests(tp, fbp, 0, freehdr.nvalid - 1); xfs_dir2_free_log_header(tp, fbp); @@ -442,7 +395,7 @@ xfs_dir2_leafn_add( mp = dp->i_mount; tp = args->trans; leaf = bp->b_addr; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); /* @@ -497,7 +450,7 @@ xfs_dir2_leafn_add( lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, args->blkno, args->index)); - xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); + dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(tp, dp, bp); xfs_dir3_leaf_log_ents(tp, dp, bp, lfloglow, lfloghigh); xfs_dir3_leaf_check(dp, bp); @@ -507,20 +460,20 @@ xfs_dir2_leafn_add( #ifdef DEBUG static void xfs_dir2_free_hdr_check( - struct xfs_mount *mp, + struct xfs_inode *dp, struct xfs_buf *bp, xfs_dir2_db_t db) { struct xfs_dir3_icfree_hdr hdr; - xfs_dir3_free_hdr_from_disk(&hdr, bp->b_addr); + dp->d_ops->free_hdr_from_disk(&hdr, bp->b_addr); - ASSERT((hdr.firstdb % xfs_dir3_free_max_bests(mp)) == 0); + ASSERT((hdr.firstdb % xfs_dir3_free_max_bests(dp->i_mount)) == 0); ASSERT(hdr.firstdb <= db); ASSERT(db < hdr.firstdb + hdr.nvalid); } #else -#define xfs_dir2_free_hdr_check(mp, dp, db) +#define xfs_dir2_free_hdr_check(dp, bp, db) #endif /* DEBUG */ /* @@ -537,7 +490,7 @@ xfs_dir2_leafn_lasthash( struct xfs_dir2_leaf_entry *ents; struct xfs_dir3_icleaf_hdr leafhdr; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); @@ -584,7 +537,7 @@ xfs_dir2_leafn_lookup_for_addname( tp = args->trans; mp = dp->i_mount; leaf = bp->b_addr; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, bp); @@ -655,7 +608,7 @@ xfs_dir2_leafn_lookup_for_addname( return error; free = curbp->b_addr; - xfs_dir2_free_hdr_check(mp, curbp, curdb); + xfs_dir2_free_hdr_check(dp, curbp, curdb); } /* * Get the index for our entry. @@ -734,7 +687,7 @@ xfs_dir2_leafn_lookup_for_entry( tp = args->trans; mp = dp->i_mount; leaf = bp->b_addr; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, bp); @@ -969,8 +922,8 @@ xfs_dir2_leafn_order( struct xfs_dir3_icleaf_hdr hdr1; struct xfs_dir3_icleaf_hdr hdr2; - xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1); - xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2); + dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1); + dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2); ents1 = dp->d_ops->leaf_ents_p(leaf1); ents2 = dp->d_ops->leaf_ents_p(leaf2); @@ -1025,8 +978,8 @@ xfs_dir2_leafn_rebalance( } leaf1 = blk1->bp->b_addr; leaf2 = blk2->bp->b_addr; - xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1); - xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2); + dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1); + dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2); ents1 = dp->d_ops->leaf_ents_p(leaf1); ents2 = dp->d_ops->leaf_ents_p(leaf2); @@ -1074,8 +1027,8 @@ xfs_dir2_leafn_rebalance( ASSERT(hdr1.stale + hdr2.stale == oldstale); /* log the changes made when moving the entries */ - xfs_dir3_leaf_hdr_to_disk(leaf1, &hdr1); - xfs_dir3_leaf_hdr_to_disk(leaf2, &hdr2); + dp->d_ops->leaf_hdr_to_disk(leaf1, &hdr1); + dp->d_ops->leaf_hdr_to_disk(leaf2, &hdr2); xfs_dir3_leaf_log_header(args->trans, dp, blk1->bp); xfs_dir3_leaf_log_header(args->trans, dp, blk2->bp); @@ -1124,8 +1077,9 @@ xfs_dir3_data_block_free( int logfree = 0; __be16 *bests; struct xfs_dir3_icfree_hdr freehdr; + struct xfs_inode *dp = args->dp; - xfs_dir3_free_hdr_from_disk(&freehdr, free); + dp->d_ops->free_hdr_from_disk(&freehdr, free); bests = xfs_dir3_free_bests_p(tp->t_mountp, free); if (hdr) { @@ -1161,7 +1115,7 @@ xfs_dir3_data_block_free( logfree = 1; } - xfs_dir3_free_hdr_to_disk(free, &freehdr); + dp->d_ops->free_hdr_to_disk(free, &freehdr); xfs_dir2_free_log_header(tp, fbp); /* @@ -1226,7 +1180,7 @@ xfs_dir2_leafn_remove( tp = args->trans; mp = dp->i_mount; leaf = bp->b_addr; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); /* @@ -1247,7 +1201,7 @@ xfs_dir2_leafn_remove( * Log the leaf block changes. */ leafhdr.stale++; - xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); + dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); xfs_dir3_leaf_log_header(tp, dp, bp); lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); @@ -1298,7 +1252,7 @@ xfs_dir2_leafn_remove( #ifdef DEBUG { struct xfs_dir3_icfree_hdr freehdr; - xfs_dir3_free_hdr_from_disk(&freehdr, free); + dp->d_ops->free_hdr_from_disk(&freehdr, free); ASSERT(freehdr.firstdb == xfs_dir3_free_max_bests(mp) * (fdb - XFS_DIR2_FREE_FIRSTDB(mp))); } @@ -1449,7 +1403,7 @@ xfs_dir2_leafn_toosmall( */ blk = &state->path.blk[state->path.active - 1]; leaf = blk->bp->b_addr; - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); + dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, blk->bp); @@ -1511,7 +1465,7 @@ xfs_dir2_leafn_toosmall( bytes = state->blocksize - (state->blocksize >> 2); leaf = bp->b_addr; - xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf); + dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf); ents = dp->d_ops->leaf_ents_p(leaf); count += hdr2.count - hdr2.stale; bytes -= count * sizeof(ents[0]); @@ -1574,10 +1528,10 @@ xfs_dir2_leafn_unbalance( drop_leaf = drop_blk->bp->b_addr; save_leaf = save_blk->bp->b_addr; - xfs_dir3_leaf_hdr_from_disk(&savehdr, save_leaf); - xfs_dir3_leaf_hdr_from_disk(&drophdr, drop_leaf); - sents = args->dp->d_ops->leaf_ents_p(save_leaf); - dents = args->dp->d_ops->leaf_ents_p(drop_leaf); + dp->d_ops->leaf_hdr_from_disk(&savehdr, save_leaf); + dp->d_ops->leaf_hdr_from_disk(&drophdr, drop_leaf); + sents = dp->d_ops->leaf_ents_p(save_leaf); + dents = dp->d_ops->leaf_ents_p(drop_leaf); /* * If there are any stale leaf entries, take this opportunity @@ -1603,8 +1557,8 @@ xfs_dir2_leafn_unbalance( save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval); /* log the changes made when moving the entries */ - xfs_dir3_leaf_hdr_to_disk(save_leaf, &savehdr); - xfs_dir3_leaf_hdr_to_disk(drop_leaf, &drophdr); + dp->d_ops->leaf_hdr_to_disk(save_leaf, &savehdr); + dp->d_ops->leaf_hdr_to_disk(drop_leaf, &drophdr); xfs_dir3_leaf_log_header(args->trans, dp, save_blk->bp); xfs_dir3_leaf_log_header(args->trans, dp, drop_blk->bp); @@ -1735,7 +1689,7 @@ xfs_dir2_node_addname_int( free = fbp->b_addr; findex = fblk->index; bests = xfs_dir3_free_bests_p(mp, free); - xfs_dir3_free_hdr_from_disk(&freehdr, free); + dp->d_ops->free_hdr_from_disk(&freehdr, free); /* * This means the free entry showed that the data block had @@ -1828,7 +1782,7 @@ xfs_dir2_node_addname_int( * there, so we have to do it here to avoid warnings. Blech. */ bests = xfs_dir3_free_bests_p(mp, free); - xfs_dir3_free_hdr_from_disk(&freehdr, free); + dp->d_ops->free_hdr_from_disk(&freehdr, free); if (be16_to_cpu(bests[findex]) != NULLDATAOFF && be16_to_cpu(bests[findex]) >= length) dbno = freehdr.firstdb + findex; @@ -1927,7 +1881,7 @@ xfs_dir2_node_addname_int( return error; free = fbp->b_addr; bests = xfs_dir3_free_bests_p(mp, free); - xfs_dir3_free_hdr_from_disk(&freehdr, free); + dp->d_ops->free_hdr_from_disk(&freehdr, free); /* * Remember the first slot as our empty slot. @@ -1937,7 +1891,7 @@ xfs_dir2_node_addname_int( } else { free = fbp->b_addr; bests = xfs_dir3_free_bests_p(mp, free); - xfs_dir3_free_hdr_from_disk(&freehdr, free); + dp->d_ops->free_hdr_from_disk(&freehdr, free); } /* @@ -1962,7 +1916,7 @@ xfs_dir2_node_addname_int( */ if (bests[findex] == cpu_to_be16(NULLDATAOFF)) { freehdr.nused++; - xfs_dir3_free_hdr_to_disk(fbp->b_addr, &freehdr); + dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); xfs_dir2_free_log_header(tp, fbp); } /* @@ -2294,7 +2248,7 @@ xfs_dir2_node_trim_free( if (!bp) return 0; free = bp->b_addr; - xfs_dir3_free_hdr_from_disk(&freehdr, free); + dp->d_ops->free_hdr_from_disk(&freehdr, free); /* * If there are used entries, there's nothing to do. diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h index 3e4b5ba7b41f..8b9d2281f85b 100644 --- a/fs/xfs/xfs_dir2_priv.h +++ b/fs/xfs/xfs_dir2_priv.h @@ -94,10 +94,6 @@ xfs_dir3_leaf_find_entry(struct xfs_dir3_icleaf_hdr *leafhdr, int lowstale, int highstale, int *lfloglow, int *lfloghigh); extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state); -extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to, - struct xfs_dir2_leaf *from); -extern void xfs_dir3_leaf_hdr_to_disk(struct xfs_dir2_leaf *to, - struct xfs_dir3_icleaf_hdr *from); extern bool xfs_dir3_leaf_check_int(struct xfs_mount *mp, struct xfs_inode *dp, struct xfs_dir3_icleaf_hdr *hdr, struct xfs_dir2_leaf *leaf); -- cgit v1.2.3 From 24dd0f546c366da68f33bbf2ecef2306f8c2281d Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 30 Oct 2013 13:48:41 -0500 Subject: xfs: convert directory vector functions to constants Next step in the vectorisation process is the directory free block encode/decode operations. There are relatively few of these, though there are quite a number of calls to them. Binary sizes: text data bss dec hex filename 794490 96802 1096 892388 d9de4 fs/xfs/xfs.o.orig 792986 96802 1096 890884 d9804 fs/xfs/xfs.o.p1 792350 96802 1096 890248 d9588 fs/xfs/xfs.o.p2 789293 96802 1096 887191 d8997 fs/xfs/xfs.o.p3 789005 96802 1096 886903 d8997 fs/xfs/xfs.o.p4 789061 96802 1096 886959 d88af fs/xfs/xfs.o.p5 789733 96802 1096 887631 d8b4f fs/xfs/xfs.o.p6 791421 96802 1096 889319 d91e7 fs/xfs/xfs.o.p7 791701 96802 1096 889599 d92ff fs/xfs/xfs.o.p8 Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_da_format.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_da_format.h | 39 ---------------------- fs/xfs/xfs_dir2.h | 5 +++ fs/xfs/xfs_dir2_leaf.c | 2 +- fs/xfs/xfs_dir2_node.c | 61 +++++++++++++++++----------------- 5 files changed, 126 insertions(+), 70 deletions(-) diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index b232c275791d..01e6f9a9b804 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c @@ -629,6 +629,80 @@ xfs_da3_node_hdr_to_disk( /* * Directory free space block operations */ +static int +xfs_dir2_free_hdr_size(void) +{ + return sizeof(struct xfs_dir2_free_hdr); +} + +static int +xfs_dir2_free_max_bests(struct xfs_mount *mp) +{ + return (mp->m_dirblksize - xfs_dir2_free_hdr_size()) / + sizeof(xfs_dir2_data_off_t); +} + +static __be16 * +xfs_dir2_free_bests_p(struct xfs_dir2_free *free) +{ + return (__be16 *)((char *)free + xfs_dir2_free_hdr_size()); +} + +/* + * Convert data space db to the corresponding free db. + */ +static xfs_dir2_db_t +xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db) +{ + return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir2_free_max_bests(mp); +} + +/* + * Convert data space db to the corresponding index in a free db. + */ +static int +xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) +{ + return db % xfs_dir2_free_max_bests(mp); +} + +static int +xfs_dir3_free_hdr_size(void) +{ + return sizeof(struct xfs_dir3_free_hdr); +} + +static int +xfs_dir3_free_max_bests(struct xfs_mount *mp) +{ + return (mp->m_dirblksize - xfs_dir3_free_hdr_size()) / + sizeof(xfs_dir2_data_off_t); +} + +static __be16 * +xfs_dir3_free_bests_p(struct xfs_dir2_free *free) +{ + return (__be16 *)((char *)free + xfs_dir3_free_hdr_size()); +} + +/* + * Convert data space db to the corresponding free db. + */ +static xfs_dir2_db_t +xfs_dir3_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db) +{ + return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp); +} + +/* + * Convert data space db to the corresponding index in a free db. + */ +static int +xfs_dir3_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) +{ + return db % xfs_dir3_free_max_bests(mp); +} + static void xfs_dir2_free_hdr_from_disk( struct xfs_dir3_icfree_hdr *to, @@ -722,8 +796,13 @@ const struct xfs_dir_ops xfs_dir2_ops = { .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, + .free_hdr_size = xfs_dir2_free_hdr_size, .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk, .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk, + .free_max_bests = xfs_dir2_free_max_bests, + .free_bests_p = xfs_dir2_free_bests_p, + .db_to_fdb = xfs_dir2_db_to_fdb, + .db_to_fdindex = xfs_dir2_db_to_fdindex, }; const struct xfs_dir_ops xfs_dir2_ftype_ops = { @@ -764,8 +843,13 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = { .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, + .free_hdr_size = xfs_dir2_free_hdr_size, .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk, .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk, + .free_max_bests = xfs_dir2_free_max_bests, + .free_bests_p = xfs_dir2_free_bests_p, + .db_to_fdb = xfs_dir2_db_to_fdb, + .db_to_fdindex = xfs_dir2_db_to_fdindex, }; const struct xfs_dir_ops xfs_dir3_ops = { @@ -806,8 +890,13 @@ const struct xfs_dir_ops xfs_dir3_ops = { .node_hdr_from_disk = xfs_da3_node_hdr_from_disk, .node_tree_p = xfs_da3_node_tree_p, + .free_hdr_size = xfs_dir3_free_hdr_size, .free_hdr_to_disk = xfs_dir3_free_hdr_to_disk, .free_hdr_from_disk = xfs_dir3_free_hdr_from_disk, + .free_max_bests = xfs_dir3_free_max_bests, + .free_bests_p = xfs_dir3_free_bests_p, + .db_to_fdb = xfs_dir3_db_to_fdb, + .db_to_fdindex = xfs_dir3_db_to_fdindex, }; const struct xfs_dir_ops xfs_dir2_nondir_ops = { diff --git a/fs/xfs/xfs_da_format.h b/fs/xfs/xfs_da_format.h index 1ff7b9f42097..a19d3f8f639c 100644 --- a/fs/xfs/xfs_da_format.h +++ b/fs/xfs/xfs_da_format.h @@ -704,45 +704,6 @@ struct xfs_dir3_icfree_hdr { }; -static inline int -xfs_dir3_free_hdr_size(struct xfs_mount *mp) -{ - if (xfs_sb_version_hascrc(&mp->m_sb)) - return sizeof(struct xfs_dir3_free_hdr); - return sizeof(struct xfs_dir2_free_hdr); -} - -static inline int -xfs_dir3_free_max_bests(struct xfs_mount *mp) -{ - return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) / - sizeof(xfs_dir2_data_off_t); -} - -static inline __be16 * -xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free) -{ - return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp)); -} - -/* - * Convert data space db to the corresponding free db. - */ -static inline xfs_dir2_db_t -xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db) -{ - return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp); -} - -/* - * Convert data space db to the corresponding index in a free db. - */ -static inline int -xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) -{ - return db % xfs_dir3_free_max_bests(mp); -} - /* * Single block format. * diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 61195348f667..4264cb9199f8 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -92,10 +92,15 @@ struct xfs_dir_ops { struct xfs_da_node_entry * (*node_tree_p)(struct xfs_da_intnode *dap); + int (*free_hdr_size)(void); void (*free_hdr_to_disk)(struct xfs_dir2_free *to, struct xfs_dir3_icfree_hdr *from); void (*free_hdr_from_disk)(struct xfs_dir3_icfree_hdr *to, struct xfs_dir2_free *from); + int (*free_max_bests)(struct xfs_mount *mp); + __be16 * (*free_bests_p)(struct xfs_dir2_free *free); + xfs_dir2_db_t (*db_to_fdb)(struct xfs_mount *mp, xfs_dir2_db_t db); + int (*db_to_fdindex)(struct xfs_mount *mp, xfs_dir2_db_t db); }; extern const struct xfs_dir_ops * diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 2fb8db9fb574..a3c21b15cf7b 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -1785,7 +1785,7 @@ xfs_dir2_node_to_leaf( /* * Set up the leaf bests table. */ - memcpy(xfs_dir2_leaf_bests_p(ltp), xfs_dir3_free_bests_p(mp, free), + memcpy(xfs_dir2_leaf_bests_p(ltp), dp->d_ops->free_bests_p(free), freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index eaee8c36bcc4..853798519ae9 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -240,6 +240,7 @@ xfs_dir3_free_get_buf( STATIC void xfs_dir2_free_log_bests( struct xfs_trans *tp, + struct xfs_inode *dp, struct xfs_buf *bp, int first, /* first entry to log */ int last) /* last entry to log */ @@ -248,7 +249,7 @@ xfs_dir2_free_log_bests( __be16 *bests; free = bp->b_addr; - bests = xfs_dir3_free_bests_p(tp->t_mountp, free); + bests = dp->d_ops->free_bests_p(free); ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); xfs_trans_log_buf(tp, bp, @@ -263,6 +264,7 @@ xfs_dir2_free_log_bests( static void xfs_dir2_free_log_header( struct xfs_trans *tp, + struct xfs_inode *dp, struct xfs_buf *bp) { #ifdef DEBUG @@ -272,7 +274,7 @@ xfs_dir2_free_log_header( ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); #endif - xfs_trans_log_buf(tp, bp, 0, xfs_dir3_free_hdr_size(tp->t_mountp) - 1); + xfs_trans_log_buf(tp, bp, 0, dp->d_ops->free_hdr_size() - 1); } /* @@ -332,7 +334,7 @@ xfs_dir2_leaf_to_node( * Count active entries. */ from = xfs_dir2_leaf_bests_p(ltp); - to = xfs_dir3_free_bests_p(mp, free); + to = dp->d_ops->free_bests_p(free); for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) { if ((off = be16_to_cpu(*from)) != NULLDATAOFF) n++; @@ -346,8 +348,8 @@ xfs_dir2_leaf_to_node( freehdr.nvalid = be32_to_cpu(ltp->bestcount); dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); - xfs_dir2_free_log_bests(tp, fbp, 0, freehdr.nvalid - 1); - xfs_dir2_free_log_header(tp, fbp); + xfs_dir2_free_log_bests(tp, dp, fbp, 0, freehdr.nvalid - 1); + xfs_dir2_free_log_header(tp, dp, fbp); /* * Converting the leaf to a leafnode is just a matter of changing the @@ -468,7 +470,7 @@ xfs_dir2_free_hdr_check( dp->d_ops->free_hdr_from_disk(&hdr, bp->b_addr); - ASSERT((hdr.firstdb % xfs_dir3_free_max_bests(dp->i_mount)) == 0); + ASSERT((hdr.firstdb % dp->d_ops->free_max_bests(dp->i_mount)) == 0); ASSERT(hdr.firstdb <= db); ASSERT(db < hdr.firstdb + hdr.nvalid); } @@ -590,7 +592,7 @@ xfs_dir2_leafn_lookup_for_addname( * Convert the data block to the free block * holding its freespace information. */ - newfdb = xfs_dir2_db_to_fdb(mp, newdb); + newfdb = dp->d_ops->db_to_fdb(mp, newdb); /* * If it's not the one we have in hand, read it in. */ @@ -613,11 +615,11 @@ xfs_dir2_leafn_lookup_for_addname( /* * Get the index for our entry. */ - fi = xfs_dir2_db_to_fdindex(mp, curdb); + fi = dp->d_ops->db_to_fdindex(mp, curdb); /* * If it has room, return it. */ - bests = xfs_dir3_free_bests_p(mp, free); + bests = dp->d_ops->free_bests_p(free); if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) { XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", XFS_ERRLEVEL_LOW, mp); @@ -1080,15 +1082,14 @@ xfs_dir3_data_block_free( struct xfs_inode *dp = args->dp; dp->d_ops->free_hdr_from_disk(&freehdr, free); - - bests = xfs_dir3_free_bests_p(tp->t_mountp, free); + bests = dp->d_ops->free_bests_p(free); if (hdr) { /* * Data block is not empty, just set the free entry to the new * value. */ bests[findex] = cpu_to_be16(longest); - xfs_dir2_free_log_bests(tp, fbp, findex, findex); + xfs_dir2_free_log_bests(tp, dp, fbp, findex, findex); return 0; } @@ -1116,7 +1117,7 @@ xfs_dir3_data_block_free( } dp->d_ops->free_hdr_to_disk(free, &freehdr); - xfs_dir2_free_log_header(tp, fbp); + xfs_dir2_free_log_header(tp, dp, fbp); /* * If there are no useful entries left in the block, get rid of the @@ -1140,7 +1141,7 @@ xfs_dir3_data_block_free( /* Log the free entry that changed, unless we got rid of it. */ if (logfree) - xfs_dir2_free_log_bests(tp, fbp, findex, findex); + xfs_dir2_free_log_bests(tp, dp, fbp, findex, findex); return 0; } @@ -1243,7 +1244,7 @@ xfs_dir2_leafn_remove( * Convert the data block number to a free block, * read in the free block. */ - fdb = xfs_dir2_db_to_fdb(mp, db); + fdb = dp->d_ops->db_to_fdb(mp, db); error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(mp, fdb), &fbp); if (error) @@ -1253,14 +1254,14 @@ xfs_dir2_leafn_remove( { struct xfs_dir3_icfree_hdr freehdr; dp->d_ops->free_hdr_from_disk(&freehdr, free); - ASSERT(freehdr.firstdb == xfs_dir3_free_max_bests(mp) * + ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(mp) * (fdb - XFS_DIR2_FREE_FIRSTDB(mp))); } #endif /* * Calculate which entry we need to fix. */ - findex = xfs_dir2_db_to_fdindex(mp, db); + findex = dp->d_ops->db_to_fdindex(mp, db); longest = be16_to_cpu(bf[0].length); /* * If the data block is now empty we can get rid of it @@ -1688,7 +1689,7 @@ xfs_dir2_node_addname_int( ifbno = fblk->blkno; free = fbp->b_addr; findex = fblk->index; - bests = xfs_dir3_free_bests_p(mp, free); + bests = dp->d_ops->free_bests_p(free); dp->d_ops->free_hdr_from_disk(&freehdr, free); /* @@ -1781,7 +1782,7 @@ xfs_dir2_node_addname_int( * and the freehdr are actually initialised if they are placed * there, so we have to do it here to avoid warnings. Blech. */ - bests = xfs_dir3_free_bests_p(mp, free); + bests = dp->d_ops->free_bests_p(free); dp->d_ops->free_hdr_from_disk(&freehdr, free); if (be16_to_cpu(bests[findex]) != NULLDATAOFF && be16_to_cpu(bests[findex]) >= length) @@ -1833,7 +1834,7 @@ xfs_dir2_node_addname_int( * Get the freespace block corresponding to the data block * that was just allocated. */ - fbno = xfs_dir2_db_to_fdb(mp, dbno); + fbno = dp->d_ops->db_to_fdb(mp, dbno); error = xfs_dir2_free_try_read(tp, dp, xfs_dir2_db_to_da(mp, fbno), &fbp); @@ -1850,12 +1851,12 @@ xfs_dir2_node_addname_int( if (error) return error; - if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) { + if (unlikely(dp->d_ops->db_to_fdb(mp, dbno) != fbno)) { xfs_alert(mp, "%s: dir ino %llu needed freesp block %lld for\n" " data block %lld, got %lld ifbno %llu lastfbno %d", __func__, (unsigned long long)dp->i_ino, - (long long)xfs_dir2_db_to_fdb(mp, dbno), + (long long)dp->d_ops->db_to_fdb(mp, dbno), (long long)dbno, (long long)fbno, (unsigned long long)ifbno, lastfbno); if (fblk) { @@ -1880,30 +1881,30 @@ xfs_dir2_node_addname_int( if (error) return error; free = fbp->b_addr; - bests = xfs_dir3_free_bests_p(mp, free); + bests = dp->d_ops->free_bests_p(free); dp->d_ops->free_hdr_from_disk(&freehdr, free); /* * Remember the first slot as our empty slot. */ freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * - xfs_dir3_free_max_bests(mp); + dp->d_ops->free_max_bests(mp); } else { free = fbp->b_addr; - bests = xfs_dir3_free_bests_p(mp, free); + bests = dp->d_ops->free_bests_p(free); dp->d_ops->free_hdr_from_disk(&freehdr, free); } /* * Set the freespace block index from the data block number. */ - findex = xfs_dir2_db_to_fdindex(mp, dbno); + findex = dp->d_ops->db_to_fdindex(mp, dbno); /* * If it's after the end of the current entries in the * freespace block, extend that table. */ if (findex >= freehdr.nvalid) { - ASSERT(findex < xfs_dir3_free_max_bests(mp)); + ASSERT(findex < dp->d_ops->free_max_bests(mp)); freehdr.nvalid = findex + 1; /* * Tag new entry so nused will go up. @@ -1917,7 +1918,7 @@ xfs_dir2_node_addname_int( if (bests[findex] == cpu_to_be16(NULLDATAOFF)) { freehdr.nused++; dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); - xfs_dir2_free_log_header(tp, fbp); + xfs_dir2_free_log_header(tp, dp, fbp); } /* * Update the real value in the table. @@ -1987,7 +1988,7 @@ xfs_dir2_node_addname_int( /* * If the freespace entry is now wrong, update it. */ - bests = xfs_dir3_free_bests_p(mp, free); /* gcc is so stupid */ + bests = dp->d_ops->free_bests_p(free); /* gcc is so stupid */ if (be16_to_cpu(bests[findex]) != be16_to_cpu(bf[0].length)) { bests[findex] = bf[0].length; logfree = 1; @@ -1996,7 +1997,7 @@ xfs_dir2_node_addname_int( * Log the freespace entry if needed. */ if (logfree) - xfs_dir2_free_log_bests(tp, fbp, findex, findex); + xfs_dir2_free_log_bests(tp, dp, fbp, findex, findex); /* * Return the data block and offset in args, then drop the data block. */ -- cgit v1.2.3 From 1c9a5b2e3045b91a10335adcc73267c304cb5dc0 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 30 Oct 2013 09:15:02 +1100 Subject: xfs: convert directory vector functions to constants Many of the vectorised function calls now take no parameters and return a constant value. There is no reason for these to be vectored functions, so convert them to constants Binary sizes: text data bss dec hex filename 794490 96802 1096 892388 d9de4 fs/xfs/xfs.o.orig 792986 96802 1096 890884 d9804 fs/xfs/xfs.o.p1 792350 96802 1096 890248 d9588 fs/xfs/xfs.o.p2 789293 96802 1096 887191 d8997 fs/xfs/xfs.o.p3 789005 96802 1096 886903 d8997 fs/xfs/xfs.o.p4 789061 96802 1096 886959 d88af fs/xfs/xfs.o.p5 789733 96802 1096 887631 d8b4f fs/xfs/xfs.o.p6 791421 96802 1096 889319 d91e7 fs/xfs/xfs.o.p7 791701 96802 1096 889599 d92ff fs/xfs/xfs.o.p8 791205 96802 1096 889103 d91cf fs/xfs/xfs.o.p9 Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_da_btree.c | 14 ++- fs/xfs/xfs_da_format.c | 220 +++++++++++++++++----------------------------- fs/xfs/xfs_dir2.c | 2 +- fs/xfs/xfs_dir2.h | 14 +-- fs/xfs/xfs_dir2_block.c | 4 +- fs/xfs/xfs_dir2_data.c | 8 +- fs/xfs/xfs_dir2_leaf.c | 6 +- fs/xfs/xfs_dir2_node.c | 8 +- fs/xfs/xfs_dir2_readdir.c | 6 +- fs/xfs/xfs_dir2_sf.c | 6 +- 10 files changed, 112 insertions(+), 176 deletions(-) diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index a51762dae543..796272a2e129 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -333,8 +333,7 @@ xfs_da3_node_create( dp->d_ops->node_hdr_to_disk(node, &ichdr); xfs_trans_log_buf(tp, bp, - XFS_DA_LOGRANGE(node, &node->hdr, - dp->d_ops->node_hdr_size())); + XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size)); *bpp = bp; return(0); @@ -838,13 +837,12 @@ xfs_da3_node_rebalance( */ dp->d_ops->node_hdr_to_disk(node1, &nodehdr1); xfs_trans_log_buf(tp, blk1->bp, - XFS_DA_LOGRANGE(node1, &node1->hdr, - dp->d_ops->node_hdr_size())); + XFS_DA_LOGRANGE(node1, &node1->hdr, dp->d_ops->node_hdr_size)); dp->d_ops->node_hdr_to_disk(node2, &nodehdr2); xfs_trans_log_buf(tp, blk2->bp, XFS_DA_LOGRANGE(node2, &node2->hdr, - dp->d_ops->node_hdr_size() + + dp->d_ops->node_hdr_size + (sizeof(btree2[0]) * nodehdr2.count))); /* @@ -915,7 +913,7 @@ xfs_da3_node_add( nodehdr.count += 1; dp->d_ops->node_hdr_to_disk(node, &nodehdr); xfs_trans_log_buf(state->args->trans, oldblk->bp, - XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size())); + XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size)); /* * Copy the last hash value from the oldblk to propagate upwards. @@ -1350,7 +1348,7 @@ xfs_da3_node_remove( nodehdr.count -= 1; dp->d_ops->node_hdr_to_disk(node, &nodehdr); xfs_trans_log_buf(state->args->trans, drop_blk->bp, - XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size())); + XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size)); /* * Copy the last hash value from the block to propagate upwards. @@ -1423,7 +1421,7 @@ xfs_da3_node_unbalance( dp->d_ops->node_hdr_to_disk(save_node, &save_hdr); xfs_trans_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, &save_node->hdr, - dp->d_ops->node_hdr_size())); + dp->d_ops->node_hdr_size)); /* * Save the last hashval in the remaining block for upward propagation. diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index 01e6f9a9b804..40f18d3b7b9b 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c @@ -209,31 +209,41 @@ xfs_dir3_sfe_put_ino( /* * Directory data block operations */ -static int -__xfs_dir3_data_entsize( - bool ftype, - int n) -{ - int size = offsetof(struct xfs_dir2_data_entry, name[0]); - size += n; - size += sizeof(xfs_dir2_data_off_t); - if (ftype) - size += sizeof(__uint8_t); - return roundup(size, XFS_DIR2_DATA_ALIGN); -} +/* + * For special situations, the dirent size ends up fixed because we always know + * what the size of the entry is. That's true for the "." and "..", and + * therefore we know that they are a fixed size and hence their offsets are + * constant, as is the first entry. + * + * Hence, this calculation is written as a macro to be able to be calculated at + * compile time and so certain offsets can be calculated directly in the + * structure initaliser via the macro. There are two macros - one for dirents + * with ftype and without so there are no unresolvable conditionals in the + * calculations. We also use round_up() as XFS_DIR2_DATA_ALIGN is always a power + * of 2 and the compiler doesn't reject it (unlike roundup()). + */ +#define XFS_DIR2_DATA_ENTSIZE(n) \ + round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \ + sizeof(xfs_dir2_data_off_t)), XFS_DIR2_DATA_ALIGN) + +#define XFS_DIR3_DATA_ENTSIZE(n) \ + round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \ + sizeof(xfs_dir2_data_off_t) + sizeof(__uint8_t)), \ + XFS_DIR2_DATA_ALIGN) static int xfs_dir2_data_entsize( int n) { - return __xfs_dir3_data_entsize(false, n); + return XFS_DIR2_DATA_ENTSIZE(n); } + static int xfs_dir3_data_entsize( int n) { - return __xfs_dir3_data_entsize(true, n); + return XFS_DIR3_DATA_ENTSIZE(n); } static __uint8_t @@ -293,45 +303,6 @@ xfs_dir3_data_entry_tag_p( xfs_dir3_data_entsize(dep->namelen) - sizeof(__be16)); } -/* - * Offsets of . and .. in data space (always block 0) - */ -static xfs_dir2_data_aoff_t -xfs_dir2_data_dot_offset(void) -{ - return sizeof(struct xfs_dir2_data_hdr); -} - -static xfs_dir2_data_aoff_t -xfs_dir2_data_dotdot_offset(void) -{ - return xfs_dir2_data_dot_offset() + xfs_dir2_data_entsize(1); -} - -static xfs_dir2_data_aoff_t -xfs_dir2_data_first_offset(void) -{ - return xfs_dir2_data_dotdot_offset() + xfs_dir2_data_entsize(2); -} - -static xfs_dir2_data_aoff_t -xfs_dir3_data_dot_offset(void) -{ - return sizeof(struct xfs_dir3_data_hdr); -} - -static xfs_dir2_data_aoff_t -xfs_dir3_data_dotdot_offset(void) -{ - return xfs_dir3_data_dot_offset() + xfs_dir3_data_entsize(1); -} - -static xfs_dir2_data_aoff_t -xfs_dir3_data_first_offset(void) -{ - return xfs_dir3_data_dotdot_offset() + xfs_dir3_data_entsize(2); -} - /* * location of . and .. in data space (always block 0) */ @@ -340,7 +311,7 @@ xfs_dir2_data_dot_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir2_data_dot_offset()); + ((char *)hdr + sizeof(struct xfs_dir2_data_hdr)); } static struct xfs_dir2_data_entry * @@ -348,7 +319,8 @@ xfs_dir2_data_dotdot_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir2_data_dotdot_offset()); + ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) + + XFS_DIR2_DATA_ENTSIZE(1)); } static struct xfs_dir2_data_entry * @@ -356,7 +328,9 @@ xfs_dir2_data_first_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir2_data_first_offset()); + ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) + + XFS_DIR2_DATA_ENTSIZE(1) + + XFS_DIR2_DATA_ENTSIZE(2)); } static struct xfs_dir2_data_entry * @@ -364,7 +338,7 @@ xfs_dir3_data_dot_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_dot_offset()); + ((char *)hdr + sizeof(struct xfs_dir3_data_hdr)); } static struct xfs_dir2_data_entry * @@ -372,7 +346,8 @@ xfs_dir3_data_dotdot_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_dotdot_offset()); + ((char *)hdr + sizeof(struct xfs_dir3_data_hdr) + + XFS_DIR3_DATA_ENTSIZE(1)); } static struct xfs_dir2_data_entry * @@ -380,7 +355,9 @@ xfs_dir3_data_first_entry_p( struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_first_offset()); + ((char *)hdr + sizeof(struct xfs_dir3_data_hdr) + + XFS_DIR3_DATA_ENTSIZE(1) + + XFS_DIR3_DATA_ENTSIZE(2)); } static struct xfs_dir2_data_free * @@ -395,60 +372,42 @@ xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) return ((struct xfs_dir3_data_hdr *)hdr)->best_free; } -static size_t -xfs_dir2_data_entry_offset(void) -{ - return sizeof(struct xfs_dir2_data_hdr); -} - static struct xfs_dir2_data_entry * xfs_dir2_data_entry_p(struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir2_data_entry_offset()); + ((char *)hdr + sizeof(struct xfs_dir2_data_hdr)); } static struct xfs_dir2_data_unused * xfs_dir2_data_unused_p(struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_unused *) - ((char *)hdr + xfs_dir2_data_entry_offset()); -} - -static size_t -xfs_dir3_data_entry_offset(void) -{ - return sizeof(struct xfs_dir3_data_hdr); + ((char *)hdr + sizeof(struct xfs_dir2_data_hdr)); } static struct xfs_dir2_data_entry * xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_entry *) - ((char *)hdr + xfs_dir3_data_entry_offset()); + ((char *)hdr + sizeof(struct xfs_dir3_data_hdr)); } static struct xfs_dir2_data_unused * xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) { return (struct xfs_dir2_data_unused *) - ((char *)hdr + xfs_dir3_data_entry_offset()); + ((char *)hdr + sizeof(struct xfs_dir3_data_hdr)); } /* * Directory Leaf block operations */ -static int -xfs_dir2_leaf_hdr_size(void) -{ - return sizeof(struct xfs_dir2_leaf_hdr); -} - static int xfs_dir2_max_leaf_ents(struct xfs_mount *mp) { - return (mp->m_dirblksize - xfs_dir2_leaf_hdr_size()) / + return (mp->m_dirblksize - sizeof(struct xfs_dir2_leaf_hdr)) / (uint)sizeof(struct xfs_dir2_leaf_entry); } @@ -458,16 +417,10 @@ xfs_dir2_leaf_ents_p(struct xfs_dir2_leaf *lp) return lp->__ents; } -static int -xfs_dir3_leaf_hdr_size(void) -{ - return sizeof(struct xfs_dir3_leaf_hdr); -} - static int xfs_dir3_max_leaf_ents(struct xfs_mount *mp) { - return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size()) / + return (mp->m_dirblksize - sizeof(struct xfs_dir3_leaf_hdr)) / (uint)sizeof(struct xfs_dir2_leaf_entry); } @@ -545,25 +498,13 @@ xfs_dir3_leaf_hdr_to_disk( /* * Directory/Attribute Node block operations */ -static inline int -xfs_da2_node_hdr_size(void) -{ - return sizeof(struct xfs_da_node_hdr); -} - static struct xfs_da_node_entry * xfs_da2_node_tree_p(struct xfs_da_intnode *dap) { return dap->__btree; } -static inline int -xfs_da3_node_hdr_size(void) -{ - return sizeof(struct xfs_da3_node_hdr); -} - -static inline struct xfs_da_node_entry * +static struct xfs_da_node_entry * xfs_da3_node_tree_p(struct xfs_da_intnode *dap) { return ((struct xfs_da3_intnode *)dap)->__btree; @@ -629,23 +570,17 @@ xfs_da3_node_hdr_to_disk( /* * Directory free space block operations */ -static int -xfs_dir2_free_hdr_size(void) -{ - return sizeof(struct xfs_dir2_free_hdr); -} - static int xfs_dir2_free_max_bests(struct xfs_mount *mp) { - return (mp->m_dirblksize - xfs_dir2_free_hdr_size()) / + return (mp->m_dirblksize - sizeof(struct xfs_dir2_free_hdr)) / sizeof(xfs_dir2_data_off_t); } static __be16 * xfs_dir2_free_bests_p(struct xfs_dir2_free *free) { - return (__be16 *)((char *)free + xfs_dir2_free_hdr_size()); + return (__be16 *)((char *)free + sizeof(struct xfs_dir2_free_hdr)); } /* @@ -666,23 +601,17 @@ xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) return db % xfs_dir2_free_max_bests(mp); } -static int -xfs_dir3_free_hdr_size(void) -{ - return sizeof(struct xfs_dir3_free_hdr); -} - static int xfs_dir3_free_max_bests(struct xfs_mount *mp) { - return (mp->m_dirblksize - xfs_dir3_free_hdr_size()) / + return (mp->m_dirblksize - sizeof(struct xfs_dir3_free_hdr)) / sizeof(xfs_dir2_data_off_t); } static __be16 * xfs_dir3_free_bests_p(struct xfs_dir2_free *free) { - return (__be16 *)((char *)free + xfs_dir3_free_hdr_size()); + return (__be16 *)((char *)free + sizeof(struct xfs_dir3_free_hdr)); } /* @@ -774,10 +703,13 @@ const struct xfs_dir_ops xfs_dir2_ops = { .data_entry_tag_p = xfs_dir2_data_entry_tag_p, .data_bestfree_p = xfs_dir2_data_bestfree_p, - .data_dot_offset = xfs_dir2_data_dot_offset, - .data_dotdot_offset = xfs_dir2_data_dotdot_offset, - .data_first_offset = xfs_dir2_data_first_offset, - .data_entry_offset = xfs_dir2_data_entry_offset, + .data_dot_offset = sizeof(struct xfs_dir2_data_hdr), + .data_dotdot_offset = sizeof(struct xfs_dir2_data_hdr) + + XFS_DIR2_DATA_ENTSIZE(1), + .data_first_offset = sizeof(struct xfs_dir2_data_hdr) + + XFS_DIR2_DATA_ENTSIZE(1) + + XFS_DIR2_DATA_ENTSIZE(2), + .data_entry_offset = sizeof(struct xfs_dir2_data_hdr), .data_dot_entry_p = xfs_dir2_data_dot_entry_p, .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p, @@ -785,18 +717,18 @@ const struct xfs_dir_ops xfs_dir2_ops = { .data_entry_p = xfs_dir2_data_entry_p, .data_unused_p = xfs_dir2_data_unused_p, - .leaf_hdr_size = xfs_dir2_leaf_hdr_size, + .leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr), .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk, .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk, .leaf_max_ents = xfs_dir2_max_leaf_ents, .leaf_ents_p = xfs_dir2_leaf_ents_p, - .node_hdr_size = xfs_da2_node_hdr_size, + .node_hdr_size = sizeof(struct xfs_da_node_hdr), .node_hdr_to_disk = xfs_da2_node_hdr_to_disk, .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, - .free_hdr_size = xfs_dir2_free_hdr_size, + .free_hdr_size = sizeof(struct xfs_dir2_free_hdr), .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk, .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk, .free_max_bests = xfs_dir2_free_max_bests, @@ -821,10 +753,13 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = { .data_entry_tag_p = xfs_dir3_data_entry_tag_p, .data_bestfree_p = xfs_dir2_data_bestfree_p, - .data_dot_offset = xfs_dir2_data_dot_offset, - .data_dotdot_offset = xfs_dir2_data_dotdot_offset, - .data_first_offset = xfs_dir2_data_first_offset, - .data_entry_offset = xfs_dir2_data_entry_offset, + .data_dot_offset = sizeof(struct xfs_dir2_data_hdr), + .data_dotdot_offset = sizeof(struct xfs_dir2_data_hdr) + + XFS_DIR3_DATA_ENTSIZE(1), + .data_first_offset = sizeof(struct xfs_dir2_data_hdr) + + XFS_DIR3_DATA_ENTSIZE(1) + + XFS_DIR3_DATA_ENTSIZE(2), + .data_entry_offset = sizeof(struct xfs_dir2_data_hdr), .data_dot_entry_p = xfs_dir2_data_dot_entry_p, .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p, @@ -832,18 +767,18 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = { .data_entry_p = xfs_dir2_data_entry_p, .data_unused_p = xfs_dir2_data_unused_p, - .leaf_hdr_size = xfs_dir2_leaf_hdr_size, + .leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr), .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk, .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk, .leaf_max_ents = xfs_dir2_max_leaf_ents, .leaf_ents_p = xfs_dir2_leaf_ents_p, - .node_hdr_size = xfs_da2_node_hdr_size, + .node_hdr_size = sizeof(struct xfs_da_node_hdr), .node_hdr_to_disk = xfs_da2_node_hdr_to_disk, .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, - .free_hdr_size = xfs_dir2_free_hdr_size, + .free_hdr_size = sizeof(struct xfs_dir2_free_hdr), .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk, .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk, .free_max_bests = xfs_dir2_free_max_bests, @@ -868,10 +803,13 @@ const struct xfs_dir_ops xfs_dir3_ops = { .data_entry_tag_p = xfs_dir3_data_entry_tag_p, .data_bestfree_p = xfs_dir3_data_bestfree_p, - .data_dot_offset = xfs_dir3_data_dot_offset, - .data_dotdot_offset = xfs_dir3_data_dotdot_offset, - .data_first_offset = xfs_dir3_data_first_offset, - .data_entry_offset = xfs_dir3_data_entry_offset, + .data_dot_offset = sizeof(struct xfs_dir3_data_hdr), + .data_dotdot_offset = sizeof(struct xfs_dir3_data_hdr) + + XFS_DIR3_DATA_ENTSIZE(1), + .data_first_offset = sizeof(struct xfs_dir3_data_hdr) + + XFS_DIR3_DATA_ENTSIZE(1) + + XFS_DIR3_DATA_ENTSIZE(2), + .data_entry_offset = sizeof(struct xfs_dir3_data_hdr), .data_dot_entry_p = xfs_dir3_data_dot_entry_p, .data_dotdot_entry_p = xfs_dir3_data_dotdot_entry_p, @@ -879,18 +817,18 @@ const struct xfs_dir_ops xfs_dir3_ops = { .data_entry_p = xfs_dir3_data_entry_p, .data_unused_p = xfs_dir3_data_unused_p, - .leaf_hdr_size = xfs_dir3_leaf_hdr_size, + .leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr), .leaf_hdr_to_disk = xfs_dir3_leaf_hdr_to_disk, .leaf_hdr_from_disk = xfs_dir3_leaf_hdr_from_disk, .leaf_max_ents = xfs_dir3_max_leaf_ents, .leaf_ents_p = xfs_dir3_leaf_ents_p, - .node_hdr_size = xfs_da3_node_hdr_size, + .node_hdr_size = sizeof(struct xfs_da3_node_hdr), .node_hdr_to_disk = xfs_da3_node_hdr_to_disk, .node_hdr_from_disk = xfs_da3_node_hdr_from_disk, .node_tree_p = xfs_da3_node_tree_p, - .free_hdr_size = xfs_dir3_free_hdr_size, + .free_hdr_size = sizeof(struct xfs_dir3_free_hdr), .free_hdr_to_disk = xfs_dir3_free_hdr_to_disk, .free_hdr_from_disk = xfs_dir3_free_hdr_from_disk, .free_max_bests = xfs_dir3_free_max_bests, @@ -900,14 +838,14 @@ const struct xfs_dir_ops xfs_dir3_ops = { }; const struct xfs_dir_ops xfs_dir2_nondir_ops = { - .node_hdr_size = xfs_da2_node_hdr_size, + .node_hdr_size = sizeof(struct xfs_da_node_hdr), .node_hdr_to_disk = xfs_da2_node_hdr_to_disk, .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, }; const struct xfs_dir_ops xfs_dir3_nondir_ops = { - .node_hdr_size = xfs_da3_node_hdr_size, + .node_hdr_size = sizeof(struct xfs_da3_node_hdr), .node_hdr_to_disk = xfs_da3_node_hdr_to_disk, .node_hdr_from_disk = xfs_da3_node_hdr_from_disk, .node_tree_p = xfs_da3_node_tree_p, diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 1b44e83924b7..ce16ef02997a 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -105,7 +105,7 @@ xfs_dir_mount( mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp)); mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp)); - nodehdr_size = mp->m_dir_inode_ops->node_hdr_size(); + nodehdr_size = mp->m_dir_inode_ops->node_hdr_size; mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_size) / (uint)sizeof(xfs_da_node_entry_t); mp->m_dir_node_ents = (mp->m_dirblksize - nodehdr_size) / diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 4264cb9199f8..cec70e0781ab 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -59,10 +59,10 @@ struct xfs_dir_ops { struct xfs_dir2_data_free * (*data_bestfree_p)(struct xfs_dir2_data_hdr *hdr); - xfs_dir2_data_aoff_t (*data_dot_offset)(void); - xfs_dir2_data_aoff_t (*data_dotdot_offset)(void); - xfs_dir2_data_aoff_t (*data_first_offset)(void); - size_t (*data_entry_offset)(void); + xfs_dir2_data_aoff_t data_dot_offset; + xfs_dir2_data_aoff_t data_dotdot_offset; + xfs_dir2_data_aoff_t data_first_offset; + size_t data_entry_offset; struct xfs_dir2_data_entry * (*data_dot_entry_p)(struct xfs_dir2_data_hdr *hdr); @@ -75,7 +75,7 @@ struct xfs_dir_ops { struct xfs_dir2_data_unused * (*data_unused_p)(struct xfs_dir2_data_hdr *hdr); - int (*leaf_hdr_size)(void); + int leaf_hdr_size; void (*leaf_hdr_to_disk)(struct xfs_dir2_leaf *to, struct xfs_dir3_icleaf_hdr *from); void (*leaf_hdr_from_disk)(struct xfs_dir3_icleaf_hdr *to, @@ -84,7 +84,7 @@ struct xfs_dir_ops { struct xfs_dir2_leaf_entry * (*leaf_ents_p)(struct xfs_dir2_leaf *lp); - int (*node_hdr_size)(void); + int node_hdr_size; void (*node_hdr_to_disk)(struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from); void (*node_hdr_from_disk)(struct xfs_da3_icnode_hdr *to, @@ -92,7 +92,7 @@ struct xfs_dir_ops { struct xfs_da_node_entry * (*node_tree_p)(struct xfs_da_intnode *dap); - int (*free_hdr_size)(void); + int free_hdr_size; void (*free_hdr_to_disk)(struct xfs_dir2_free *to, struct xfs_dir3_icfree_hdr *from); void (*free_hdr_from_disk)(struct xfs_dir3_icfree_hdr *to, diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index c1ff552aa7bf..90cdbf4b5f19 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -951,7 +951,7 @@ xfs_dir2_leaf_to_block( while (dp->i_d.di_size > mp->m_dirblksize) { int hdrsz; - hdrsz = dp->d_ops->data_entry_offset(); + hdrsz = dp->d_ops->data_entry_offset; bestsp = xfs_dir2_leaf_bests_p(ltp); if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) == mp->m_dirblksize - hdrsz) { @@ -1185,7 +1185,7 @@ xfs_dir2_sf_to_block( blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, (char *)dep - (char *)hdr)); - offset = dp->d_ops->data_first_offset(); + offset = dp->d_ops->data_first_offset; /* * Loop over existing entries, stuff them in. */ diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 32d657fbe6a4..18e920c86be6 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -598,7 +598,7 @@ xfs_dir3_data_init( hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); bf = dp->d_ops->data_bestfree_p(hdr); - bf[0].offset = cpu_to_be16(dp->d_ops->data_entry_offset()); + bf[0].offset = cpu_to_be16(dp->d_ops->data_entry_offset); for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) { bf[i].length = 0; bf[i].offset = 0; @@ -610,7 +610,7 @@ xfs_dir3_data_init( dup = dp->d_ops->data_unused_p(hdr); dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); - t = mp->m_dirblksize - (uint)dp->d_ops->data_entry_offset(); + t = mp->m_dirblksize - (uint)dp->d_ops->data_entry_offset; bf[0].length = cpu_to_be16(t); dup->length = cpu_to_be16(t); *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr); @@ -663,7 +663,7 @@ xfs_dir2_data_log_header( hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); #endif - xfs_trans_log_buf(tp, bp, 0, dp->d_ops->data_entry_offset() - 1); + xfs_trans_log_buf(tp, bp, 0, dp->d_ops->data_entry_offset - 1); } /* @@ -742,7 +742,7 @@ xfs_dir2_data_make_free( * If this isn't the start of the block, then back up to * the previous entry and see if it's free. */ - if (offset > dp->d_ops->data_entry_offset()) { + if (offset > dp->d_ops->data_entry_offset) { __be16 *tagp; /* tag just before us */ tagp = (__be16 *)((char *)hdr + offset) - 1; diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index a3c21b15cf7b..ae47ec6e16c4 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -1116,7 +1116,7 @@ xfs_dir3_leaf_log_header( leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), - dp->d_ops->leaf_hdr_size() - 1); + dp->d_ops->leaf_hdr_size - 1); } /* @@ -1424,7 +1424,7 @@ xfs_dir2_leaf_removename( * If the data block is now empty then get rid of the data block. */ if (be16_to_cpu(bf[0].length) == - mp->m_dirblksize - dp->d_ops->data_entry_offset()) { + mp->m_dirblksize - dp->d_ops->data_entry_offset) { ASSERT(db != mp->m_dirdatablk); if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { /* @@ -1623,7 +1623,7 @@ xfs_dir2_leaf_trim_data( ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); ASSERT(be16_to_cpu(bf[0].length) == - mp->m_dirblksize - dp->d_ops->data_entry_offset()); + mp->m_dirblksize - dp->d_ops->data_entry_offset); ASSERT(db == be32_to_cpu(ltp->bestcount) - 1); } #endif diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 853798519ae9..f90bf0690346 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -274,7 +274,7 @@ xfs_dir2_free_log_header( ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); #endif - xfs_trans_log_buf(tp, bp, 0, dp->d_ops->free_hdr_size() - 1); + xfs_trans_log_buf(tp, bp, 0, dp->d_ops->free_hdr_size - 1); } /* @@ -1268,7 +1268,7 @@ xfs_dir2_leafn_remove( * (usually). */ if (longest == mp->m_dirblksize - - dp->d_ops->data_entry_offset()) { + dp->d_ops->data_entry_offset) { /* * Try to punch out the data block. */ @@ -1300,7 +1300,7 @@ xfs_dir2_leafn_remove( * Return indication of whether this leaf block is empty enough * to justify trying to join it with a neighbor. */ - *rval = (dp->d_ops->leaf_hdr_size() + + *rval = (dp->d_ops->leaf_hdr_size + (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) < mp->m_dir_magicpct; return 0; @@ -1409,7 +1409,7 @@ xfs_dir2_leafn_toosmall( xfs_dir3_leaf_check(dp, blk->bp); count = leafhdr.count - leafhdr.stale; - bytes = dp->d_ops->leaf_hdr_size() + count * sizeof(ents[0]); + bytes = dp->d_ops->leaf_hdr_size + count * sizeof(ents[0]); if (bytes > (state->blocksize >> 1)) { /* * Blk over 50%, don't try to join. diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index f45ecac821ec..c4e50c6ed584 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -119,9 +119,9 @@ xfs_dir2_sf_getdents( * mp->m_dirdatablk. */ dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, - dp->d_ops->data_dot_offset()); + dp->d_ops->data_dot_offset); dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, - dp->d_ops->data_dotdot_offset()); + dp->d_ops->data_dotdot_offset); /* * Put . entry unless we're starting past it. @@ -584,7 +584,7 @@ xfs_dir2_leaf_getdents( * Skip past the header. */ if (byteoff == 0) - curoff += dp->d_ops->data_entry_offset(); + curoff += dp->d_ops->data_entry_offset; /* * Skip past entries until we reach our offset. */ diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 42bbcff15cc5..aafc6e46cb58 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -473,7 +473,7 @@ xfs_dir2_sf_addname_hard( * to insert the new entry. * If it's going to end up at the end then oldsfep will point there. */ - for (offset = dp->d_ops->data_first_offset(), + for (offset = dp->d_ops->data_first_offset, oldsfep = xfs_dir2_sf_firstentry(oldsfp), add_datasize = dp->d_ops->data_entsize(args->namelen), eof = (char *)oldsfep == &buf[old_isize]; @@ -556,7 +556,7 @@ xfs_dir2_sf_addname_pick( sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; size = dp->d_ops->data_entsize(args->namelen); - offset = dp->d_ops->data_first_offset(); + offset = dp->d_ops->data_first_offset; sfep = xfs_dir2_sf_firstentry(sfp); holefit = 0; /* @@ -629,7 +629,7 @@ xfs_dir2_sf_check( mp = dp->i_mount; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; - offset = dp->d_ops->data_first_offset(); + offset = dp->d_ops->data_first_offset; ino = dp->d_ops->sf_get_parent_ino(sfp); i8count = ino > XFS_DIR2_MAX_SHORT_INUM; -- cgit v1.2.3 From b01ef655d8b9753c3d25e4c22e0a4e7c442fe5e1 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:55 +1100 Subject: xfs: make dir2 ftype offset pointers explicit Rather than hiding the ftype field size accounting inside the dirent padding for the ".." and first entry offset functions for v2 directory formats, add explicit functions that calculate it correctly. Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_da_format.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index 40f18d3b7b9b..870cac0b0981 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c @@ -333,6 +333,25 @@ xfs_dir2_data_first_entry_p( XFS_DIR2_DATA_ENTSIZE(2)); } +static struct xfs_dir2_data_entry * +xfs_dir2_ftype_data_dotdot_entry_p( + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) + + XFS_DIR3_DATA_ENTSIZE(1)); +} + +static struct xfs_dir2_data_entry * +xfs_dir2_ftype_data_first_entry_p( + struct xfs_dir2_data_hdr *hdr) +{ + return (struct xfs_dir2_data_entry *) + ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) + + XFS_DIR3_DATA_ENTSIZE(1) + + XFS_DIR3_DATA_ENTSIZE(2)); +} + static struct xfs_dir2_data_entry * xfs_dir3_data_dot_entry_p( struct xfs_dir2_data_hdr *hdr) @@ -762,8 +781,8 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = { .data_entry_offset = sizeof(struct xfs_dir2_data_hdr), .data_dot_entry_p = xfs_dir2_data_dot_entry_p, - .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p, - .data_first_entry_p = xfs_dir2_data_first_entry_p, + .data_dotdot_entry_p = xfs_dir2_ftype_data_dotdot_entry_p, + .data_first_entry_p = xfs_dir2_ftype_data_first_entry_p, .data_entry_p = xfs_dir2_data_entry_p, .data_unused_p = xfs_dir2_data_unused_p, -- cgit v1.2.3 From a62936210525da2f46ae264e0bf9680eafac176e Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:56 +1100 Subject: xfs: validity check the directory block leaf entry count The directory block format verifier fails to check that the leaf entry count is in a valid range, and so if it is corrupted then it can lead to derefencing a pointer outside the block buffer. While we can't exactly validate the count without first walking the directory block, we can ensure the count lands in the valid area within the directory block and hence avoid out-of-block references. Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_dir2_data.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 18e920c86be6..70acff4ee173 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -65,7 +65,6 @@ __xfs_dir3_data_check( const struct xfs_dir_ops *ops; mp = bp->b_target->bt_mount; - hdr = bp->b_addr; /* * We can be passed a null dp here from a verifier, so we need to go the @@ -73,12 +72,25 @@ __xfs_dir3_data_check( */ ops = xfs_dir_get_ops(mp, dp); + hdr = bp->b_addr; + p = (char *)ops->data_entry_p(hdr); + switch (hdr->magic) { case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): btp = xfs_dir2_block_tail_p(mp, hdr); lep = xfs_dir2_block_leaf_p(btp); endp = (char *)lep; + + /* + * The number of leaf entries is limited by the size of the + * block and the amount of space used by the data entries. + * We don't know how much space is used by the data entries yet, + * so just ensure that the count falls somewhere inside the + * block right now. + */ + XFS_WANT_CORRUPTED_RETURN(be32_to_cpu(btp->count) < + ((char *)btp - p) / sizeof(struct xfs_dir2_leaf_entry)); break; case cpu_to_be32(XFS_DIR3_DATA_MAGIC): case cpu_to_be32(XFS_DIR2_DATA_MAGIC): @@ -88,13 +100,12 @@ __xfs_dir3_data_check( XFS_ERROR_REPORT("Bad Magic", XFS_ERRLEVEL_LOW, mp); return EFSCORRUPTED; } - bf = ops->data_bestfree_p(hdr); - p = (char *)ops->data_entry_p(hdr); - count = lastfree = freeseen = 0; /* * Account for zero bestfree entries. */ + bf = ops->data_bestfree_p(hdr); + count = lastfree = freeseen = 0; if (!bf[0].length) { XFS_WANT_CORRUPTED_RETURN(!bf[0].offset); freeseen |= 1 << 0; -- cgit v1.2.3 From 632b89e82bf1c04c251924b49adc689f7b346321 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:58 +1100 Subject: xfs: fix static and extern sparse warnings The kbuild test robot indicated that there were some new sparse warnings in fs/xfs/xfs_dquot_buf.c. Actually, there were a lot more that is wasn't warning about, so fix them all up. Reported-by: kbuild test robot Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_alloc_btree.c | 1 + fs/xfs/xfs_attr_leaf.c | 1 + fs/xfs/xfs_attr_remote.c | 1 + fs/xfs/xfs_bit.c | 1 + fs/xfs/xfs_bmap_btree.c | 1 + fs/xfs/xfs_buf_item.c | 2 +- fs/xfs/xfs_da_format.c | 11 ++++++----- fs/xfs/xfs_dquot_buf.c | 3 ++- fs/xfs/xfs_ialloc_btree.c | 1 + fs/xfs/xfs_rtbitmap.c | 1 + fs/xfs/xfs_sb.c | 1 + fs/xfs/xfs_super.c | 2 +- 12 files changed, 18 insertions(+), 8 deletions(-) diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index 698587f6c60a..13085429e523 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c @@ -17,6 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index fdf9992dcbbc..7b126f46a2f9 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c index 2e5530467f2d..739e0a52deda 100644 --- a/fs/xfs/xfs_attr_remote.c +++ b/fs/xfs/xfs_attr_remote.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c index 16ce44a2b43e..0e8885a59646 100644 --- a/fs/xfs/xfs_bit.c +++ b/fs/xfs/xfs_bit.c @@ -17,6 +17,7 @@ */ #include "xfs.h" #include "xfs_log_format.h" +#include "xfs_bit.h" /* * XFS bit manipulation routines, used in non-realtime code. diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 2fb4a2202e17..706bc3f777cb 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -17,6 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index b6d20c55282b..a64f67ba25d3 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -809,7 +809,7 @@ xfs_buf_item_init( * Mark bytes first through last inclusive as dirty in the buf * item's bitmap. */ -void +static void xfs_buf_item_log_segment( struct xfs_buf_log_item *bip, uint first, diff --git a/fs/xfs/xfs_da_format.c b/fs/xfs/xfs_da_format.c index 870cac0b0981..e6c83e1fbc8a 100644 --- a/fs/xfs/xfs_da_format.c +++ b/fs/xfs/xfs_da_format.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" @@ -706,7 +707,7 @@ xfs_dir3_free_hdr_to_disk( hdr3->nused = cpu_to_be32(from->nused); } -const struct xfs_dir_ops xfs_dir2_ops = { +static const struct xfs_dir_ops xfs_dir2_ops = { .sf_entsize = xfs_dir2_sf_entsize, .sf_nextentry = xfs_dir2_sf_nextentry, .sf_get_ftype = xfs_dir2_sfe_get_ftype, @@ -756,7 +757,7 @@ const struct xfs_dir_ops xfs_dir2_ops = { .db_to_fdindex = xfs_dir2_db_to_fdindex, }; -const struct xfs_dir_ops xfs_dir2_ftype_ops = { +static const struct xfs_dir_ops xfs_dir2_ftype_ops = { .sf_entsize = xfs_dir3_sf_entsize, .sf_nextentry = xfs_dir3_sf_nextentry, .sf_get_ftype = xfs_dir3_sfe_get_ftype, @@ -806,7 +807,7 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = { .db_to_fdindex = xfs_dir2_db_to_fdindex, }; -const struct xfs_dir_ops xfs_dir3_ops = { +static const struct xfs_dir_ops xfs_dir3_ops = { .sf_entsize = xfs_dir3_sf_entsize, .sf_nextentry = xfs_dir3_sf_nextentry, .sf_get_ftype = xfs_dir3_sfe_get_ftype, @@ -856,14 +857,14 @@ const struct xfs_dir_ops xfs_dir3_ops = { .db_to_fdindex = xfs_dir3_db_to_fdindex, }; -const struct xfs_dir_ops xfs_dir2_nondir_ops = { +static const struct xfs_dir_ops xfs_dir2_nondir_ops = { .node_hdr_size = sizeof(struct xfs_da_node_hdr), .node_hdr_to_disk = xfs_da2_node_hdr_to_disk, .node_hdr_from_disk = xfs_da2_node_hdr_from_disk, .node_tree_p = xfs_da2_node_tree_p, }; -const struct xfs_dir_ops xfs_dir3_nondir_ops = { +static const struct xfs_dir_ops xfs_dir3_nondir_ops = { .node_hdr_size = sizeof(struct xfs_da3_node_hdr), .node_hdr_to_disk = xfs_da3_node_hdr_to_disk, .node_hdr_from_disk = xfs_da3_node_hdr_from_disk, diff --git a/fs/xfs/xfs_dquot_buf.c b/fs/xfs/xfs_dquot_buf.c index aaaf41b29869..d401457d2f25 100644 --- a/fs/xfs/xfs_dquot_buf.c +++ b/fs/xfs/xfs_dquot_buf.c @@ -18,6 +18,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" @@ -267,7 +268,7 @@ xfs_dquot_buf_read_verify( * the buffer after the update is done. This ensures that the dquot in the * buffer always has an up-to-date CRC value. */ -void +static void xfs_dquot_buf_write_verify( struct xfs_buf *bp) { diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c index 1fa142dc86cb..c8fa5bbb36de 100644 --- a/fs/xfs/xfs_ialloc_btree.c +++ b/fs/xfs/xfs_ialloc_btree.c @@ -17,6 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" diff --git a/fs/xfs/xfs_rtbitmap.c b/fs/xfs/xfs_rtbitmap.c index e30efe8be5e6..b1f2fe8af4a8 100644 --- a/fs/xfs/xfs_rtbitmap.c +++ b/fs/xfs/xfs_rtbitmap.c @@ -37,6 +37,7 @@ #include "xfs_buf.h" #include "xfs_icache.h" #include "xfs_dinode.h" +#include "xfs_rtalloc.h" /* diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index 05b5493d2baa..13c7834b0e65 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -17,6 +17,7 @@ */ #include "xfs.h" #include "xfs_fs.h" +#include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 4eb63ad87d7d..d971f4932b5d 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1155,7 +1155,7 @@ xfs_restore_resvblks(struct xfs_mount *mp) * Note: xfs_log_quiesce() stops background log work - the callers must ensure * it is started again when appropriate. */ -void +static void xfs_quiesce_attr( struct xfs_mount *mp) { -- cgit v1.2.3 From ad22c7a043c2cc6792820e6c5da699935933e87d Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:57 +1100 Subject: xfs: prevent stack overflows from page cache allocation Page cache allocation doesn't always go through ->begin_write and hence we don't always get the opportunity to set the allocation context to GFP_NOFS. Failing to do this means we open up the direct relcaim stack to recurse into the filesystem and consume a significant amount of stack. On RHEL6.4 kernels we are seeing ra_submit() and generic_file_splice_read() from an nfsd context recursing into the filesystem via the inode cache shrinker and evicting inodes. This is causing truncation to be run (e.g EOF block freeing) and causing bmap btree block merges and free space btree block splits to occur. These btree manipulations are occurring with the call chain already 30 functions deep and hence there is not enough stack space to complete such operations. To avoid these specific overruns, we need to prevent the page cache allocation from recursing via direct reclaim. We can do that because the allocation functions take the allocation context from that which is stored in the mapping for the inode. We don't set that right now, so the default is GFP_HIGHUSER_MOVABLE, which is effectively a GFP_KERNEL context. We need it to be the equivalent of GFP_NOFS, so when we initialise an inode, set the mapping gfp mask appropriately. This makes the use of AOP_FLAG_NOFS redundant from other parts of the XFS IO path, so get rid of it. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_aops.c | 3 +-- fs/xfs/xfs_iops.c | 9 +++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index eb310caf13b1..71c8c9d2b882 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -1572,8 +1572,7 @@ xfs_vm_write_begin( ASSERT(len <= PAGE_CACHE_SIZE); - page = grab_cache_page_write_begin(mapping, index, - flags | AOP_FLAG_NOFS); + page = grab_cache_page_write_begin(mapping, index, flags); if (!page) return -ENOMEM; diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index c4cd6d47f523..27e0e544e963 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1168,6 +1168,7 @@ xfs_setup_inode( struct xfs_inode *ip) { struct inode *inode = &ip->i_vnode; + gfp_t gfp_mask; inode->i_ino = ip->i_ino; inode->i_state = I_NEW; @@ -1229,6 +1230,14 @@ xfs_setup_inode( break; } + /* + * Ensure all page cache allocations are done from GFP_NOFS context to + * prevent direct reclaim recursion back into the filesystem and blowing + * stacks or deadlocking. + */ + gfp_mask = mapping_gfp_mask(inode->i_mapping); + mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS))); + /* * If there is no attribute fork no ACL can exist on this inode, * and it can't have any file capabilities attached to it either. -- cgit v1.2.3 From 5bf1f439c89d4653f8cc8f8aa303e0d6991aba4b Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Fri, 25 Oct 2013 15:53:25 +0400 Subject: xfs:xfs_dir2_node.c: pointer use before check for null ASSERT on args takes place after args dereference. This assertion is redundant since we are going to panic anyway. Found by Linux Driver Verification project (linuxtesting.org) - PVS-Studio analyzer. Signed-off-by: Denis Efremov Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_dir2_node.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index f90bf0690346..56369d4509d5 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -1327,7 +1327,6 @@ xfs_dir2_leafn_split( args = state->args; dp = args->dp; mp = dp->i_mount; - ASSERT(args != NULL); ASSERT(oldblk->magic == XFS_DIR2_LEAFN_MAGIC); error = xfs_da_grow_inode(args, &blkno); if (error) { -- cgit v1.2.3 From 643f7c4e5656bd18c769211f933190f7bb738245 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Wed, 30 Oct 2013 16:01:00 -0500 Subject: xfs: fix possible NULL dereference in xlog_verify_iclog In xlog_verify_iclog a debug check of the incore log buffers prints an error if icptr is null and then goes on to dereference the pointer regardless. Convert this to an assert so that the intention is clear. This was reported by Coverty. Signed-off-by: Ben Myers Reviewed-by: Eric Sandeen --- fs/xfs/xfs_log.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index e523396753c5..49dd41e6a2dc 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -3710,11 +3710,9 @@ xlog_verify_iclog( /* check validity of iclog pointers */ spin_lock(&log->l_icloglock); icptr = log->l_iclog; - for (i=0; i < log->l_iclog_bufs; i++) { - if (icptr == NULL) - xfs_emerg(log->l_mp, "%s: invalid ptr", __func__); - icptr = icptr->ic_next; - } + for (i = 0; i < log->l_iclog_bufs; i++, icptr = icptr->ic_next) + ASSERT(icptr); + if (icptr != log->l_iclog) xfs_emerg(log->l_mp, "%s: corrupt iclog ring", __func__); spin_unlock(&log->l_icloglock); -- cgit v1.2.3 From 10e6e65dfcedff63275c3d649d329c044caa8e26 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Mon, 9 Sep 2013 15:33:29 -0500 Subject: xfs: be more forgiving of a v4 secondary sb w/ junk in v5 fields Today, if xfs_sb_read_verify encounters a v4 superblock with junk past v4 fields which includes data in sb_crc, it will be treated as a failing checksum and a significant corruption. There are known prior bugs which leave junk at the end of the V4 superblock; we don't need to actually fail the verification in this case if other checks pan out ok. So if this is a secondary superblock, and the primary superblock doesn't indicate that this is a V5 filesystem, don't treat this as an actual checksum failure. We should probably check the garbage condition as we do in xfs_repair, and possibly warn about it or self-heal, but that's a different scope of work. Stable folks: This can go back to v3.10, which is what introduced the sb CRC checking that is tripped up by old, stale, incorrect V4 superblocks w/ unzeroed bits. Cc: stable@vger.kernel.org Signed-off-by: Eric Sandeen Acked-by: Dave Chinner Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers --- fs/xfs/xfs_sb.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c index 13c7834b0e65..b7c9aea77f8f 100644 --- a/fs/xfs/xfs_sb.c +++ b/fs/xfs/xfs_sb.c @@ -588,6 +588,11 @@ xfs_sb_verify( * single bit error could clear the feature bit and unused parts of the * superblock are supposed to be zero. Hence a non-null crc field indicates that * we've potentially lost a feature bit and we should check it anyway. + * + * However, past bugs (i.e. in growfs) left non-zeroed regions beyond the + * last field in V4 secondary superblocks. So for secondary superblocks, + * we are more forgiving, and ignore CRC failures if the primary doesn't + * indicate that the fs version is V5. */ static void xfs_sb_read_verify( @@ -608,8 +613,12 @@ xfs_sb_read_verify( if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize), offsetof(struct xfs_sb, sb_crc))) { - error = EFSCORRUPTED; - goto out_error; + /* Only fail bad secondaries on a known V5 filesystem */ + if (bp->b_bn != XFS_SB_DADDR && + xfs_sb_version_hascrc(&mp->m_sb)) { + error = EFSCORRUPTED; + goto out_error; + } } } error = xfs_sb_verify(bp, true); -- cgit v1.2.3 From bb86d21cba22a045b09d11b71decf5ca7c3d5def Mon Sep 17 00:00:00 2001 From: Jie Liu Date: Fri, 25 Oct 2013 14:52:44 +0800 Subject: xfs: fix the extent count when allocating an new indirection array entry At xfs_iext_add(), if extent(s) are being appended to the last page in the indirection array and the new extent(s) don't fit in the page, the number of extents(erp->er_extcount) in a new allocated entry should be the minimum value between count and XFS_LINEAR_EXTS, instead of count. For now, there is no existing test case can demonstrates a problem with the er_extcount being set incorrectly here, but it obviously like a bug. Signed-off-by: Jie Liu Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_inode_fork.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/xfs/xfs_inode_fork.c b/fs/xfs/xfs_inode_fork.c index 22c9837c5d4b..cfee14a83cfe 100644 --- a/fs/xfs/xfs_inode_fork.c +++ b/fs/xfs/xfs_inode_fork.c @@ -1021,15 +1021,14 @@ xfs_iext_add( * the next index needed in the indirection array. */ else { - int count = ext_diff; + uint count = ext_diff; while (count) { erp = xfs_iext_irec_new(ifp, erp_idx); - erp->er_extcount = count; - count -= MIN(count, (int)XFS_LINEAR_EXTS); - if (count) { + erp->er_extcount = min(count, XFS_LINEAR_EXTS); + count -= erp->er_extcount; + if (count) erp_idx++; - } } } } -- cgit v1.2.3 From 273203699f82667296e1f14344c5a5a6c4600470 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Oct 2013 22:11:44 +1100 Subject: xfs: xfs_remove deadlocks due to inverted AGF vs AGI lock ordering Removing an inode from the namespace involves removing the directory entry and dropping the link count on the inode. Removing the directory entry can result in locking an AGF (directory blocks were freed) and removing a link count can result in placing the inode on an unlinked list which results in locking an AGI. The big problem here is that we have an ordering constraint on AGF and AGI locking - inode allocation locks the AGI, then can allocate a new extent for new inodes, locking the AGF after the AGI. Similarly, freeing the inode removes the inode from the unlinked list, requiring that we lock the AGI first, and then freeing the inode can result in an inode chunk being freed and hence freeing disk space requiring that we lock an AGF. Hence the ordering that is imposed by other parts of the code is AGI before AGF. This means we cannot remove the directory entry before we drop the inode reference count and put it on the unlinked list as this results in a lock order of AGF then AGI, and this can deadlock against inode allocation and freeing. Therefore we must drop the link counts before we remove the directory entry. This is still safe from a transactional point of view - it is not until we get to xfs_bmap_finish() that we have the possibility of multiple transactions in this operation. Hence as long as we remove the directory entry and drop the link count in the first transaction of the remove operation, there are no transactional constraints on the ordering here. Change the ordering of the operations in the xfs_remove() function to align the ordering of AGI and AGF locking to match that of the rest of the code. Signed-off-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_inode.c | 72 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 326b94dbe159..001aa893ed59 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2404,6 +2404,33 @@ xfs_iunpin_wait( __xfs_iunpin_wait(ip); } +/* + * Removing an inode from the namespace involves removing the directory entry + * and dropping the link count on the inode. Removing the directory entry can + * result in locking an AGF (directory blocks were freed) and removing a link + * count can result in placing the inode on an unlinked list which results in + * locking an AGI. + * + * The big problem here is that we have an ordering constraint on AGF and AGI + * locking - inode allocation locks the AGI, then can allocate a new extent for + * new inodes, locking the AGF after the AGI. Similarly, freeing the inode + * removes the inode from the unlinked list, requiring that we lock the AGI + * first, and then freeing the inode can result in an inode chunk being freed + * and hence freeing disk space requiring that we lock an AGF. + * + * Hence the ordering that is imposed by other parts of the code is AGI before + * AGF. This means we cannot remove the directory entry before we drop the inode + * reference count and put it on the unlinked list as this results in a lock + * order of AGF then AGI, and this can deadlock against inode allocation and + * freeing. Therefore we must drop the link counts before we remove the + * directory entry. + * + * This is still safe from a transactional point of view - it is not until we + * get to xfs_bmap_finish() that we have the possibility of multiple + * transactions in this operation. Hence as long as we remove the directory + * entry and drop the link count in the first transaction of the remove + * operation, there are no transactional constraints on the ordering here. + */ int xfs_remove( xfs_inode_t *dp, @@ -2473,6 +2500,7 @@ xfs_remove( /* * If we're removing a directory perform some additional validation. */ + cancel_flags |= XFS_TRANS_ABORT; if (is_dir) { ASSERT(ip->i_d.di_nlink >= 2); if (ip->i_d.di_nlink != 2) { @@ -2483,31 +2511,16 @@ xfs_remove( error = XFS_ERROR(ENOTEMPTY); goto out_trans_cancel; } - } - xfs_bmap_init(&free_list, &first_block); - error = xfs_dir_removename(tp, dp, name, ip->i_ino, - &first_block, &free_list, resblks); - if (error) { - ASSERT(error != ENOENT); - goto out_bmap_cancel; - } - xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - - if (is_dir) { - /* - * Drop the link from ip's "..". - */ + /* Drop the link from ip's "..". */ error = xfs_droplink(tp, dp); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; - /* - * Drop the "." link from ip to self. - */ + /* Drop the "." link from ip to self. */ error = xfs_droplink(tp, ip); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; } else { /* * When removing a non-directory we need to log the parent @@ -2516,20 +2529,24 @@ xfs_remove( */ xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); } + xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); - /* - * Drop the link from dp to ip. - */ + /* Drop the link from dp to ip. */ error = xfs_droplink(tp, ip); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; - /* - * Determine if this is the last link while - * we are in the transaction. - */ + /* Determine if this is the last link while the inode is locked */ link_zero = (ip->i_d.di_nlink == 0); + xfs_bmap_init(&free_list, &first_block); + error = xfs_dir_removename(tp, dp, name, ip->i_ino, + &first_block, &free_list, resblks); + if (error) { + ASSERT(error != ENOENT); + goto out_bmap_cancel; + } + /* * If this is a synchronous mount, make sure that the * remove transaction goes to disk before returning to @@ -2559,7 +2576,6 @@ xfs_remove( out_bmap_cancel: xfs_bmap_cancel(&free_list); - cancel_flags |= XFS_TRANS_ABORT; out_trans_cancel: xfs_trans_cancel(tp, cancel_flags); std_return: -- cgit v1.2.3 From 750b9c90668b173a92b20e747b9736b8537eda5a Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 1 Nov 2013 15:27:18 +1100 Subject: xfs: trace AIL manipulations I debugging a log tail issue on a RHEL6 kernel, I added these trace points to trace log items being added, moved and removed in the AIL and how that affected the log tail LSN that was written to the log. They were very helpful in that they immediately identified the cause of the problem being seen. Hence I'd like to always have them available for use. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_log.c | 1 + fs/xfs/xfs_trace.h | 59 +++++++++++++++++++++++++++++++++++++++++++++++++- fs/xfs/xfs_trans_ail.c | 3 +++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 49dd41e6a2dc..8497a00e399d 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1076,6 +1076,7 @@ xlog_assign_tail_lsn_locked( tail_lsn = lip->li_lsn; else tail_lsn = atomic64_read(&log->l_last_sync_lsn); + trace_xfs_log_assign_tail_lsn(log, tail_lsn); atomic64_set(&log->l_tail_lsn, tail_lsn); return tail_lsn; } diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 47910e638c18..f195476a037c 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -31,8 +31,8 @@ struct xfs_da_args; struct xfs_da_node_entry; struct xfs_dquot; struct xfs_log_item; -struct xlog_ticket; struct xlog; +struct xlog_ticket; struct xlog_recover; struct xlog_recover_item; struct xfs_buf_log_format; @@ -938,6 +938,63 @@ DEFINE_LOG_ITEM_EVENT(xfs_ail_pinned); DEFINE_LOG_ITEM_EVENT(xfs_ail_locked); DEFINE_LOG_ITEM_EVENT(xfs_ail_flushing); +DECLARE_EVENT_CLASS(xfs_ail_class, + TP_PROTO(struct xfs_log_item *lip, xfs_lsn_t old_lsn, xfs_lsn_t new_lsn), + TP_ARGS(lip, old_lsn, new_lsn), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(void *, lip) + __field(uint, type) + __field(uint, flags) + __field(xfs_lsn_t, old_lsn) + __field(xfs_lsn_t, new_lsn) + ), + TP_fast_assign( + __entry->dev = lip->li_mountp->m_super->s_dev; + __entry->lip = lip; + __entry->type = lip->li_type; + __entry->flags = lip->li_flags; + __entry->old_lsn = old_lsn; + __entry->new_lsn = new_lsn; + ), + TP_printk("dev %d:%d lip 0x%p old lsn %d/%d new lsn %d/%d type %s flags %s", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->lip, + CYCLE_LSN(__entry->old_lsn), BLOCK_LSN(__entry->old_lsn), + CYCLE_LSN(__entry->new_lsn), BLOCK_LSN(__entry->new_lsn), + __print_symbolic(__entry->type, XFS_LI_TYPE_DESC), + __print_flags(__entry->flags, "|", XFS_LI_FLAGS)) +) + +#define DEFINE_AIL_EVENT(name) \ +DEFINE_EVENT(xfs_ail_class, name, \ + TP_PROTO(struct xfs_log_item *lip, xfs_lsn_t old_lsn, xfs_lsn_t new_lsn), \ + TP_ARGS(lip, old_lsn, new_lsn)) +DEFINE_AIL_EVENT(xfs_ail_insert); +DEFINE_AIL_EVENT(xfs_ail_move); +DEFINE_AIL_EVENT(xfs_ail_delete); + +TRACE_EVENT(xfs_log_assign_tail_lsn, + TP_PROTO(struct xlog *log, xfs_lsn_t new_lsn), + TP_ARGS(log, new_lsn), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_lsn_t, new_lsn) + __field(xfs_lsn_t, old_lsn) + __field(xfs_lsn_t, last_sync_lsn) + ), + TP_fast_assign( + __entry->dev = log->l_mp->m_super->s_dev; + __entry->new_lsn = new_lsn; + __entry->old_lsn = atomic64_read(&log->l_tail_lsn); + __entry->last_sync_lsn = atomic64_read(&log->l_last_sync_lsn); + ), + TP_printk("dev %d:%d new tail lsn %d/%d, old lsn %d/%d, last sync %d/%d", + MAJOR(__entry->dev), MINOR(__entry->dev), + CYCLE_LSN(__entry->new_lsn), BLOCK_LSN(__entry->new_lsn), + CYCLE_LSN(__entry->old_lsn), BLOCK_LSN(__entry->old_lsn), + CYCLE_LSN(__entry->last_sync_lsn), BLOCK_LSN(__entry->last_sync_lsn)) +) DECLARE_EVENT_CLASS(xfs_file_class, TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 4b47cfebd25b..a7287354e535 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -659,11 +659,13 @@ xfs_trans_ail_update_bulk( if (XFS_LSN_CMP(lsn, lip->li_lsn) <= 0) continue; + trace_xfs_ail_move(lip, lip->li_lsn, lsn); xfs_ail_delete(ailp, lip); if (mlip == lip) mlip_changed = 1; } else { lip->li_flags |= XFS_LI_IN_AIL; + trace_xfs_ail_insert(lip, 0, lsn); } lip->li_lsn = lsn; list_add(&lip->li_ail, &tmp); @@ -732,6 +734,7 @@ xfs_trans_ail_delete_bulk( return; } + trace_xfs_ail_delete(lip, mlip->li_lsn, lip->li_lsn); xfs_ail_delete(ailp, lip); lip->li_flags &= ~XFS_LI_IN_AIL; lip->li_lsn = 0; -- cgit v1.2.3 From d123031a5673cd38a85ce66cc07243dfe5f424c9 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Fri, 1 Nov 2013 15:27:19 +1100 Subject: xfs: add tracepoints to AGF/AGI read operations To help track down AGI/AGF lock ordering issues, I added these tracepoints to tell us when an AGI or AGF is read and locked. With these we can now determine if the lock ordering goes wrong from tracing captures. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Ben Myers --- fs/xfs/xfs_alloc.c | 5 ++++- fs/xfs/xfs_ialloc.c | 6 +++++- fs/xfs/xfs_trace.h | 25 +++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index bcf16528bac5..9eab2dfdcbb5 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -2294,6 +2294,8 @@ xfs_read_agf( { int error; + trace_xfs_read_agf(mp, agno); + ASSERT(agno != NULLAGNUMBER); error = xfs_trans_read_buf( mp, tp, mp->m_ddev_targp, @@ -2324,8 +2326,9 @@ xfs_alloc_read_agf( struct xfs_perag *pag; /* per allocation group data */ int error; - ASSERT(agno != NULLAGNUMBER); + trace_xfs_alloc_read_agf(mp, agno); + ASSERT(agno != NULLAGNUMBER); error = xfs_read_agf(mp, tp, agno, (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0, bpp); diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 14d732f61a41..e87719c5bebe 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -40,6 +40,7 @@ #include "xfs_icreate_item.h" #include "xfs_icache.h" #include "xfs_dinode.h" +#include "xfs_trace.h" /* @@ -1627,8 +1628,9 @@ xfs_read_agi( { int error; - ASSERT(agno != NULLAGNUMBER); + trace_xfs_read_agi(mp, agno); + ASSERT(agno != NULLAGNUMBER); error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), 0, bpp, &xfs_agi_buf_ops); @@ -1651,6 +1653,8 @@ xfs_ialloc_read_agi( struct xfs_perag *pag; /* per allocation group data */ int error; + trace_xfs_ialloc_read_agi(mp, agno); + error = xfs_read_agi(mp, tp, agno, bpp); if (error) return error; diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index f195476a037c..425dfa45b9a0 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -135,6 +135,31 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim); DEFINE_PERAG_REF_EVENT(xfs_perag_set_eofblocks); DEFINE_PERAG_REF_EVENT(xfs_perag_clear_eofblocks); +DECLARE_EVENT_CLASS(xfs_ag_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno), + TP_ARGS(mp, agno), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + ), + TP_printk("dev %d:%d agno %u", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno) +); +#define DEFINE_AG_EVENT(name) \ +DEFINE_EVENT(xfs_ag_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno), \ + TP_ARGS(mp, agno)) + +DEFINE_AG_EVENT(xfs_read_agf); +DEFINE_AG_EVENT(xfs_alloc_read_agf); +DEFINE_AG_EVENT(xfs_read_agi); +DEFINE_AG_EVENT(xfs_ialloc_read_agi); + TRACE_EVENT(xfs_attr_list_node_descend, TP_PROTO(struct xfs_attr_list_context *ctx, struct xfs_da_node_entry *btree), -- cgit v1.2.3 From 359d992bcd398273637cd9edde10afca953783c4 Mon Sep 17 00:00:00 2001 From: Gu Zheng Date: Mon, 4 Nov 2013 18:21:05 +0800 Subject: xfs: simplify kmem_{zone_}zalloc Introduce flag KM_ZERO which is used to alloc zeroed entry, and convert kmem_{zone_}zalloc to call kmem_{zone_}alloc() with KM_ZERO directly, in order to avoid the setting to zero step. And following Dave's suggestion, make kmem_{zone_}zalloc static inline into kmem.h as they're now just a simple wrapper. V2: Make kmem_{zone_}zalloc static inline into kmem.h as Dave suggested. Signed-off-by: Gu Zheng Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/kmem.c | 22 ---------------------- fs/xfs/kmem.h | 21 ++++++++++++++++++--- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c index a02cfb9e3bce..66a36befc5c0 100644 --- a/fs/xfs/kmem.c +++ b/fs/xfs/kmem.c @@ -62,17 +62,6 @@ kmem_alloc(size_t size, xfs_km_flags_t flags) } while (1); } -void * -kmem_zalloc(size_t size, xfs_km_flags_t flags) -{ - void *ptr; - - ptr = kmem_alloc(size, flags); - if (ptr) - memset((char *)ptr, 0, (int)size); - return ptr; -} - void * kmem_zalloc_large(size_t size, xfs_km_flags_t flags) { @@ -128,14 +117,3 @@ kmem_zone_alloc(kmem_zone_t *zone, xfs_km_flags_t flags) congestion_wait(BLK_RW_ASYNC, HZ/50); } while (1); } - -void * -kmem_zone_zalloc(kmem_zone_t *zone, xfs_km_flags_t flags) -{ - void *ptr; - - ptr = kmem_zone_alloc(zone, flags); - if (ptr) - memset((char *)ptr, 0, kmem_cache_size(zone)); - return ptr; -} diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h index 3a7371cab508..64db0e53edea 100644 --- a/fs/xfs/kmem.h +++ b/fs/xfs/kmem.h @@ -32,6 +32,7 @@ typedef unsigned __bitwise xfs_km_flags_t; #define KM_NOSLEEP ((__force xfs_km_flags_t)0x0002u) #define KM_NOFS ((__force xfs_km_flags_t)0x0004u) #define KM_MAYFAIL ((__force xfs_km_flags_t)0x0008u) +#define KM_ZERO ((__force xfs_km_flags_t)0x0010u) /* * We use a special process flag to avoid recursive callbacks into @@ -43,7 +44,7 @@ kmem_flags_convert(xfs_km_flags_t flags) { gfp_t lflags; - BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL)); + BUG_ON(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL|KM_ZERO)); if (flags & KM_NOSLEEP) { lflags = GFP_ATOMIC | __GFP_NOWARN; @@ -52,11 +53,14 @@ kmem_flags_convert(xfs_km_flags_t flags) if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS)) lflags &= ~__GFP_FS; } + + if (flags & KM_ZERO) + lflags |= __GFP_ZERO; + return lflags; } extern void *kmem_alloc(size_t, xfs_km_flags_t); -extern void *kmem_zalloc(size_t, xfs_km_flags_t); extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t); extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t); extern void kmem_free(const void *); @@ -64,6 +68,12 @@ extern void kmem_free(const void *); extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); +static inline void * +kmem_zalloc(size_t size, xfs_km_flags_t flags) +{ + return kmem_alloc(size, flags | KM_ZERO); +} + /* * Zone interfaces */ @@ -102,6 +112,11 @@ kmem_zone_destroy(kmem_zone_t *zone) } extern void *kmem_zone_alloc(kmem_zone_t *, xfs_km_flags_t); -extern void *kmem_zone_zalloc(kmem_zone_t *, xfs_km_flags_t); + +static inline void * +kmem_zone_zalloc(kmem_zone_t *zone, xfs_km_flags_t flags) +{ + return kmem_zone_alloc(zone, flags | KM_ZERO); +} #endif /* __XFS_SUPPORT_KMEM_H__ */ -- cgit v1.2.3