aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-06-06 01:01:58 -0400
committerDave Chinner <david@fromorbit.com>2014-06-06 01:01:58 -0400
commit0650b55497ef583c43d6afc80e11a39e92d9a525 (patch)
tree7605714c36579ac623f4045db2fcb08ca9d298a5
parent2d6dcc6d7e95cc83046b2f97e179e6bbb7921245 (diff)
xfs: introduce directory geometry structure
The directory code has a dependency on the struct xfs_mount to supply the directory block geometry. Block size, block log size, and other parameters are pre-caclulated in the struct xfs_mount or access directly from the superblock embedded in the struct xfs_mount. Extract all of this geometry information out of the struct xfs_mount and superblock and place it into a new struct xfs_da_geometry defined by the directory code. Allocate and initialise it at mount time, and attach it to the struct xfs_mount so it canbe passed back into the directory code appropriately rather than using the struct xfs_mount. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--fs/xfs/xfs_attr.c1
-rw-r--r--fs/xfs/xfs_attr_leaf.c2
-rw-r--r--fs/xfs/xfs_attr_list.c1
-rw-r--r--fs/xfs/xfs_da_btree.h18
-rw-r--r--fs/xfs/xfs_dir2.c73
-rw-r--r--fs/xfs/xfs_dir2.h4
-rw-r--r--fs/xfs/xfs_mount.c16
-rw-r--r--fs/xfs/xfs_mount.h3
8 files changed, 97 insertions, 21 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 1fc1f06277da..c5474982cfd2 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -88,6 +88,7 @@ xfs_attr_args_init(
88 return EINVAL; 88 return EINVAL;
89 89
90 memset(args, 0, sizeof(*args)); 90 memset(args, 0, sizeof(*args));
91 args->geo = dp->i_mount->m_attr_geo;
91 args->whichfork = XFS_ATTR_FORK; 92 args->whichfork = XFS_ATTR_FORK;
92 args->dp = dp; 93 args->dp = dp;
93 args->flags = flags; 94 args->flags = flags;
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 511c283459b1..2c0fdc8a71f6 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -711,6 +711,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
711 711
712 memset((char *)&nargs, 0, sizeof(nargs)); 712 memset((char *)&nargs, 0, sizeof(nargs));
713 nargs.dp = dp; 713 nargs.dp = dp;
714 nargs.geo = args->geo;
714 nargs.firstblock = args->firstblock; 715 nargs.firstblock = args->firstblock;
715 nargs.flist = args->flist; 716 nargs.flist = args->flist;
716 nargs.total = args->total; 717 nargs.total = args->total;
@@ -838,6 +839,7 @@ xfs_attr3_leaf_to_shortform(
838 * Copy the attributes 839 * Copy the attributes
839 */ 840 */
840 memset((char *)&nargs, 0, sizeof(nargs)); 841 memset((char *)&nargs, 0, sizeof(nargs));
842 nargs.geo = args->geo;
841 nargs.dp = dp; 843 nargs.dp = dp;
842 nargs.firstblock = args->firstblock; 844 nargs.firstblock = args->firstblock;
843 nargs.flist = args->flist; 845 nargs.flist = args->flist;
diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
index 833fe5d98d80..90e2eeb21207 100644
--- a/fs/xfs/xfs_attr_list.c
+++ b/fs/xfs/xfs_attr_list.c
@@ -444,6 +444,7 @@ xfs_attr3_leaf_list_int(
444 xfs_da_args_t args; 444 xfs_da_args_t args;
445 445
446 memset((char *)&args, 0, sizeof(args)); 446 memset((char *)&args, 0, sizeof(args));
447 args.geo = context->dp->i_mount->m_attr_geo;
447 args.dp = context->dp; 448 args.dp = context->dp;
448 args.whichfork = XFS_ATTR_FORK; 449 args.whichfork = XFS_ATTR_FORK;
449 args.valuelen = valuelen; 450 args.valuelen = valuelen;
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index c824a0aa039f..0ac63adca705 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -25,6 +25,23 @@ struct xfs_trans;
25struct zone; 25struct zone;
26struct xfs_dir_ops; 26struct xfs_dir_ops;
27 27
28/*
29 * Directory/attribute geometry information. There will be one of these for each
30 * data fork type, and it will be passed around via the xfs_da_args. Global
31 * structures will be attached to the xfs_mount.
32 */
33struct xfs_da_geometry {
34 int blksize; /* da block size in bytes */
35 int fsbcount; /* da block size in filesystem blocks */
36 uint8_t fsblog; /* log2 of _filesystem_ block size */
37 uint8_t blklog; /* log2 of da block size */
38 uint node_ents; /* # of entries in a danode */
39 int magicpct; /* 37% of block size in bytes */
40 xfs_dablk_t datablk; /* blockno of dir data v2 */
41 xfs_dablk_t leafblk; /* blockno of leaf data v2 */
42 xfs_dablk_t freeblk; /* blockno of free data v2 */
43};
44
28/*======================================================================== 45/*========================================================================
29 * Btree searching and modification structure definitions. 46 * Btree searching and modification structure definitions.
30 *========================================================================*/ 47 *========================================================================*/
@@ -42,6 +59,7 @@ enum xfs_dacmp {
42 * Structure to ease passing around component names. 59 * Structure to ease passing around component names.
43 */ 60 */
44typedef struct xfs_da_args { 61typedef struct xfs_da_args {
62 struct xfs_da_geometry *geo; /* da block geometry */
45 const __uint8_t *name; /* string (maybe not NULL terminated) */ 63 const __uint8_t *name; /* string (maybe not NULL terminated) */
46 int namelen; /* length of string (maybe no NULL) */ 64 int namelen; /* length of string (maybe no NULL) */
47 __uint8_t filetype; /* filetype of inode for directories */ 65 __uint8_t filetype; /* filetype of inode for directories */
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index e365c98c0f1e..bf0d6dd47242 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -85,11 +85,12 @@ static struct xfs_nameops xfs_ascii_ci_nameops = {
85 .compname = xfs_ascii_ci_compname, 85 .compname = xfs_ascii_ci_compname,
86}; 86};
87 87
88void 88int
89xfs_dir_mount( 89xfs_da_mount(
90 xfs_mount_t *mp) 90 struct xfs_mount *mp)
91{ 91{
92 int nodehdr_size; 92 struct xfs_da_geometry *dageo;
93 int nodehdr_size;
93 94
94 95
95 ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb)); 96 ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb));
@@ -99,24 +100,64 @@ xfs_dir_mount(
99 mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL); 100 mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL);
100 mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL); 101 mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL);
101 102
102 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
103 mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog;
104 mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp));
105 mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
106 mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp));
107
108 nodehdr_size = mp->m_dir_inode_ops->node_hdr_size; 103 nodehdr_size = mp->m_dir_inode_ops->node_hdr_size;
109 mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_size) / 104 mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
105 KM_SLEEP | KM_MAYFAIL);
106 mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
107 KM_SLEEP | KM_MAYFAIL);
108 if (!mp->m_dir_geo || !mp->m_attr_geo) {
109 kmem_free(mp->m_dir_geo);
110 kmem_free(mp->m_attr_geo);
111 return ENOMEM;
112 }
113
114 /* set up directory geometry */
115 dageo = mp->m_dir_geo;
116 dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
117 dageo->fsblog = mp->m_sb.sb_blocklog;
118 dageo->blksize = 1 << dageo->blklog;
119 dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
120 dageo->datablk = xfs_dir2_byte_to_da(mp, XFS_DIR2_DATA_OFFSET);
121 dageo->leafblk = xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET);
122 dageo->freeblk = xfs_dir2_byte_to_da(mp, XFS_DIR2_FREE_OFFSET);
123 dageo->node_ents = (dageo->blksize - nodehdr_size) /
110 (uint)sizeof(xfs_da_node_entry_t); 124 (uint)sizeof(xfs_da_node_entry_t);
111 mp->m_dir_node_ents = (mp->m_dirblksize - nodehdr_size) / 125 dageo->magicpct = (dageo->blksize * 37) / 100;
126
127 /* set up attribute geometry - single fsb only */
128 dageo = mp->m_attr_geo;
129 dageo->blklog = mp->m_sb.sb_blocklog;
130 dageo->fsblog = mp->m_sb.sb_blocklog;
131 dageo->blksize = 1 << dageo->blklog;
132 dageo->fsbcount = 1;
133 dageo->node_ents = (dageo->blksize - nodehdr_size) /
112 (uint)sizeof(xfs_da_node_entry_t); 134 (uint)sizeof(xfs_da_node_entry_t);
135 dageo->magicpct = (dageo->blksize * 37) / 100;
113 136
114 mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;
115 if (xfs_sb_version_hasasciici(&mp->m_sb)) 137 if (xfs_sb_version_hasasciici(&mp->m_sb))
116 mp->m_dirnameops = &xfs_ascii_ci_nameops; 138 mp->m_dirnameops = &xfs_ascii_ci_nameops;
117 else 139 else
118 mp->m_dirnameops = &xfs_default_nameops; 140 mp->m_dirnameops = &xfs_default_nameops;
119 141
142 /* XXX: these are to be removed as code is converted to use geo */
143 mp->m_dirblksize = mp->m_dir_geo->blksize;
144 mp->m_dirblkfsbs = mp->m_dir_geo->fsbcount;
145 mp->m_dirdatablk = mp->m_dir_geo->datablk;
146 mp->m_dirleafblk = mp->m_dir_geo->leafblk;
147 mp->m_dirfreeblk = mp->m_dir_geo->freeblk;
148 mp->m_dir_node_ents = mp->m_dir_geo->node_ents;
149 mp->m_dir_magicpct = mp->m_dir_geo->magicpct;
150 mp->m_attr_node_ents = mp->m_attr_geo->node_ents;
151 mp->m_attr_magicpct = mp->m_attr_geo->magicpct;
152 return 0;
153}
154
155void
156xfs_da_unmount(
157 struct xfs_mount *mp)
158{
159 kmem_free(mp->m_dir_geo);
160 kmem_free(mp->m_attr_geo);
120} 161}
121 162
122/* 163/*
@@ -192,6 +233,7 @@ xfs_dir_init(
192 if (!args) 233 if (!args)
193 return ENOMEM; 234 return ENOMEM;
194 235
236 args->geo = dp->i_mount->m_dir_geo;
195 args->dp = dp; 237 args->dp = dp;
196 args->trans = tp; 238 args->trans = tp;
197 error = xfs_dir2_sf_create(args, pdp->i_ino); 239 error = xfs_dir2_sf_create(args, pdp->i_ino);
@@ -226,6 +268,7 @@ xfs_dir_createname(
226 if (!args) 268 if (!args)
227 return ENOMEM; 269 return ENOMEM;
228 270
271 args->geo = dp->i_mount->m_dir_geo;
229 args->name = name->name; 272 args->name = name->name;
230 args->namelen = name->len; 273 args->namelen = name->len;
231 args->filetype = name->type; 274 args->filetype = name->type;
@@ -320,6 +363,7 @@ xfs_dir_lookup(
320 * annotations into the reclaim path for the ilock. 363 * annotations into the reclaim path for the ilock.
321 */ 364 */
322 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 365 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
366 args->geo = dp->i_mount->m_dir_geo;
323 args->name = name->name; 367 args->name = name->name;
324 args->namelen = name->len; 368 args->namelen = name->len;
325 args->filetype = name->type; 369 args->filetype = name->type;
@@ -391,6 +435,7 @@ xfs_dir_removename(
391 if (!args) 435 if (!args)
392 return ENOMEM; 436 return ENOMEM;
393 437
438 args->geo = dp->i_mount->m_dir_geo;
394 args->name = name->name; 439 args->name = name->name;
395 args->namelen = name->len; 440 args->namelen = name->len;
396 args->filetype = name->type; 441 args->filetype = name->type;
@@ -455,6 +500,7 @@ xfs_dir_replace(
455 if (!args) 500 if (!args)
456 return ENOMEM; 501 return ENOMEM;
457 502
503 args->geo = dp->i_mount->m_dir_geo;
458 args->name = name->name; 504 args->name = name->name;
459 args->namelen = name->len; 505 args->namelen = name->len;
460 args->filetype = name->type; 506 args->filetype = name->type;
@@ -516,6 +562,7 @@ xfs_dir_canenter(
516 if (!args) 562 if (!args)
517 return ENOMEM; 563 return ENOMEM;
518 564
565 args->geo = dp->i_mount->m_dir_geo;
519 args->name = name->name; 566 args->name = name->name;
520 args->namelen = name->len; 567 args->namelen = name->len;
521 args->filetype = name->type; 568 args->filetype = name->type;
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 64a6b19c2fd0..7a85b9c1f849 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -112,7 +112,9 @@ extern const struct xfs_dir_ops *
112 * Generic directory interface routines 112 * Generic directory interface routines
113 */ 113 */
114extern void xfs_dir_startup(void); 114extern void xfs_dir_startup(void);
115extern void xfs_dir_mount(struct xfs_mount *mp); 115extern int xfs_da_mount(struct xfs_mount *mp);
116extern void xfs_da_unmount(struct xfs_mount *mp);
117
116extern int xfs_dir_isempty(struct xfs_inode *dp); 118extern int xfs_dir_isempty(struct xfs_inode *dp);
117extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, 119extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
118 struct xfs_inode *pdp); 120 struct xfs_inode *pdp);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 944f3d9456a8..1ec84c359ea5 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -774,12 +774,11 @@ xfs_mountfs(
774 774
775 mp->m_dmevmask = 0; /* not persistent; set after each mount */ 775 mp->m_dmevmask = 0; /* not persistent; set after each mount */
776 776
777 xfs_dir_mount(mp); 777 error = xfs_da_mount(mp);
778 778 if (error) {
779 /* 779 xfs_warn(mp, "Failed dir/attr init: %d", error);
780 * Initialize the attribute manager's entries. 780 goto out_remove_uuid;
781 */ 781 }
782 mp->m_attr_magicpct = (mp->m_sb.sb_blocksize * 37) / 100;
783 782
784 /* 783 /*
785 * Initialize the precomputed transaction reservations values. 784 * Initialize the precomputed transaction reservations values.
@@ -794,7 +793,7 @@ xfs_mountfs(
794 error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); 793 error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
795 if (error) { 794 if (error) {
796 xfs_warn(mp, "Failed per-ag init: %d", error); 795 xfs_warn(mp, "Failed per-ag init: %d", error);
797 goto out_remove_uuid; 796 goto out_free_dir;
798 } 797 }
799 798
800 if (!sbp->sb_logblocks) { 799 if (!sbp->sb_logblocks) {
@@ -969,6 +968,8 @@ xfs_mountfs(
969 xfs_wait_buftarg(mp->m_ddev_targp); 968 xfs_wait_buftarg(mp->m_ddev_targp);
970 out_free_perag: 969 out_free_perag:
971 xfs_free_perag(mp); 970 xfs_free_perag(mp);
971 out_free_dir:
972 xfs_da_unmount(mp);
972 out_remove_uuid: 973 out_remove_uuid:
973 xfs_uuid_unmount(mp); 974 xfs_uuid_unmount(mp);
974 out: 975 out:
@@ -1046,6 +1047,7 @@ xfs_unmountfs(
1046 "Freespace may not be correct on next mount."); 1047 "Freespace may not be correct on next mount.");
1047 1048
1048 xfs_log_unmount(mp); 1049 xfs_log_unmount(mp);
1050 xfs_da_unmount(mp);
1049 xfs_uuid_unmount(mp); 1051 xfs_uuid_unmount(mp);
1050 1052
1051#if defined(DEBUG) 1053#if defined(DEBUG)
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index a466c5e5826e..27cce7b4875d 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -27,6 +27,7 @@ struct xfs_nameops;
27struct xfs_ail; 27struct xfs_ail;
28struct xfs_quotainfo; 28struct xfs_quotainfo;
29struct xfs_dir_ops; 29struct xfs_dir_ops;
30struct xfs_da_geometry;
30 31
31#ifdef HAVE_PERCPU_SB 32#ifdef HAVE_PERCPU_SB
32 33
@@ -96,6 +97,8 @@ typedef struct xfs_mount {
96 uint m_readio_blocks; /* min read size blocks */ 97 uint m_readio_blocks; /* min read size blocks */
97 uint m_writeio_log; /* min write size log bytes */ 98 uint m_writeio_log; /* min write size log bytes */
98 uint m_writeio_blocks; /* min write size blocks */ 99 uint m_writeio_blocks; /* min write size blocks */
100 struct xfs_da_geometry *m_dir_geo; /* directory block geometry */
101 struct xfs_da_geometry *m_attr_geo; /* attribute block geometry */
99 struct xlog *m_log; /* log specific stuff */ 102 struct xlog *m_log; /* log specific stuff */
100 int m_logbufs; /* number of log buffers */ 103 int m_logbufs; /* number of log buffers */
101 int m_logbsize; /* size of each log buffer */ 104 int m_logbsize; /* size of each log buffer */